@saltcorn/server 1.3.1-beta.0 → 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 (406) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/auth/admin.js +9 -1
  3. package/auth/roleadmin.js +54 -1
  4. package/auth/routes.js +50 -5
  5. package/docs/assets/search.js +1 -1
  6. package/docs/classes/_saltcorn_common_code.Relation.html +10 -10
  7. package/docs/classes/_saltcorn_common_code.RelationsFinder.html +5 -5
  8. package/docs/classes/_saltcorn_data.models.Crash.html +17 -17
  9. package/docs/classes/_saltcorn_data.models.EventLog-1.html +19 -19
  10. package/docs/classes/_saltcorn_data.models.Field.html +74 -74
  11. package/docs/classes/_saltcorn_data.models.FieldRepeat.html +16 -16
  12. package/docs/classes/_saltcorn_data.models.File-1.html +48 -48
  13. package/docs/classes/_saltcorn_data.models.Form-1.html +39 -39
  14. package/docs/classes/_saltcorn_data.models.Library.html +13 -13
  15. package/docs/classes/_saltcorn_data.models.Page.html +24 -24
  16. package/docs/classes/_saltcorn_data.models.PageGroup-1.html +25 -25
  17. package/docs/classes/_saltcorn_data.models.Plugin.html +25 -25
  18. package/docs/classes/_saltcorn_data.models.Role.html +9 -9
  19. package/docs/classes/_saltcorn_data.models.Table-1.html +92 -92
  20. package/docs/classes/_saltcorn_data.models.TableConstraint.html +14 -14
  21. package/docs/classes/_saltcorn_data.models.Trigger.html +71 -39
  22. package/docs/classes/_saltcorn_data.models.User.html +51 -49
  23. package/docs/classes/_saltcorn_data.models.View-1.html +54 -54
  24. package/docs/classes/_saltcorn_data.models.Workflow.html +17 -17
  25. package/docs/classes/_saltcorn_data.models.WorkflowRun.html +35 -35
  26. package/docs/classes/_saltcorn_data.models.WorkflowStep.html +27 -27
  27. package/docs/classes/_saltcorn_data.models.WorkflowTrace.html +18 -18
  28. package/docs/classes/_saltcorn_mobile_builder.MobileBuilder.html +37 -37
  29. package/docs/enums/_saltcorn_common_code.RelationType.html +7 -7
  30. package/docs/enums/_saltcorn_common_code.ViewDisplayType.html +4 -4
  31. package/docs/functions/_saltcorn_admin_models.backup.create_backup.html +1 -1
  32. package/docs/functions/_saltcorn_admin_models.backup.create_csv_from_rows.html +1 -1
  33. package/docs/functions/_saltcorn_admin_models.backup.restore.html +1 -1
  34. package/docs/functions/_saltcorn_admin_models.pack.add_to_menu.html +1 -1
  35. package/docs/functions/_saltcorn_admin_models.pack.can_install_pack.html +1 -1
  36. package/docs/functions/_saltcorn_admin_models.pack.fetch_available_packs.html +1 -1
  37. package/docs/functions/_saltcorn_admin_models.pack.fetch_pack_by_name.html +1 -1
  38. package/docs/functions/_saltcorn_admin_models.pack.install_pack.html +1 -1
  39. package/docs/functions/_saltcorn_admin_models.pack.library_pack.html +1 -1
  40. package/docs/functions/_saltcorn_admin_models.pack.model_instance_pack.html +1 -1
  41. package/docs/functions/_saltcorn_admin_models.pack.model_pack.html +1 -1
  42. package/docs/functions/_saltcorn_admin_models.pack.page_group_pack.html +1 -1
  43. package/docs/functions/_saltcorn_admin_models.pack.page_pack.html +1 -1
  44. package/docs/functions/_saltcorn_admin_models.pack.plugin_pack.html +1 -1
  45. package/docs/functions/_saltcorn_admin_models.pack.role_pack.html +1 -1
  46. package/docs/functions/_saltcorn_admin_models.pack.table_pack.html +1 -1
  47. package/docs/functions/_saltcorn_admin_models.pack.trigger_pack.html +1 -1
  48. package/docs/functions/_saltcorn_admin_models.pack.uninstall_pack.html +1 -1
  49. package/docs/functions/_saltcorn_admin_models.pack.view_pack.html +1 -1
  50. package/docs/functions/_saltcorn_admin_models.tenant.copy_tenant_template.html +1 -1
  51. package/docs/functions/_saltcorn_admin_models.tenant.create_tenant.html +1 -1
  52. package/docs/functions/_saltcorn_admin_models.tenant.deleteTenant.html +1 -1
  53. package/docs/functions/_saltcorn_admin_models.tenant.domain_sanitize.html +1 -1
  54. package/docs/functions/_saltcorn_admin_models.tenant.eachTenant.html +1 -1
  55. package/docs/functions/_saltcorn_admin_models.tenant.getAllTenantRows.html +1 -1
  56. package/docs/functions/_saltcorn_admin_models.tenant.getAllTenants.html +1 -1
  57. package/docs/functions/_saltcorn_admin_models.tenant.insertTenant.html +1 -1
  58. package/docs/functions/_saltcorn_admin_models.tenant.switchToTenant.html +1 -1
  59. package/docs/functions/_saltcorn_common_code.buildTableCaches.html +1 -1
  60. package/docs/functions/_saltcorn_common_code.parseLegacyRelation.html +1 -1
  61. package/docs/functions/_saltcorn_common_code.parseRelationPath.html +1 -1
  62. package/docs/functions/_saltcorn_data.models.config.check_email_mask.html +1 -1
  63. package/docs/functions/_saltcorn_data.models.config.deleteConfig.html +1 -1
  64. package/docs/functions/_saltcorn_data.models.config.getAllConfig.html +1 -1
  65. package/docs/functions/_saltcorn_data.models.config.getConfig.html +1 -1
  66. package/docs/functions/_saltcorn_data.models.config.get_base_url.html +1 -1
  67. package/docs/functions/_saltcorn_data.models.config.get_latest_npm_version.html +1 -1
  68. package/docs/functions/_saltcorn_data.models.config.remove_from_menu.html +1 -1
  69. package/docs/functions/_saltcorn_data.models.config.save_menu_items.html +1 -1
  70. package/docs/functions/_saltcorn_data.models.config.setConfig.html +1 -1
  71. package/docs/functions/_saltcorn_data.models.discovery.discover_tables.html +1 -1
  72. package/docs/functions/_saltcorn_data.models.discovery.discoverable_tables.html +1 -1
  73. package/docs/functions/_saltcorn_data.models.discovery.findType.html +1 -1
  74. package/docs/functions/_saltcorn_data.models.discovery.get_existing_views.html +1 -1
  75. package/docs/functions/_saltcorn_data.models.discovery.implement_discovery.html +1 -1
  76. package/docs/functions/_saltcorn_data.models.email.getMailTransport.html +1 -1
  77. package/docs/functions/_saltcorn_data.models.email.send_verification_email.html +1 -1
  78. package/docs/functions/_saltcorn_data.models.email.viewToEmailHtml.html +1 -1
  79. package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields.html +1 -1
  80. package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields_stored.html +1 -1
  81. package/docs/functions/_saltcorn_data.models.expression.eval_expression.html +1 -1
  82. package/docs/functions/_saltcorn_data.models.expression.expressionValidator.html +1 -1
  83. package/docs/functions/_saltcorn_data.models.expression.get_async_expression_function.html +1 -1
  84. package/docs/functions/_saltcorn_data.models.expression.get_expression_function.html +1 -1
  85. package/docs/functions/_saltcorn_data.models.expression.jsexprToWhere.html +1 -1
  86. package/docs/functions/_saltcorn_data.models.expression.recalculate_for_stored.html +1 -1
  87. package/docs/functions/_saltcorn_data.models.expression.transform_for_async.html +1 -1
  88. package/docs/functions/_saltcorn_data.models.layout.eachView.html +1 -1
  89. package/docs/functions/_saltcorn_data.models.layout.getStringsForI18n.html +1 -1
  90. package/docs/functions/_saltcorn_data.models.layout.getViews.html +1 -1
  91. package/docs/functions/_saltcorn_data.models.layout.translateLayout.html +1 -1
  92. package/docs/functions/_saltcorn_data.models.layout.traverse.html +1 -1
  93. package/docs/functions/_saltcorn_data.models.layout.traverseSync.html +1 -1
  94. package/docs/functions/_saltcorn_data.models.random.all_views.html +1 -1
  95. package/docs/functions/_saltcorn_data.models.random.fill_table_row.html +1 -1
  96. package/docs/functions/_saltcorn_data.models.random.initial_view.html +1 -1
  97. package/docs/functions/_saltcorn_data.models.random.random_table.html +1 -1
  98. package/docs/functions/_saltcorn_db_common.buildInsertBulkSql.html +2 -1
  99. package/docs/functions/_saltcorn_db_common.buildInsertSql.html +2 -1
  100. package/docs/functions/_saltcorn_db_common.commitAndBeginNewTransaction.html +103 -0
  101. package/docs/functions/_saltcorn_db_common.doCount.html +2 -1
  102. package/docs/functions/_saltcorn_db_common.doDeleteWhere.html +2 -1
  103. package/docs/functions/_saltcorn_db_common.doListScTables.html +2 -1
  104. package/docs/functions/_saltcorn_db_common.doListTables.html +2 -1
  105. package/docs/functions/_saltcorn_db_common.doListUserDefinedTables.html +2 -1
  106. package/docs/functions/_saltcorn_db_common.do_add_index.html +2 -1
  107. package/docs/functions/_saltcorn_db_common.do_drop_index.html +2 -1
  108. package/docs/functions/_saltcorn_db_common.ftsFieldsSqlExpr.html +2 -1
  109. package/docs/functions/_saltcorn_db_common.mkSelectOptions.html +2 -1
  110. package/docs/functions/_saltcorn_db_common.mkVal.html +2 -1
  111. package/docs/functions/_saltcorn_db_common.mkWhere.html +2 -1
  112. package/docs/functions/_saltcorn_db_common.multi_tenant.enable_multi_tenant.html +2 -1
  113. package/docs/functions/_saltcorn_db_common.multi_tenant.getRequestContext.html +2 -1
  114. package/docs/functions/_saltcorn_db_common.multi_tenant.getTenantSchema.html +2 -1
  115. package/docs/functions/_saltcorn_db_common.multi_tenant.init.html +2 -1
  116. package/docs/functions/_saltcorn_db_common.multi_tenant.is_it_multi_tenant.html +2 -1
  117. package/docs/functions/_saltcorn_db_common.multi_tenant.runWithTenant.html +2 -1
  118. package/docs/functions/_saltcorn_db_common.orderByIsObject.html +2 -1
  119. package/docs/functions/_saltcorn_db_common.orderByIsOperator.html +2 -1
  120. package/docs/functions/_saltcorn_db_common.prefixFieldsInWhere.html +2 -1
  121. package/docs/functions/_saltcorn_db_common.reprAsJson.html +2 -1
  122. package/docs/functions/_saltcorn_db_common.slugify.html +2 -1
  123. package/docs/functions/_saltcorn_db_common.sqlBinOp.html +2 -1
  124. package/docs/functions/_saltcorn_db_common.sqlFun.html +2 -1
  125. package/docs/functions/_saltcorn_db_common.sqlsanitize.html +2 -1
  126. package/docs/functions/_saltcorn_db_common.sqlsanitizeAllowDots.html +2 -1
  127. package/docs/functions/_saltcorn_db_common.subSelectWhere.html +2 -1
  128. package/docs/functions/_saltcorn_db_common.tryCatchInTransaction.html +2 -1
  129. package/docs/functions/_saltcorn_db_common.withTransaction.html +2 -1
  130. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidFeatures.html +1 -1
  131. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidPermissions.html +1 -1
  132. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.buildTablesFile.html +1 -1
  133. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyPrepopulatedDb.html +1 -1
  134. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyServerFiles.html +1 -1
  135. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyShareExtFiles.html +1 -1
  136. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copySiteLogo.html +1 -1
  137. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyTranslationFiles.html +1 -1
  138. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.createSqliteDb.html +1 -1
  139. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.decodeProvisioningProfile.html +1 -1
  140. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.extractDomain.html +1 -1
  141. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.generateAndroidVersionCode.html +1 -1
  142. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyAndroidManifest.html +1 -1
  143. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyConfigXml.html +1 -1
  144. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyGradleConfig.html +1 -1
  145. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyInfoPlist.html +1 -1
  146. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyXcodeProjectFile.html +1 -1
  147. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepAppIcon.html +1 -1
  148. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareAppIcon.html +1 -1
  149. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareBuildDir.html +1 -1
  150. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareExportOptionsPlist.html +1 -1
  151. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashIcon.html +1 -1
  152. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashPage.html +1 -1
  153. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCapacitorConfig.html +1 -1
  154. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCfgFile.html +1 -1
  155. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeDataExtractionRules.html +1 -1
  156. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeNetworkSecurityConfig.html +1 -1
  157. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePodfile.html +1 -1
  158. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePrivacyInfo.html +1 -1
  159. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundleMobileAppCode.html +1 -1
  160. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundlePackagesAndPlugins.html +1 -1
  161. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyMobileAppDirs.html +1 -1
  162. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyPublicDirs.html +1 -1
  163. package/docs/functions/_saltcorn_sqlite.add_index.html +1 -1
  164. package/docs/functions/_saltcorn_sqlite.add_unique_constraint.html +1 -1
  165. package/docs/functions/_saltcorn_sqlite.begin.html +1 -1
  166. package/docs/functions/_saltcorn_sqlite.changeConnection.html +1 -1
  167. package/docs/functions/_saltcorn_sqlite.close.html +1 -1
  168. package/docs/functions/_saltcorn_sqlite.commit.html +1 -1
  169. package/docs/functions/_saltcorn_sqlite.count.html +1 -1
  170. package/docs/functions/_saltcorn_sqlite.deleteWhere.html +1 -1
  171. package/docs/functions/_saltcorn_sqlite.dropTable.html +1 -1
  172. package/docs/functions/_saltcorn_sqlite.dropTables.html +1 -1
  173. package/docs/functions/_saltcorn_sqlite.drop_index.html +1 -1
  174. package/docs/functions/_saltcorn_sqlite.drop_reset_schema.html +1 -1
  175. package/docs/functions/_saltcorn_sqlite.drop_unique_constraint.html +1 -1
  176. package/docs/functions/_saltcorn_sqlite.getVersion.html +1 -1
  177. package/docs/functions/_saltcorn_sqlite.get_db_filepath.html +1 -1
  178. package/docs/functions/_saltcorn_sqlite.get_sql_logging.html +1 -1
  179. package/docs/functions/_saltcorn_sqlite.init.html +1 -1
  180. package/docs/functions/_saltcorn_sqlite.insert.html +1 -1
  181. package/docs/functions/_saltcorn_sqlite.listScTables.html +1 -1
  182. package/docs/functions/_saltcorn_sqlite.listTables.html +1 -1
  183. package/docs/functions/_saltcorn_sqlite.listUserDefinedTables.html +1 -1
  184. package/docs/functions/_saltcorn_sqlite.query.html +1 -1
  185. package/docs/functions/_saltcorn_sqlite.rollback.html +1 -1
  186. package/docs/functions/_saltcorn_sqlite.select.html +1 -1
  187. package/docs/functions/_saltcorn_sqlite.selectMaybeOne.html +1 -1
  188. package/docs/functions/_saltcorn_sqlite.selectOne.html +1 -1
  189. package/docs/functions/_saltcorn_sqlite.set_sql_logging.html +1 -1
  190. package/docs/functions/_saltcorn_sqlite.sql_log.html +1 -1
  191. package/docs/functions/_saltcorn_sqlite.update.html +1 -1
  192. package/docs/functions/_saltcorn_sqlite.updateWhere.html +1 -1
  193. package/docs/functions/_saltcorn_sqlite_mobile.add_index.html +1 -1
  194. package/docs/functions/_saltcorn_sqlite_mobile.add_unique_constraint.html +1 -1
  195. package/docs/functions/_saltcorn_sqlite_mobile.count.html +1 -1
  196. package/docs/functions/_saltcorn_sqlite_mobile.deleteWhere.html +1 -1
  197. package/docs/functions/_saltcorn_sqlite_mobile.drop_index.html +1 -1
  198. package/docs/functions/_saltcorn_sqlite_mobile.drop_reset_schema.html +1 -1
  199. package/docs/functions/_saltcorn_sqlite_mobile.drop_unique_constraint.html +1 -1
  200. package/docs/functions/_saltcorn_sqlite_mobile.init.html +1 -1
  201. package/docs/functions/_saltcorn_sqlite_mobile.insert.html +1 -1
  202. package/docs/functions/_saltcorn_sqlite_mobile.insertRows.html +1 -1
  203. package/docs/functions/_saltcorn_sqlite_mobile.listScTables.html +1 -1
  204. package/docs/functions/_saltcorn_sqlite_mobile.listTables.html +1 -1
  205. package/docs/functions/_saltcorn_sqlite_mobile.listUserDefinedTables.html +1 -1
  206. package/docs/functions/_saltcorn_sqlite_mobile.query.html +1 -1
  207. package/docs/functions/_saltcorn_sqlite_mobile.select.html +1 -1
  208. package/docs/functions/_saltcorn_sqlite_mobile.selectMaybeOne.html +1 -1
  209. package/docs/functions/_saltcorn_sqlite_mobile.selectOne.html +1 -1
  210. package/docs/functions/_saltcorn_sqlite_mobile.setConnectionObject.html +1 -1
  211. package/docs/functions/_saltcorn_sqlite_mobile.tableExists.html +1 -1
  212. package/docs/functions/_saltcorn_sqlite_mobile.time.html +1 -1
  213. package/docs/functions/_saltcorn_sqlite_mobile.update.html +1 -1
  214. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_field.instanceOfField.html +1 -1
  215. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_page.instanceOfPage.html +1 -1
  216. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_view.instanceOfView.html +1 -1
  217. package/docs/functions/_saltcorn_types.Types.base_types.instanceOWithHtmlFile.html +1 -1
  218. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfErrorMsg.html +1 -1
  219. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfSuccessMsg.html +1 -1
  220. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfType.html +1 -1
  221. package/docs/functions/_saltcorn_types.generators.generateBool.html +1 -1
  222. package/docs/functions/_saltcorn_types.generators.generateString.html +1 -1
  223. package/docs/functions/_saltcorn_types.generators.num_between.html +1 -1
  224. package/docs/functions/_saltcorn_types.generators.oneOf.html +1 -1
  225. package/docs/interfaces/_saltcorn_mobile_builder.common_build_utils.ScCapacitorConfig.html +10 -10
  226. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractField.html +15 -15
  227. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractFieldRepeat.html +3 -3
  228. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_form.AbstractForm.html +27 -27
  229. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_page.AbstractPage.html +7 -7
  230. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_role.AbstractRole.html +3 -3
  231. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_table.AbstractTable.html +11 -11
  232. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_trigger.AbstractTrigger.html +38 -16
  233. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_view.AbstractView.html +10 -10
  234. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_workflow.AbstractWorkflow.html +13 -13
  235. package/docs/modules/_saltcorn_admin_models.backup.html +1 -1
  236. package/docs/modules/_saltcorn_admin_models.html +1 -1
  237. package/docs/modules/_saltcorn_admin_models.pack.html +1 -1
  238. package/docs/modules/_saltcorn_admin_models.tenant.html +1 -1
  239. package/docs/modules/_saltcorn_common_code.html +1 -1
  240. package/docs/modules/_saltcorn_data.html +3 -3
  241. package/docs/modules/_saltcorn_data.models.EventLog.html +2 -2
  242. package/docs/modules/_saltcorn_data.models.File.html +2 -2
  243. package/docs/modules/_saltcorn_data.models.Form.html +2 -2
  244. package/docs/modules/_saltcorn_data.models.PageGroup.html +2 -2
  245. package/docs/modules/_saltcorn_data.models.Table.html +2 -2
  246. package/docs/modules/_saltcorn_data.models.View.html +2 -2
  247. package/docs/modules/_saltcorn_data.models.config.html +1 -1
  248. package/docs/modules/_saltcorn_data.models.discovery.html +1 -1
  249. package/docs/modules/_saltcorn_data.models.email.html +1 -1
  250. package/docs/modules/_saltcorn_data.models.expression.html +1 -1
  251. package/docs/modules/_saltcorn_data.models.html +1 -1
  252. package/docs/modules/_saltcorn_data.models.layout.html +1 -1
  253. package/docs/modules/_saltcorn_data.models.random.html +1 -1
  254. package/docs/modules/_saltcorn_data.models.scheduler.html +1 -1
  255. package/docs/modules/_saltcorn_data.plugin_helper.html +1 -1
  256. package/docs/modules/_saltcorn_data.utils.html +3 -1
  257. package/docs/modules/_saltcorn_db_common.html +4 -2
  258. package/docs/modules/_saltcorn_db_common.multi_tenant.html +2 -1
  259. package/docs/modules/_saltcorn_markup.html +2 -2
  260. package/docs/modules/_saltcorn_mobile_builder.common_build_utils.html +1 -1
  261. package/docs/modules/_saltcorn_mobile_builder.html +1 -1
  262. package/docs/modules/_saltcorn_mobile_builder.package_bundle_utils.html +1 -1
  263. package/docs/modules/_saltcorn_sqlite.html +1 -1
  264. package/docs/modules/_saltcorn_sqlite_mobile.html +1 -1
  265. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_field.html +1 -1
  266. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_form.html +1 -1
  267. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_library.html +1 -1
  268. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_page.html +1 -1
  269. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_plugin.html +1 -1
  270. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_role.html +1 -1
  271. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_table.html +1 -1
  272. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_trigger.html +1 -1
  273. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_view.html +1 -1
  274. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_workflow.html +1 -1
  275. package/docs/modules/_saltcorn_types.ModelAbstracts.html +1 -1
  276. package/docs/modules/_saltcorn_types.Types.base_types.html +1 -1
  277. package/docs/modules/_saltcorn_types.Types.common_types.html +1 -1
  278. package/docs/modules/_saltcorn_types.Types.html +1 -1
  279. package/docs/modules/_saltcorn_types.generators.html +1 -1
  280. package/docs/modules/_saltcorn_types.html +1 -1
  281. package/docs/types/_saltcorn_data.models.EventLog.EventLogCfg.html +1 -1
  282. package/docs/types/_saltcorn_data.models.File.FileCfg.html +1 -1
  283. package/docs/types/_saltcorn_data.models.Form.AdditionalButton.html +1 -1
  284. package/docs/types/_saltcorn_data.models.Form.FormCfg.html +1 -1
  285. package/docs/types/_saltcorn_data.models.PageGroup.ScreenInfoParams.html +1 -1
  286. package/docs/types/_saltcorn_data.models.Table.ChildRelations.html +1 -1
  287. package/docs/types/_saltcorn_data.models.Table.ParentRelations.html +1 -1
  288. package/docs/types/_saltcorn_data.models.Table.RelationData.html +1 -1
  289. package/docs/types/_saltcorn_data.models.View.FindViewsPred.html +1 -1
  290. package/docs/types/_saltcorn_db_common.AggregationOptions.html +2 -1
  291. package/docs/types/_saltcorn_db_common.CoordOpts.html +2 -1
  292. package/docs/types/_saltcorn_db_common.DatabaseClient.html +2 -1
  293. package/docs/types/_saltcorn_db_common.JoinField.html +2 -1
  294. package/docs/types/_saltcorn_db_common.JoinFields.html +2 -1
  295. package/docs/types/_saltcorn_db_common.JoinOptions.html +2 -1
  296. package/docs/types/_saltcorn_db_common.JsonPath.html +2 -1
  297. package/docs/types/_saltcorn_db_common.JsonPathElem.html +2 -1
  298. package/docs/types/_saltcorn_db_common.Operator.html +2 -1
  299. package/docs/types/_saltcorn_db_common.PartialSome.html +2 -1
  300. package/docs/types/_saltcorn_db_common.PrimaryKeyValue.html +2 -1
  301. package/docs/types/_saltcorn_db_common.Row.html +2 -1
  302. package/docs/types/_saltcorn_db_common.SelectOptions.html +2 -1
  303. package/docs/types/_saltcorn_db_common.SqlAndValues.html +2 -1
  304. package/docs/types/_saltcorn_db_common.StrongRow.html +2 -1
  305. package/docs/types/_saltcorn_db_common.SubselectOptions.html +2 -1
  306. package/docs/types/_saltcorn_db_common.Value.html +2 -1
  307. package/docs/types/_saltcorn_db_common.Where.html +2 -1
  308. package/docs/types/_saltcorn_mobile_builder.IosCfg.html +1 -1
  309. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.FieldCfg.html +1 -1
  310. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.InputType.html +1 -1
  311. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_form.AdditionalButton.html +1 -1
  312. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryCfg.html +1 -1
  313. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryPack.html +1 -1
  314. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PageCfg.html +1 -1
  315. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PagePack.html +1 -1
  316. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginCfg.html +1 -1
  317. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginPack.html +1 -1
  318. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RoleCfg.html +1 -1
  319. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RolePack.html +1 -1
  320. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TableCfg.html +1 -1
  321. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TablePack.html +1 -1
  322. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerCfg.html +1 -1
  323. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerPack.html +1 -1
  324. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewCfg.html +1 -1
  325. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewPack.html +1 -1
  326. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.ConfigWorkflowStep.html +1 -1
  327. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.RunResult.html +1 -1
  328. package/docs/types/_saltcorn_types.Types.base_types.Action.html +11 -3
  329. package/docs/types/_saltcorn_types.Types.base_types.AuthenticationMethod.html +1 -1
  330. package/docs/types/_saltcorn_types.Types.base_types.CalcJoinfield.html +1 -1
  331. package/docs/types/_saltcorn_types.Types.base_types.CapacitorPlugin.html +1 -1
  332. package/docs/types/_saltcorn_types.Types.base_types.CodePagePack.html +1 -1
  333. package/docs/types/_saltcorn_types.Types.base_types.Column.html +1 -1
  334. package/docs/types/_saltcorn_types.Types.base_types.ConnectObjType.html +4 -2
  335. package/docs/types/_saltcorn_types.Types.base_types.ConnectedObjects.html +1 -1
  336. package/docs/types/_saltcorn_types.Types.base_types.CopilotSkill.html +1 -1
  337. package/docs/types/_saltcorn_types.Types.base_types.ErrorObj.html +1 -1
  338. package/docs/types/_saltcorn_types.Types.base_types.FieldLike.html +1 -1
  339. package/docs/types/_saltcorn_types.Types.base_types.FieldView.html +1 -1
  340. package/docs/types/_saltcorn_types.Types.base_types.Header.html +1 -1
  341. package/docs/types/_saltcorn_types.Types.base_types.JoinFieldOption.html +1 -1
  342. package/docs/types/_saltcorn_types.Types.base_types.Layout.html +1 -1
  343. package/docs/types/_saltcorn_types.Types.base_types.MobileConfig.html +1 -1
  344. package/docs/types/_saltcorn_types.Types.base_types.ModelPattern.html +1 -1
  345. package/docs/types/_saltcorn_types.Types.base_types.Pack.html +1 -1
  346. package/docs/types/_saltcorn_types.Types.base_types.Plugin.html +1 -1
  347. package/docs/types/_saltcorn_types.Types.base_types.PluginFunction.html +1 -1
  348. package/docs/types/_saltcorn_types.Types.base_types.PluginLayout.html +1 -1
  349. package/docs/types/_saltcorn_types.Types.base_types.PluginRoute.html +1 -1
  350. package/docs/types/_saltcorn_types.Types.base_types.PluginSourceType.html +1 -1
  351. package/docs/types/_saltcorn_types.Types.base_types.PluginType.html +1 -1
  352. package/docs/types/_saltcorn_types.Types.base_types.PluginWrap.html +1 -1
  353. package/docs/types/_saltcorn_types.Types.base_types.PluginWrapArg.html +1 -1
  354. package/docs/types/_saltcorn_types.Types.base_types.RelationOption.html +1 -1
  355. package/docs/types/_saltcorn_types.Types.base_types.Req.html +1 -1
  356. package/docs/types/_saltcorn_types.Types.base_types.Res.html +1 -1
  357. package/docs/types/_saltcorn_types.Types.base_types.ResultType.html +1 -1
  358. package/docs/types/_saltcorn_types.Types.base_types.RouteAction.html +1 -1
  359. package/docs/types/_saltcorn_types.Types.base_types.RunExtra.html +1 -1
  360. package/docs/types/_saltcorn_types.Types.base_types.SlugStepType.html +1 -1
  361. package/docs/types/_saltcorn_types.Types.base_types.StepResType.html +1 -1
  362. package/docs/types/_saltcorn_types.Types.base_types.SubField.html +1 -1
  363. package/docs/types/_saltcorn_types.Types.base_types.TableProvider.html +1 -1
  364. package/docs/types/_saltcorn_types.Types.base_types.TableQuery.html +1 -1
  365. package/docs/types/_saltcorn_types.Types.base_types.Tablely.html +1 -1
  366. package/docs/types/_saltcorn_types.Types.base_types.ViewTemplate.html +1 -1
  367. package/docs/types/_saltcorn_types.Types.common_types.ErrorMessage.html +1 -1
  368. package/docs/types/_saltcorn_types.Types.common_types.GenObj.html +1 -1
  369. package/docs/types/_saltcorn_types.Types.common_types.ReqRes.html +1 -1
  370. package/docs/types/_saltcorn_types.Types.common_types.ResultMessage.html +1 -1
  371. package/docs/types/_saltcorn_types.Types.common_types.SuccessMessage.html +1 -1
  372. package/docs/types/_saltcorn_types.Types.common_types.Type.html +1 -1
  373. package/docs/variables/_saltcorn_data.db.html +1 -1
  374. package/docs/variables/_saltcorn_data.migrations.html +1 -1
  375. package/docs/variables/_saltcorn_data.models.config.available_languages.html +1 -1
  376. package/docs/variables/_saltcorn_data.models.config.configTypes.html +1 -1
  377. package/docs/variables/_saltcorn_data.models.scheduler.runScheduler.html +1 -1
  378. package/docs/variables/_saltcorn_data.plugin_helper.run_action_column.html +1 -1
  379. package/docs/variables/_saltcorn_data.utils.NotAuthorized.html +2 -1
  380. package/docs/variables/_saltcorn_data.utils.isPushEnabled.html +67 -0
  381. package/docs/variables/_saltcorn_data.utils.sleep.html +2 -1
  382. package/docs/variables/_saltcorn_db_common.multi_tenant.tenantNamespace.html +2 -1
  383. package/help/JavaScript action code.tmd +10 -0
  384. package/locales/en.json +32 -1
  385. package/package.json +9 -9
  386. package/public/log_viewer_utils.js +3 -2
  387. package/public/saltcorn-common.js +100 -31
  388. package/public/saltcorn.css +16 -0
  389. package/public/saltcorn.js +8 -0
  390. package/routes/actions.js +17 -1
  391. package/routes/admin.js +5 -3
  392. package/routes/common_lists.js +8 -1
  393. package/routes/eventlog.js +20 -0
  394. package/routes/fields.js +10 -2
  395. package/routes/menu.js +98 -6
  396. package/routes/notifications.js +39 -11
  397. package/routes/page.js +4 -1
  398. package/routes/pageedit.js +4 -1
  399. package/routes/plugins.js +8 -7
  400. package/routes/tables.js +11 -0
  401. package/routes/view.js +12 -3
  402. package/serve.js +76 -21
  403. package/tests/admin.test.js +3 -3
  404. package/tests/auth.test.js +1 -0
  405. package/tests/viewedit.test.js +2 -0
  406. package/wrapper.js +26 -193
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 = () => {
@@ -32,14 +32,19 @@ router.use(
32
32
  })
33
33
  );
34
34
 
35
- const notificationSettingsForm = () => {
35
+ const notificationSettingsForm = (user) => {
36
36
  const fields = [{ name: "notify_email", label: "Email", type: "Bool" }];
37
- if (getState().getConfig("enable_push_notify", false))
38
- fields.push({
39
- name: "notify_push",
40
- label: "Push",
41
- type: "Bool",
42
- });
37
+ if (getState().getConfig("enable_push_notify", false)) {
38
+ const policyByRole = getState()?.getConfig("push_policy_by_role") || {};
39
+ const pushPolicy = policyByRole[user?.role_id || 100] || "Default on";
40
+ if (!["Always", "Never"].includes(pushPolicy)) {
41
+ fields.push({
42
+ name: "notify_push",
43
+ label: "Push",
44
+ type: "Bool",
45
+ });
46
+ }
47
+ }
43
48
 
44
49
  return new Form({
45
50
  action: `/notifications/settings`,
@@ -74,12 +79,23 @@ router.get(
74
79
  }
75
80
  );
76
81
 
77
- const form = notificationSettingsForm();
82
+ const form = notificationSettingsForm(req.user);
78
83
  const user = await User.findOne({ id: req.user?.id });
79
84
  form.values = {
80
85
  notify_email: user?._attributes?.notify_email,
81
- notify_push: user?._attributes?.notify_push,
82
86
  };
87
+
88
+ if (getState().getConfig("enable_push_notify", false)) {
89
+ let notifPushAttr = user?._attributes?.notify_push;
90
+ if (notifPushAttr === undefined) {
91
+ const policyByRole = getState()?.getConfig("push_policy_by_role") || {};
92
+ const pushPolicy = policyByRole[user.role_id || 100] || "Default on";
93
+ if (pushPolicy === "Default on") notifPushAttr = true;
94
+ else if (pushPolicy === "Default off") notifPushAttr = false;
95
+ }
96
+ form.values.notify_push = notifPushAttr;
97
+ }
98
+
83
99
  const notifyCards = nots.length
84
100
  ? nots.map((not) => ({
85
101
  type: "card",
@@ -193,11 +209,23 @@ router.post(
193
209
  loggedIn,
194
210
  error_catcher(async (req, res) => {
195
211
  const user = await User.findOne({ id: req.user.id });
196
- const form = notificationSettingsForm();
212
+ const form = notificationSettingsForm(req.user);
197
213
  form.validate(req.body || {});
198
214
  const _attributes = { ...user._attributes, ...form.values };
215
+
216
+ // apply push enabled policy if needed
217
+ if (getState().getConfig("enable_push_notify", false)) {
218
+ const policyByRole = getState()?.getConfig("push_policy_by_role") || {};
219
+ const pushPolicy = policyByRole[user.role_id || 100] || "Default on";
220
+ if (pushPolicy === "Always") _attributes.notify_push = true;
221
+ else if (pushPolicy === "Never") _attributes.notify_push = false;
222
+ else if (_attributes.notify_push === undefined) {
223
+ _attributes.notify_push = pushPolicy === "Default on";
224
+ }
225
+ }
226
+
199
227
  await user.update({ _attributes });
200
- const pushEnabled = !!_attributes.notify_push;
228
+ const pushEnabled = _attributes.notify_push;
201
229
  const allSubs = getState().getConfig("push_notification_subscriptions", {});
202
230
  const newSubs = { ...allSubs };
203
231
  if (!pushEnabled && newSubs[req.user.id]) {
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(
@@ -174,7 +174,9 @@ const pageBuilderData = async (req, context) => {
174
174
  const actions = [
175
175
  "GoBack",
176
176
  ...Object.entries(stateActions)
177
- .filter(([k, v]) => !v.requireRow && !v.disableInBuilder)
177
+ .filter(
178
+ ([k, v]) => !v.requireRow && !v.disableInBuilder && !v.disableIf?.()
179
+ )
178
180
  .map(([k, v]) => k),
179
181
  ];
180
182
  const triggers = await Trigger.find({
@@ -199,6 +201,7 @@ const pageBuilderData = async (req, context) => {
199
201
  const actionsNotRequiringRow = Trigger.action_options({
200
202
  notRequireRow: true,
201
203
  apiNeverTriggers: true,
204
+ forBuilder: true,
202
205
  builtInLabel: "Page Actions",
203
206
  builtIns: ["GoBack"],
204
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
@@ -209,7 +209,6 @@ const initMaster = async ({ disableMigrate }, useClusterAdaptor = true) => {
209
209
  const state = getState();
210
210
  if (state) {
211
211
  await state.setConfig("joined_log_socket_ids", []);
212
- await state.setConfig("joined_real_time_socket_ids", []);
213
212
  }
214
213
  });
215
214
  if (useClusterAdaptor) setupPrimary();
@@ -291,7 +290,8 @@ const onMessageFromWorker =
291
290
  ///ie from saltcorn
292
291
  //broadcast
293
292
  Object.entries(cluster.workers).forEach(([wpid, w]) => {
294
- 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);
295
295
  });
296
296
  workerDispatchMsg(msg); //also master
297
297
  return true;
@@ -383,6 +383,13 @@ module.exports =
383
383
  masterState.listeningTo.add(id);
384
384
  }
385
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
+
386
393
  if (masterState.listeningTo.size < useNCpus)
387
394
  setTimeout(initMasterListeners, 250);
388
395
  };
@@ -421,12 +428,21 @@ module.exports =
421
428
 
422
429
  if (forkAnyWorkers) {
423
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
+ };
424
437
 
425
438
  cluster.on("exit", (worker, code, signal) => {
426
439
  console.log(`worker ${worker.process.pid} died`);
427
440
  addWorker(cluster.fork());
428
441
  });
429
442
  } else {
443
+ getState().sendMessageToWorkers = (msg) => {
444
+ workerDispatchMsg(msg); //also master
445
+ };
430
446
  await nonGreenlockWorkerSetup(appargs, port, host);
431
447
  runScheduler({
432
448
  port,
@@ -545,11 +561,26 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
545
561
  .emit("log_msg", { text: msg, time, level });
546
562
  });
547
563
 
548
- // Real-time collaboration emitter
564
+ // Real-time collaboration emitter (tied to views)
549
565
  getState().setCollabEmitter((tenant, type, data) => {
550
566
  io.of("/").to(`_${tenant}_collab_room_`).emit(type, data);
551
567
  });
552
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
+
553
584
  io.of("/").on("connection", (socket) => {
554
585
  socket.on("join_room", ([viewname, room_id]) => {
555
586
  const ten = get_tenant_from_req(socket.request) || "public";
@@ -597,7 +628,7 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
597
628
  callback({ status: "error", msg: err.message || "unknown error" });
598
629
  }
599
630
  };
600
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
631
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
601
632
  else await f();
602
633
  });
603
634
 
@@ -614,13 +645,6 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
614
645
  if (view.min_role < role_id)
615
646
  throw new Error("Not authorized to join collaboration room");
616
647
  socket.join(`_${tenant}_collab_room_`);
617
- const socketIds = await getState().getConfig(
618
- "joined_real_time_socket_ids"
619
- );
620
- socketIds.push(socket.id);
621
- await getState().setConfig("joined_real_time_socket_ids", [
622
- ...socketIds,
623
- ]);
624
648
  if (typeof callback === "function") callback({ status: "ok" });
625
649
  } catch (err) {
626
650
  getState().log(1, `Socket join_collab_room: ${err.stack}`);
@@ -628,7 +652,30 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
628
652
  callback({ status: "error", msg: err.message || "unknown error" });
629
653
  }
630
654
  };
631
- 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);
632
679
  else await f();
633
680
  });
634
681
 
@@ -636,12 +683,20 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
636
683
  const tenant =
637
684
  get_tenant_from_req(socket.request, subdomainOffset) || "public";
638
685
  const f = async () => {
639
- const socketIds = await getState().getConfig("joined_log_socket_ids");
640
- const newSocketIds = socketIds.filter((id) => id !== socket.id);
641
- 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
+ }
642
697
  };
643
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
644
- else f();
698
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
699
+ else await f();
645
700
  });
646
701
  });
647
702
 
@@ -689,8 +744,8 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
689
744
  callback({ status: "error", msg: err.message || "unknown error" });
690
745
  }
691
746
  };
692
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
693
- else f();
747
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
748
+ else await f();
694
749
  }
695
750
  );
696
751
  socket.on("write_to_stream", async (data, callback) => {
@@ -752,8 +807,8 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
752
807
  }
753
808
  });
754
809
  };
755
- if (tenant && tenant !== "public") db.runWithTenant(tenant, f);
756
- else f();
810
+ if (tenant && tenant !== "public") await db.runWithTenant(tenant, f);
811
+ else await f();
757
812
  });
758
813
  });
759
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)
@@ -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
  });