@saltcorn/server 1.6.0-beta.5 → 1.6.0-beta.7
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.
- package/CHANGELOG.md +14 -0
- package/app.js +9 -5
- package/auth/routes.js +2 -1
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/_saltcorn_admin-models.models_snapshot.Snapshot.html +2 -2
- package/docs/classes/_saltcorn_common-code.relations_relation.Relation.html +3 -3
- package/docs/classes/_saltcorn_common-code.relations_relations_finder.RelationsFinder.html +5 -5
- package/docs/classes/_saltcorn_data.diagram_cy_raster.CytoscapeRaster.html +4 -4
- package/docs/classes/_saltcorn_data.diagram_nodes_dummy_node.DummyNode.html +4 -4
- package/docs/classes/_saltcorn_data.diagram_nodes_node.Node.html +4 -4
- package/docs/classes/_saltcorn_data.diagram_nodes_page_node.PageNode.html +4 -4
- package/docs/classes/_saltcorn_data.diagram_nodes_table_node.TableNode.html +4 -4
- package/docs/classes/_saltcorn_data.diagram_nodes_trigger_node.TriggerNode.html +4 -4
- package/docs/classes/_saltcorn_data.diagram_nodes_view_node.ViewNode.html +4 -4
- package/docs/classes/_saltcorn_data.mobile-mocks_node_async_hooks.AsyncLocalStorage.html +2 -2
- package/docs/classes/_saltcorn_data.models_crash.Crash.html +2 -2
- package/docs/classes/_saltcorn_data.models_eventlog.EventLog.html +2 -2
- package/docs/classes/_saltcorn_data.models_field.Field.html +9 -9
- package/docs/classes/_saltcorn_data.models_fieldrepeat.FieldRepeat.html +2 -2
- package/docs/classes/_saltcorn_data.models_file.File.html +21 -21
- package/docs/classes/_saltcorn_data.models_form.Form.html +2 -2
- package/docs/classes/_saltcorn_data.models_internal_mail_queue.MailQueue.html +4 -4
- package/docs/classes/_saltcorn_data.models_internal_push_message_helper.PushMessageHelper.html +7 -7
- package/docs/classes/_saltcorn_data.models_library.Library.html +2 -2
- package/docs/classes/_saltcorn_data.models_model.Model.html +2 -2
- package/docs/classes/_saltcorn_data.models_model_instance.ModelInstance.html +2 -2
- package/docs/classes/_saltcorn_data.models_notification.Notification.html +2 -2
- package/docs/classes/_saltcorn_data.models_page.Page.html +11 -11
- package/docs/classes/_saltcorn_data.models_page_group.PageGroup.html +16 -16
- package/docs/classes/_saltcorn_data.models_page_group_member.PageGroupMember.html +8 -8
- package/docs/classes/_saltcorn_data.models_plugin.Plugin.html +17 -16
- package/docs/classes/_saltcorn_data.models_role.Role.html +2 -2
- package/docs/classes/_saltcorn_data.models_table.Table.html +66 -66
- package/docs/classes/_saltcorn_data.models_table_constraints.TableConstraint.html +2 -2
- package/docs/classes/_saltcorn_data.models_tag.Tag.html +2 -2
- package/docs/classes/_saltcorn_data.models_tag_entry.TagEntry.html +2 -2
- package/docs/classes/_saltcorn_data.models_trigger.Trigger.html +19 -19
- package/docs/classes/_saltcorn_data.models_user.User.html +32 -32
- package/docs/classes/_saltcorn_data.models_view.View.html +15 -15
- package/docs/classes/_saltcorn_data.models_workflow.Workflow.html +2 -2
- package/docs/classes/_saltcorn_data.models_workflow_run.WorkflowRun.html +2 -2
- package/docs/classes/_saltcorn_data.models_workflow_step.WorkflowStep.html +2 -2
- package/docs/classes/_saltcorn_data.models_workflow_trace.MetaData.html +2 -2
- package/docs/classes/_saltcorn_data.models_workflow_trace.WorkflowTrace.html +2 -2
- package/docs/classes/_saltcorn_mobile-builder.mobile-builder.MobileBuilder.html +2 -3
- package/docs/classes/_saltcorn_mobile-builder.utils_capacitor-helper.CapacitorHelper.html +2 -2
- package/docs/enums/_saltcorn_common-code.relations_relation_types.RelationType.html +2 -2
- package/docs/enums/_saltcorn_common-code.relations_relation_types.ViewDisplayType.html +2 -2
- package/docs/functions/_saltcorn_admin-models.models_config-check.runConfigurationCheck.html +1 -1
- package/docs/functions/_saltcorn_common-code.relations_relation_helpers.buildRelationPath.html +1 -1
- package/docs/functions/_saltcorn_common-code.relations_relation_helpers.buildTableCaches.html +1 -1
- package/docs/functions/_saltcorn_common-code.relations_relation_helpers.parseLegacyRelation.html +1 -1
- package/docs/functions/_saltcorn_common-code.relations_relation_helpers.parseRelationPath.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.fixturesData.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.withAnotherUserField.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.withKeyFromLayerThree.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.withKeyFromLayerTwo.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.withMultipleInbounds.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.withSecondTopicField.html +1 -1
- package/docs/functions/_saltcorn_common-code.tests_test_data.withSimplePostTopicrelation.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.action_link.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.action_url.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.fill_presets.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.getForm.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.get_view_link_query.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.get_viewable_fields.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.get_viewable_fields_from_layout.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.make_link.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.objToQueryString.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.parse_view_select.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.setDateLocales.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.splitUniques.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.standardBlockDispatch.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.standardLayoutRowVisitor.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.transformForm.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.updateViewSelect.html +1 -1
- package/docs/functions/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.view_linker.html +1 -1
- package/docs/functions/_saltcorn_data.db_connect_mobile.getConnectObject.html +1 -1
- package/docs/functions/_saltcorn_data.db_reset_schema.reset.html +1 -1
- package/docs/functions/_saltcorn_data.diagram_cy_generate_utils.generateCyCode.html +1 -1
- package/docs/functions/_saltcorn_data.diagram_cy_generate_utils.genereateCyCfg.html +1 -1
- package/docs/functions/_saltcorn_data.diagram_node_extract_utils.buildObjectTrees.html +1 -1
- package/docs/functions/_saltcorn_data.diagram_node_extract_utils.extractFromColumns.html +1 -1
- package/docs/functions/_saltcorn_data.diagram_node_extract_utils.extractFromLayout.html +1 -1
- package/docs/functions/_saltcorn_data.diagram_node_extract_utils.extractViewToCreate.html +1 -1
- package/docs/functions/_saltcorn_data.migrate.create_blank_migration.html +1 -1
- package/docs/functions/_saltcorn_data.migrate.getMigrationsInDB.html +1 -1
- package/docs/functions/_saltcorn_data.migrate.migrate.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202102091312.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202210051058.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202210101540.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202304281224.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202307211459.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202502131103.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202508011455.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202510152058.js.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202603101553.sql_pg.html +1 -1
- package/docs/functions/_saltcorn_data.migrations_202604111200.js.html +1 -0
- package/docs/functions/_saltcorn_data.migrations_202604141200.js.html +1 -0
- package/docs/functions/_saltcorn_data.mobile-mocks_node_child_process.execSync.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs.createReadStream.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs.readdirSync.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs.writeFileSync.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.mkdir.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.readFile.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.readdir.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.stat.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.unlink.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_fs_promises.writeFile.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_latest-version.latestVersion.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_v8.deserialize.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_node_v8.serialize.html +1 -1
- package/docs/functions/_saltcorn_data.mobile-mocks_npm_env-paths.envPaths.html +1 -1
- package/docs/functions/_saltcorn_data.model-helper.get_predictor.html +1 -1
- package/docs/functions/_saltcorn_data.model-helper.run_jupyter_model.html +1 -1
- package/docs/functions/_saltcorn_data.model-helper.shorten_trackback.html +1 -1
- package/docs/functions/_saltcorn_data.model-helper.write_csv.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_async_json_stream.async_json_stream.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_query.aggregation_query_fields.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_query.getAggAndField.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_query.joinfield_renamer.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_query.process_aggregations.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.buildKeyFromRelative.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.copyObject.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.deleteObject.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.downloadBuffer.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getPublicFileUrl.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getResolvedBucket.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getS3Client.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getServeUrl.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.getSignedFileUrl.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.headObject.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.isS3Enabled.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.listS3Folder.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.publicUrlToRelativePath.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.relativeKeyToPath.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.setObjectMetadata.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_s3_helpers.uploadBuffer.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_table_helper.boolExamples.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_table_helper.colorExamples.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_table_helper.floatExamples.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_table_helper.get_formula_examples.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_table_helper.intExamples.html +1 -1
- package/docs/functions/_saltcorn_data.models_internal_table_helper.stringExamples.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.build_schema_data.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.calcfldViewConfig.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.calcfldViewOptions.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.calcrelViewOptions.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.displayType.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.field_picker_fields.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.generate_joined_query.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.getActionConfigFields.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.get_child_views.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.get_inbound_relation_opts.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.get_inbound_self_relation_opts.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.get_link_view_opts.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.get_many_to_many_relation_opts.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.get_parent_views.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.initial_config_all_fields.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.json_list_to_external_table.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.link_view.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.pathToState.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.picked_fields_to_query.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.readState.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.readStateStrict.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.runCollabEvents.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.run_action_column.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.stateFieldsToQuery.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.stateFieldsToWhere.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.stateToQueryString.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-helper.strictParseInt.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-testing.auto_test_plugin.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-testing.check_view_columns.html +1 -1
- package/docs/functions/_saltcorn_data.plugin-testing.generate_attributes.html +1 -1
- package/docs/functions/_saltcorn_data.standard-menu.create_standard_menu.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertIsErrorMsg.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertIsErrorsMsg.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertIsRow.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertIsSet.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertIsType.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertsIsSuccessMessage.html +1 -1
- package/docs/functions/_saltcorn_data.tests_assertions.assertsObjectIsUser.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.createAnotherUserField.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.createKeyFromLevelTwo.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.createLevelThreeInbound.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.createMultipleInbounds.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.createSecondTopicField.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.prepareEmployeeDepartment.html +1 -1
- package/docs/functions/_saltcorn_data.tests_common_helpers.prepareSimpleTopicPostRelation.html +1 -1
- package/docs/functions/_saltcorn_data.tests_remote_query_helper.deleteViewFromServer.html +1 -1
- package/docs/functions/_saltcorn_data.tests_remote_query_helper.prepareQueryEnviroment.html +1 -1
- package/docs/functions/_saltcorn_data.tests_remote_query_helper.sendViewToServer.html +1 -1
- package/docs/functions/_saltcorn_data.translate.hasLLM.html +1 -1
- package/docs/functions/_saltcorn_data.translate.translate.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.ftsFieldsSqlExpr.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.mkSelectOptions.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.mkWhere.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.orderByIsObject.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.orderByIsOperator.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.prefixFieldsInWhere.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.sqlBinOp.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.sqlFun.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.sqlsanitize.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.sqlsanitizeAllowDots.html +1 -1
- package/docs/functions/_saltcorn_db-common.internal.subSelectWhere.html +1 -1
- package/docs/functions/_saltcorn_db-common.multi-tenant.enable_multi_tenant.html +1 -1
- package/docs/functions/_saltcorn_db-common.multi-tenant.getRequestContext.html +1 -1
- package/docs/functions/_saltcorn_db-common.multi-tenant.getTenantSchema.html +1 -1
- package/docs/functions/_saltcorn_db-common.multi-tenant.init.html +1 -1
- package/docs/functions/_saltcorn_db-common.multi-tenant.is_it_multi_tenant.html +1 -1
- package/docs/functions/_saltcorn_db-common.multi-tenant.runWithTenant.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.buildInsertBulkSql.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.buildInsertSql.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.commitAndBeginNewTransaction.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.doCount.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.doDeleteWhere.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.doListScTables.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.doListTables.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.doListUserDefinedTables.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.do_add_index.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.do_drop_index.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.mkVal.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.openOrUseTransaction.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.reprAsJson.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.slugify.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.tryCatchInTransaction.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.whenTransactionisFree.html +1 -1
- package/docs/functions/_saltcorn_db-common.sqlite-commons.withTransaction.html +1 -1
- package/docs/functions/_saltcorn_markup.mktag.mkTag.html +1 -1
- package/docs/functions/_saltcorn_markup.tabs.tabs.html +1 -1
- package/docs/functions/_saltcorn_markup.workflow.renderWorkflow.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.androidFeatures.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.androidPermissions.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.buildTablesFile.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyPrepopulatedDb.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyServerFiles.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyShareExtFiles.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copySiteLogo.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.copyTranslationFiles.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.createSqliteDb.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.extractDomain.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.generateAndroidVersionCode.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.hasAuthMethod.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyAndroidManifest.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyAppDelegate.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyConfigXml.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyGradleConfig.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyInfoPlist.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyShareViewController.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.modifyXcodeProjectFile.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepAppIcon.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareAppIcon.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareBuildDir.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareExportOptionsPlist.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareSplashIcon.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.prepareSplashPage.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.runAddEntitlementsScript.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeCapacitorConfig.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeCfgFile.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeDataExtractionRules.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeEntitlementsPlist.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writeNetworkSecurityConfig.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writePodfile.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_common-build-utils.writePrivacyInfo.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.bundleMobileAppCode.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.bundlePackagesAndPlugins.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.copyOptionalSource.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.copyPluginMobileAppDirs.html +1 -1
- package/docs/functions/_saltcorn_mobile-builder.utils_package-bundle-utils.copyPublicDirs.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.add_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.add_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.count.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.deleteWhere.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.drop_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.drop_reset_schema.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.drop_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.init.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.insert.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.insertRows.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.listScTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.listTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.listUserDefinedTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.query.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.select.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.selectMaybeOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.selectOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.setConnectionObject.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.tableExists.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.time.html +1 -1
- package/docs/functions/_saltcorn_sqlite-mobile.sqlite_capacitor.update.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.add_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.add_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.begin.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.changeConnection.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.close.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.commit.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.count.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.deleteWhere.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.dropTable.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.dropTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.drop_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.drop_reset_schema.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.drop_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.getVersion.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.get_db_filepath.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.get_sql_logging.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.init.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.insert.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.listScTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.listTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.listUserDefinedTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.query.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.rollback.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.select.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.selectMaybeOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.selectOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.set_sql_logging.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.sql_log.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.update.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sqlite.updateWhere.html +1 -1
- package/docs/functions/_saltcorn_types.base_types.instanceOWithHtmlFile.html +1 -1
- package/docs/functions/_saltcorn_types.base_types.instanceOfFieldViewEdit.html +1 -1
- package/docs/functions/_saltcorn_types.base_types.instanceOfFieldViewShow.html +1 -1
- package/docs/functions/_saltcorn_types.base_types.instanceOfPack.html +1 -1
- package/docs/functions/_saltcorn_types.common_types.instanceOfErrorMsg.html +1 -1
- package/docs/functions/_saltcorn_types.common_types.instanceOfSuccessMsg.html +1 -1
- package/docs/functions/_saltcorn_types.common_types.instanceOfType.html +1 -1
- package/docs/functions/_saltcorn_types.model-abstracts_abstract_field.instanceOfField.html +1 -1
- package/docs/functions/_saltcorn_types.model-abstracts_abstract_page.instanceOfPage.html +1 -1
- package/docs/functions/_saltcorn_types.model-abstracts_abstract_plugin.instanceOfPlugin.html +1 -1
- package/docs/functions/_saltcorn_types.model-abstracts_abstract_table.instanceOfTable.html +1 -1
- package/docs/functions/_saltcorn_types.model-abstracts_abstract_view.instanceOfView.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/interfaces/_saltcorn_db-common.dbtypes.UserLike.html +2 -2
- package/docs/interfaces/_saltcorn_markup.types.TagExports.html +2 -2
- package/docs/interfaces/_saltcorn_mobile-builder.utils_common-build-utils.ScCapacitorConfig.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_field.AbstractField.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_field.AbstractFieldRepeat.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_form.AbstractForm.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_page.AbstractPage.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_page_group.AbstractPageGroup.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_page_group_member.AbstractPageGroupMember.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_plugin.AbstractPlugin.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_role.AbstractRole.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_table.AbstractTable.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_tag.AbstractTag.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_tag_entry.AbstractTagEntry.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_trigger.AbstractTrigger.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_user.AbstractUser.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_user.ForUserRequest.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_view.AbstractView.html +2 -2
- package/docs/interfaces/_saltcorn_types.model-abstracts_abstract_workflow.AbstractWorkflow.html +2 -2
- package/docs/modules/_saltcorn_data.html +1 -1
- package/docs/modules/_saltcorn_data.migrations_202604111200.html +1 -1
- package/docs/modules/_saltcorn_data.migrations_202604141200.html +1 -0
- package/docs/types/_saltcorn_data.diagram_node_extract_utils.ExtractOpts.html +2 -2
- package/docs/types/_saltcorn_data.diagram_node_extract_utils.ExtractResult.html +2 -2
- package/docs/types/_saltcorn_data.diagram_nodes_node.NodeType.html +1 -1
- package/docs/types/_saltcorn_data.models_config.ConfigTypes.html +1 -1
- package/docs/types/_saltcorn_data.models_config.SingleConfig.html +1 -1
- package/docs/types/_saltcorn_data.models_eventlog.EventLogCfg.html +2 -2
- package/docs/types/_saltcorn_data.models_file.FileCfg.html +2 -2
- package/docs/types/_saltcorn_data.models_form.AdditionalButton.html +1 -1
- package/docs/types/_saltcorn_data.models_form.FormCfg.html +2 -2
- package/docs/types/_saltcorn_data.models_internal_push_message_helper.MobileSubscription.html +2 -2
- package/docs/types/_saltcorn_data.models_internal_push_message_helper.WebPushSubscription.html +2 -2
- package/docs/types/_saltcorn_data.models_internal_s3_helpers.S3HeadResult.html +1 -1
- package/docs/types/_saltcorn_data.models_internal_s3_helpers.S3ListResult.html +2 -2
- package/docs/types/_saltcorn_data.models_page_group.ScreenInfoParams.html +2 -2
- package/docs/types/_saltcorn_data.models_table.ChildRelations.html +2 -2
- package/docs/types/_saltcorn_data.models_table.ParentRelations.html +2 -2
- package/docs/types/_saltcorn_data.models_table.RelationData.html +2 -2
- package/docs/types/_saltcorn_data.models_tag_entry.TagEntryCfg.html +1 -1
- package/docs/types/_saltcorn_data.models_view.FindViewsPred.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.AggregationOptions.html +2 -2
- package/docs/types/_saltcorn_db-common.dbtypes.CoordOpts.html +2 -2
- package/docs/types/_saltcorn_db-common.dbtypes.DatabaseClient.html +2 -2
- package/docs/types/_saltcorn_db-common.dbtypes.JoinField.html +2 -2
- package/docs/types/_saltcorn_db-common.dbtypes.JoinFields.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.JoinOptions.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.JsonPath.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.JsonPathElem.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.Operator.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.PartialSome.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.PrimaryKeyValue.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.Row.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.SelectOptions.html +2 -2
- package/docs/types/_saltcorn_db-common.dbtypes.StrongRow.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.SubselectOptions.html +2 -2
- package/docs/types/_saltcorn_db-common.dbtypes.Value.html +1 -1
- package/docs/types/_saltcorn_db-common.dbtypes.Where.html +2 -2
- package/docs/types/_saltcorn_db-common.sqlite-commons.SqlAndValues.html +2 -2
- package/docs/types/_saltcorn_db-common.types.DbExportsType.html +2 -2
- package/docs/types/_saltcorn_db-common.types.GenObj.html +1 -1
- package/docs/types/_saltcorn_markup.emergency_layout.WrapParams.html +2 -2
- package/docs/types/_saltcorn_markup.helpers.CheckBoxGroupOpts.html +2 -2
- package/docs/types/_saltcorn_markup.helpers.PaginationOpts.html +2 -2
- package/docs/types/_saltcorn_markup.helpers.RadioGroupOpts.html +2 -2
- package/docs/types/_saltcorn_markup.helpers.SearchBarOpts.html +2 -2
- package/docs/types/_saltcorn_markup.layout.RenderOpts-1.html +2 -2
- package/docs/types/_saltcorn_markup.layout.RenderOpts.html +2 -2
- package/docs/types/_saltcorn_markup.mjml-layout.RenderOpts.html +2 -2
- package/docs/types/_saltcorn_markup.table.HeadersParams.html +2 -2
- package/docs/types/_saltcorn_markup.table.OptsParams.html +2 -2
- package/docs/types/_saltcorn_markup.types.AttributeVal.html +1 -1
- package/docs/types/_saltcorn_markup.types.Attributes.html +2 -2
- package/docs/types/_saltcorn_markup.types.ClassVal.html +1 -1
- package/docs/types/_saltcorn_markup.types.Element.html +1 -1
- package/docs/types/_saltcorn_markup.types.Falsy.html +1 -1
- package/docs/types/_saltcorn_markup.types.StyleVal.html +1 -1
- package/docs/types/_saltcorn_markup.types.TagFunction.html +1 -1
- package/docs/types/_saltcorn_mobile-builder.mobile-builder.IosCfg.html +2 -2
- package/docs/types/_saltcorn_mobile-builder.utils_capacitor-helper.CapacitorCfg.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Action.html +3 -3
- package/docs/types/_saltcorn_types.base_types.AuthenticationMethod.html +2 -2
- package/docs/types/_saltcorn_types.base_types.CalcJoinfield.html +2 -2
- package/docs/types/_saltcorn_types.base_types.CapacitorPlugin.html +2 -2
- package/docs/types/_saltcorn_types.base_types.CodePagePack.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Column.html +2 -2
- package/docs/types/_saltcorn_types.base_types.ConnectObjType.html +2 -2
- package/docs/types/_saltcorn_types.base_types.ConnectedObjects.html +2 -2
- package/docs/types/_saltcorn_types.base_types.CopilotSkill.html +2 -2
- package/docs/types/_saltcorn_types.base_types.ErrorObj.html +2 -2
- package/docs/types/_saltcorn_types.base_types.FieldLike.html +1 -1
- package/docs/types/_saltcorn_types.base_types.FieldView.html +1 -1
- package/docs/types/_saltcorn_types.base_types.Header.html +2 -2
- package/docs/types/_saltcorn_types.base_types.JoinFieldOption.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Layout.html +1 -1
- package/docs/types/_saltcorn_types.base_types.MenuItem.html +2 -2
- package/docs/types/_saltcorn_types.base_types.MobileConfig.html +2 -3
- package/docs/types/_saltcorn_types.base_types.ModelPattern.html +6 -6
- package/docs/types/_saltcorn_types.base_types.Pack.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Plugin.html +1 -1
- package/docs/types/_saltcorn_types.base_types.PluginFunction.html +2 -2
- package/docs/types/_saltcorn_types.base_types.PluginLayout.html +2 -2
- package/docs/types/_saltcorn_types.base_types.PluginRoute.html +2 -2
- package/docs/types/_saltcorn_types.base_types.PluginSourceType.html +1 -1
- package/docs/types/_saltcorn_types.base_types.PluginType.html +2 -2
- package/docs/types/_saltcorn_types.base_types.PluginWrap.html +1 -1
- package/docs/types/_saltcorn_types.base_types.PluginWrapArg.html +2 -2
- package/docs/types/_saltcorn_types.base_types.RelationOption.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Req.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Res.html +2 -2
- package/docs/types/_saltcorn_types.base_types.ResultType.html +2 -2
- package/docs/types/_saltcorn_types.base_types.RouteAction.html +1 -1
- package/docs/types/_saltcorn_types.base_types.RunExtra.html +1 -1
- package/docs/types/_saltcorn_types.base_types.SlugStepType.html +2 -2
- package/docs/types/_saltcorn_types.base_types.StepResType.html +1 -1
- package/docs/types/_saltcorn_types.base_types.SubField.html +2 -2
- package/docs/types/_saltcorn_types.base_types.TableProvider.html +2 -2
- package/docs/types/_saltcorn_types.base_types.TableQuery.html +2 -2
- package/docs/types/_saltcorn_types.base_types.Tablely.html +1 -1
- package/docs/types/_saltcorn_types.base_types.ViewTemplate.html +2 -2
- package/docs/types/_saltcorn_types.common_types.ErrorMessage.html +2 -2
- package/docs/types/_saltcorn_types.common_types.GenObj.html +1 -1
- package/docs/types/_saltcorn_types.common_types.ReqRes.html +2 -2
- package/docs/types/_saltcorn_types.common_types.ResultMessage.html +1 -1
- package/docs/types/_saltcorn_types.common_types.SuccessMessage.html +2 -2
- package/docs/types/_saltcorn_types.common_types.Type.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_event_log.EventLogPack.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_field.FieldCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_field.InputType.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_form.AdditionalButton.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_library.LibraryCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_library.LibraryPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_model.ModelCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_model.ModelPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_model_instance.ModelInstanceCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_model_instance.ModelInstancePack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_page.PageCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_page.PagePack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group.PageGroupCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group.PageGroupPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group_member.PageGroupMemberCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_page_group_member.PageGroupMemberPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_plugin.PluginCfg.html +3 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_plugin.PluginPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_role.RoleCfg.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_role.RolePack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_table.TableCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_table.TablePack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_tag.TagPack.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_tag_entry.TagEntryPack.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_trigger.TriggerCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_trigger.TriggerPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_view.ViewCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_view.ViewPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow.ConfigWorkflowStep.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow.RunResult.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_run.WorkflowRunCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_step.WorkflowStepCfg.html +2 -2
- package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_step.WorkflowStepPack.html +1 -1
- package/docs/types/_saltcorn_types.model-abstracts_abstract_workflow_trace.WorkflowTraceCfg.html +2 -2
- package/docs/variables/_saltcorn_admin-models..backup.create_backup.html +1 -1
- package/docs/variables/_saltcorn_admin-models..backup.create_csv_from_rows.html +1 -1
- package/docs/variables/_saltcorn_admin-models..backup.restore.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.add_to_menu.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.can_install_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.fetch_available_packs.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.fetch_pack_by_name.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.install_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.library_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.model_instance_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.model_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.page_group_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.page_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.plugin_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.role_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.table_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.trigger_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.uninstall_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..pack.view_pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.copy_tenant_template.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.create_tenant.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.deleteTenant.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.domain_sanitize.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.eachTenant.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.getAllTenantRows.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.getAllTenants.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.insertTenant.html +1 -1
- package/docs/variables/_saltcorn_admin-models..tenant.switchToTenant.html +1 -1
- package/docs/variables/_saltcorn_admin-models.models_backup.backup.html +1 -1
- package/docs/variables/_saltcorn_admin-models.pack.pack.html +1 -1
- package/docs/variables/_saltcorn_admin-models.tenant.tenant.html +1 -1
- package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedFive.html +1 -1
- package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedFour.html +1 -1
- package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedOne.html +1 -1
- package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedSix.html +1 -1
- package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedThree.html +1 -1
- package/docs/variables/_saltcorn_common-code.tests_expected_relations.expectedTwo.html +1 -1
- package/docs/variables/_saltcorn_data..migrations.html +1 -1
- package/docs/variables/_saltcorn_data..plugin_helper.run_action_column.html +1 -1
- package/docs/variables/_saltcorn_data..utils.NotAuthorized.html +1 -1
- package/docs/variables/_saltcorn_data..utils.isPushEnabled.html +1 -1
- package/docs/variables/_saltcorn_data..utils.sleep.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_actions.actions.html +4 -4
- package/docs/variables/_saltcorn_data.base-plugin_fieldviews.fieldviews.html +3 -3
- package/docs/variables/_saltcorn_data.base-plugin_fileview.fileviews.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_index.index.html +6 -6
- package/docs/variables/_saltcorn_data.base-plugin_types.types.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_edit.edit.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_feed.feed.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_filter.filter.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_list.list.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_listshowlist.listshowlist.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_room.room-1.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_room.room.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_show.show.html +1 -1
- package/docs/variables/_saltcorn_data.base-plugin_viewtemplates_viewable_fields.edit_build_in_actions.html +1 -1
- package/docs/variables/_saltcorn_data.contract.contract.html +1 -1
- package/docs/variables/_saltcorn_data.db_connect.connect.html +1 -1
- package/docs/variables/_saltcorn_data.db_fa5-icons.fa5Icons.html +1 -1
- package/docs/variables/_saltcorn_data.db_fixtures.fixtures.html +1 -1
- package/docs/variables/_saltcorn_data.db_index.dbExports.html +1 -1
- package/docs/variables/_saltcorn_data.db_state.state.html +3 -3
- package/docs/variables/_saltcorn_data.migrations_202005141503.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202005241712.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202005251037.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202005282134.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202006022156.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202006051507.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202006240906.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202007091707.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202007202144.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202008031500.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202008051415.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202008121149.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202008121149.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202009112140.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202009112140.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202009181655.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202009221105.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202009231331.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202009301531.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202010231444.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202010251412.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202011021749.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202011051353.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202011111127.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202012011203.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202012100841.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202012281835.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202101061051.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202101141128.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202102091312.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202102101624.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202102172148.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202102261650.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106102347.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106112120.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106120012.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106120220.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106121701.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106121703.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106121703.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202106251126.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202107281619.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202107302158.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202107302158.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202108022257.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202109201624.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202109301031.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202109301031.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202111290253.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202111290253.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202112282254.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202112282254.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202207022002.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202207252150.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202207252150.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202207261221.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202208101144.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202208101144.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202211040031.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202212112152.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202212112152.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202301130917.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202303201126.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202303201126.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202303221944.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202303221944.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202304281224.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202305031518.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202305031518.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202308211648.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202311011755.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202311011755.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202311231356.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202402071125.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202406260915.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202412051957.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202412051957.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202412111526.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202412111526.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202501081226.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202501081226.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202501201239.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202501262157.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202503071353.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202506050958.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202510110312.sql_pg.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202510110312.sql_sqlite.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202511081024.sql.html +1 -1
- package/docs/variables/_saltcorn_data.migrations_202604091531.sql.html +1 -1
- package/docs/variables/_saltcorn_data.mobile-mocks_npm_npm-registry-fetch.npmRegistryFetch.html +1 -1
- package/docs/variables/_saltcorn_data.mobile-mocks_saltcorn_html-pdf-node.htmlPdfNode.html +1 -1
- package/docs/variables/_saltcorn_data.models_config.configExports.html +1 -1
- package/docs/variables/_saltcorn_data.models_discovery.discovery.html +1 -1
- package/docs/variables/_saltcorn_data.models_email.email.html +3 -3
- package/docs/variables/_saltcorn_data.models_expression.expression.html +3 -3
- package/docs/variables/_saltcorn_data.models_index.config.available_languages.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.check_email_mask.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.configTypes.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.deleteConfig.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.getAllConfig.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.getConfig.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.get_base_url.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.get_latest_npm_version.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.remove_from_menu.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.save_menu_items.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.config.setConfig.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.discovery.discover_tables.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.discovery.discoverable_tables.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.discovery.findType.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.discovery.get_existing_views.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.discovery.implement_discovery.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.email.getMailTransport.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.email.send_verification_email.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.email.viewToEmailHtml.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.apply_calculated_fields.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.apply_calculated_fields_stored.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.eval_expression.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.expressionValidator.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.get_async_expression_function.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.get_expression_function.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.jsexprToWhere.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.recalculate_for_stored.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.expression.transform_for_async.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.layout.eachView.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.layout.getStringsForI18n.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.layout.getViews.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.layout.translateLayout.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.layout.traverse.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.layout.traverseSync.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.random.all_views.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.random.fill_table_row.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.random.initial_view.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.random.random_table.html +1 -1
- package/docs/variables/_saltcorn_data.models_index.scheduler.runScheduler.html +1 -1
- package/docs/variables/_saltcorn_data.models_layout.layout.html +1 -1
- package/docs/variables/_saltcorn_data.models_random.random.html +1 -1
- package/docs/variables/_saltcorn_data.models_scheduler.scheduler.html +1 -1
- package/docs/variables/_saltcorn_data.plugin-helper.add_free_variables_to_joinfields.html +1 -1
- package/docs/variables/_saltcorn_data.tests_mocks.mocks.html +1 -1
- package/docs/variables/_saltcorn_data.tests_remote_query_helper.renderEditInEditConfig.html +1 -1
- package/docs/variables/_saltcorn_data.utils.utils.html +10 -4
- package/docs/variables/_saltcorn_data.web-mobile-commons.webMobileCommons.html +1 -1
- package/docs/variables/_saltcorn_db-common.internal.dbCommonModulePath.html +1 -1
- package/docs/variables/_saltcorn_db-common.multi-tenant.tenantNamespace.html +1 -1
- package/docs/variables/_saltcorn_db-common.tenants.tenants.html +1 -1
- package/docs/variables/_saltcorn_markup..export_.html +1 -1
- package/docs/variables/_saltcorn_markup.builder.builder.html +1 -1
- package/docs/variables/_saltcorn_markup.emergency_layout.EmergencyLayoutExports.html +1 -1
- package/docs/variables/_saltcorn_markup.form.form.html +1 -1
- package/docs/variables/_saltcorn_markup.helpers.HelpersExports.html +1 -1
- package/docs/variables/_saltcorn_markup.layout.LayoutExports-1.html +1 -1
- package/docs/variables/_saltcorn_markup.layout.LayoutExports.html +1 -1
- package/docs/variables/_saltcorn_markup.layout_utils.layoutUtils.html +1 -1
- package/docs/variables/_saltcorn_markup.mjml-layout.LayoutExports.html +1 -1
- package/docs/variables/_saltcorn_markup.mjml-tags.tagsExports.html +1 -1
- package/docs/variables/_saltcorn_markup.table.TableExports.html +1 -1
- package/docs/variables/_saltcorn_markup.tags.tagsExports.html +1 -1
- package/docs/variables/_saltcorn_types..generators.generateBool.html +1 -1
- package/docs/variables/_saltcorn_types..generators.generateString.html +1 -1
- package/docs/variables/_saltcorn_types..generators.num_between.html +1 -1
- package/docs/variables/_saltcorn_types..generators.oneOf.html +1 -1
- package/docs/variables/_saltcorn_types.generators.generators.html +1 -1
- package/help/JavaScript action code.tmd +5 -1
- package/locales/en.json +3 -1
- package/package.json +13 -13
- package/public/saltcorn-common.js +5 -2
- package/public/saltcorn.js +23 -0
- package/routes/actions.js +9 -8
- package/routes/admin.js +67 -8
- package/routes/api.js +40 -37
- package/routes/fields.js +114 -10
- package/routes/files.js +13 -1
- package/routes/list.js +5 -4
- package/routes/plugins.js +29 -3
- package/routes/sync.js +45 -32
- package/routes/tables.js +166 -0
- package/routes/utils.js +9 -32
- package/serve.js +26 -9
- package/tests/admin.test.js +5 -5
- package/tests/api.test.js +130 -1
- package/tests/files.test.js +39 -0
- package/tests/plugin_install.test.js +120 -0
- package/tests/sync.test.js +62 -46
- package/tests/view.test.js +32 -0
- package/wrapper.js +1 -1
- package/docs/functions/_saltcorn_data.migrations_202604111200.sql_pg.html +0 -1
package/tests/api.test.js
CHANGED
|
@@ -822,7 +822,10 @@ describe("API emit-event access control", () => {
|
|
|
822
822
|
.set("Authorization", `jwt ${adminJwt}`)
|
|
823
823
|
.send({ payload: {} })
|
|
824
824
|
.expect(
|
|
825
|
-
respondJsonWith(
|
|
825
|
+
respondJsonWith(
|
|
826
|
+
403,
|
|
827
|
+
(resp) => resp.error === "Event type not allowed"
|
|
828
|
+
)
|
|
826
829
|
);
|
|
827
830
|
}
|
|
828
831
|
});
|
|
@@ -1150,4 +1153,130 @@ describe("API cross-table sub-select access control", () => {
|
|
|
1150
1153
|
const rows2 = resp2.body.success || [];
|
|
1151
1154
|
expect(rows1.length).toBe(rows2.length);
|
|
1152
1155
|
});
|
|
1156
|
+
|
|
1157
|
+
it("should not allow probing restricted tables via _relation_path_ parameter", async () => {
|
|
1158
|
+
const app = await getApp({ disableCsrf: true });
|
|
1159
|
+
// The _relation_path_ query parameter accepts JSON that specifies a
|
|
1160
|
+
// relation path through arbitrary tables. handleRelationPath() constructs
|
|
1161
|
+
// an inSelectWithLevels subquery with NO authorization checks.
|
|
1162
|
+
//
|
|
1163
|
+
// Attack: query the public books table with a _relation_path_ that
|
|
1164
|
+
// traverses the restricted patients table (min_role_read=40):
|
|
1165
|
+
// ?_relation_path_={"relation":".books.patients$name","srcId":"Kirk Douglas"}
|
|
1166
|
+
// This generates:
|
|
1167
|
+
// WHERE id IN (SELECT id FROM patients WHERE name = 'Kirk Douglas')
|
|
1168
|
+
// A public user can determine whether a patient with a given name exists
|
|
1169
|
+
// by observing which books are returned.
|
|
1170
|
+
const patients = Table.findOne({ name: "patients" });
|
|
1171
|
+
expect(patients.min_role_read).toBe(40);
|
|
1172
|
+
|
|
1173
|
+
// srcId matching an existing patient name
|
|
1174
|
+
const resp1 = await request(app)
|
|
1175
|
+
.get("/api/books/")
|
|
1176
|
+
.query({
|
|
1177
|
+
_relation_path_: JSON.stringify({
|
|
1178
|
+
relation: ".books.patients$name",
|
|
1179
|
+
srcId: "Kirk Douglas",
|
|
1180
|
+
}),
|
|
1181
|
+
})
|
|
1182
|
+
.expect(200);
|
|
1183
|
+
|
|
1184
|
+
// srcId with a non-existent patient name
|
|
1185
|
+
const resp2 = await request(app)
|
|
1186
|
+
.get("/api/books/")
|
|
1187
|
+
.query({
|
|
1188
|
+
_relation_path_: JSON.stringify({
|
|
1189
|
+
relation: ".books.patients$name",
|
|
1190
|
+
srcId: "ZZZNONEXISTENT",
|
|
1191
|
+
}),
|
|
1192
|
+
})
|
|
1193
|
+
.expect(200);
|
|
1194
|
+
|
|
1195
|
+
// If the relation_path is allowed without authorization, resp1 returns
|
|
1196
|
+
// book id=1 (because patient "Kirk Douglas" has id=1) while resp2
|
|
1197
|
+
// returns nothing. The difference reveals that "Kirk Douglas" exists
|
|
1198
|
+
// in the restricted patients table.
|
|
1199
|
+
//
|
|
1200
|
+
// Secure behavior: both queries return the same results (the subquery
|
|
1201
|
+
// against the restricted table is blocked or ignored), OR the query
|
|
1202
|
+
// is rejected.
|
|
1203
|
+
const rows1 = resp1.body.success || [];
|
|
1204
|
+
const rows2 = resp2.body.success || [];
|
|
1205
|
+
expect(rows1.length).toBe(rows2.length);
|
|
1206
|
+
});
|
|
1207
|
+
|
|
1208
|
+
it("should not allow probing restricted tables via dot-prefix relation path", async () => {
|
|
1209
|
+
const app = await getApp({ disableCsrf: true });
|
|
1210
|
+
// The dot-prefix syntax (e.g. ?.books.patients$name=value) is another
|
|
1211
|
+
// way to invoke handleRelationPath, which has no authorization checks.
|
|
1212
|
+
// This constructs the same inSelectWithLevels subquery.
|
|
1213
|
+
const patients = Table.findOne({ name: "patients" });
|
|
1214
|
+
expect(patients.min_role_read).toBe(40);
|
|
1215
|
+
|
|
1216
|
+
const resp1 = await request(app)
|
|
1217
|
+
.get("/api/books/")
|
|
1218
|
+
.query({ ".books.patients$name": "Kirk Douglas" })
|
|
1219
|
+
.expect(200);
|
|
1220
|
+
|
|
1221
|
+
const resp2 = await request(app)
|
|
1222
|
+
.get("/api/books/")
|
|
1223
|
+
.query({ ".books.patients$name": "ZZZNONEXISTENT" })
|
|
1224
|
+
.expect(200);
|
|
1225
|
+
|
|
1226
|
+
const rows1 = resp1.body.success || [];
|
|
1227
|
+
const rows2 = resp2.body.success || [];
|
|
1228
|
+
expect(rows1.length).toBe(rows2.length);
|
|
1229
|
+
});
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
describe("API CSRF protection", () => {
|
|
1233
|
+
let adminToken, adminJwt;
|
|
1234
|
+
|
|
1235
|
+
beforeAll(async () => {
|
|
1236
|
+
const admin = await User.findOne({ email: "admin@foo.com" });
|
|
1237
|
+
adminToken = await admin.getNewAPIToken();
|
|
1238
|
+
adminJwt = await getAdminJwt();
|
|
1239
|
+
});
|
|
1240
|
+
|
|
1241
|
+
it("should reject POST with session cookie but no CSRF token", async () => {
|
|
1242
|
+
const app = await getApp({ disableCsrf: false });
|
|
1243
|
+
const loginCookie = await getAdminLoginCookie();
|
|
1244
|
+
await request(app)
|
|
1245
|
+
.post("/api/books/")
|
|
1246
|
+
.set("Cookie", loginCookie)
|
|
1247
|
+
.send({ author: "CSRF Test", pages: 1 })
|
|
1248
|
+
.set("Content-Type", "application/json")
|
|
1249
|
+
.expect(302);
|
|
1250
|
+
});
|
|
1251
|
+
|
|
1252
|
+
it("should allow POST with bearer token and no CSRF token", async () => {
|
|
1253
|
+
const app = await getApp({ disableCsrf: false });
|
|
1254
|
+
await request(app)
|
|
1255
|
+
.post("/api/books/")
|
|
1256
|
+
.set("Authorization", "Bearer " + adminToken)
|
|
1257
|
+
.send({ author: "Bearer No CSRF", pages: 2 })
|
|
1258
|
+
.set("Content-Type", "application/json")
|
|
1259
|
+
.set("Accept", "application/json")
|
|
1260
|
+
.expect(succeedJsonWith((resp) => resp && typeof resp === "number"));
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1263
|
+
it("should allow POST with valid JWT and no CSRF token", async () => {
|
|
1264
|
+
const app = await getApp({ disableCsrf: false });
|
|
1265
|
+
await request(app)
|
|
1266
|
+
.post("/api/books/")
|
|
1267
|
+
.set("Authorization", `jwt ${adminJwt}`)
|
|
1268
|
+
.send({ author: "JWT No CSRF", pages: 3 })
|
|
1269
|
+
.set("Content-Type", "application/json")
|
|
1270
|
+
.set("Accept", "application/json")
|
|
1271
|
+
.expect(succeedJsonWith((resp) => resp && typeof resp === "number"));
|
|
1272
|
+
});
|
|
1273
|
+
|
|
1274
|
+
it("should not bypass CSRF by appending a fake ?jwt= query parameter", async () => {
|
|
1275
|
+
const app = await getApp({ disableCsrf: false });
|
|
1276
|
+
await request(app)
|
|
1277
|
+
.post("/api/books/?jwt=fakejwt")
|
|
1278
|
+
.send({ author: "CSRF Bypass Attempt", pages: 4 })
|
|
1279
|
+
.set("Content-Type", "application/json")
|
|
1280
|
+
.expect(302);
|
|
1281
|
+
});
|
|
1153
1282
|
});
|
package/tests/files.test.js
CHANGED
|
@@ -107,6 +107,13 @@ beforeAll(async () => {
|
|
|
107
107
|
"console.log('I am a script');",
|
|
108
108
|
1
|
|
109
109
|
);
|
|
110
|
+
await createTestFile(
|
|
111
|
+
"/",
|
|
112
|
+
"malicious.svg",
|
|
113
|
+
"image/svg+xml",
|
|
114
|
+
`<svg xmlns="http://www.w3.org/2000/svg"><script>alert('XSS')</script><circle cx="50" cy="50" r="40"/></svg>`,
|
|
115
|
+
100
|
|
116
|
+
);
|
|
110
117
|
});
|
|
111
118
|
afterAll(db.close);
|
|
112
119
|
|
|
@@ -163,6 +170,16 @@ describe("files admin", () => {
|
|
|
163
170
|
toSucceedWithImage({ lengthIs: (bs) => bs < 100000 && bs > 2000 })
|
|
164
171
|
);
|
|
165
172
|
});
|
|
173
|
+
it("sanitize SVG served via /files/resize (XSS bypass)", async () => {
|
|
174
|
+
const app = await getApp({ disableCsrf: true });
|
|
175
|
+
const res = await request(app).get("/files/resize/0/0/malicious.svg");
|
|
176
|
+
expect(res.status).toBe(200);
|
|
177
|
+
const body = res.text || Buffer.from(res.body).toString();
|
|
178
|
+
// The resize endpoint must also sanitize SVG files, just like /files/serve does.
|
|
179
|
+
// Without this, an attacker can bypass DOMPurify by requesting an SVG via
|
|
180
|
+
// /files/resize/0/0/path.svg (width=0 makes it serve the original file).
|
|
181
|
+
expect(body).not.toContain("<script>");
|
|
182
|
+
});
|
|
166
183
|
it("serve resized file without height", async () => {
|
|
167
184
|
const app = await getApp({ disableCsrf: true });
|
|
168
185
|
await request(app)
|
|
@@ -538,4 +555,26 @@ describe("visible_entries test", () => {
|
|
|
538
555
|
expect(body.files.length).toBe(0);
|
|
539
556
|
expect(body.directories.length).toBe(0);
|
|
540
557
|
});
|
|
558
|
+
|
|
559
|
+
it("should not crash on regex special characters in file_exts (CVE: regex injection)", async () => {
|
|
560
|
+
// The file_exts parameter is passed directly to new RegExp() without escaping.
|
|
561
|
+
// Regex metacharacters like ( [ cause SyntaxError → 500 Internal Server Error.
|
|
562
|
+
// This also enables ReDoS: patterns like (a+)+b cause exponential CPU usage.
|
|
563
|
+
// Confirmed: a file with 30 repeated chars + backtracking regex → 3.6s,
|
|
564
|
+
// 35 chars → 112s. The endpoint should escape regex metacharacters
|
|
565
|
+
// or use literal string matching, not raw user input in new RegExp().
|
|
566
|
+
const app = await getApp({ disableCsrf: true });
|
|
567
|
+
const adminCookie = await getAdminLoginCookie();
|
|
568
|
+
await getState().setConfig("min_role_edit_files", 1);
|
|
569
|
+
const resp = await request(app)
|
|
570
|
+
.get(
|
|
571
|
+
"/files/visible_entries?dir=_sc_test_subfolder_one&file_exts=" +
|
|
572
|
+
encodeURIComponent("([")
|
|
573
|
+
)
|
|
574
|
+
.set("Cookie", adminCookie);
|
|
575
|
+
// Should return 200 with valid JSON, not crash with 500
|
|
576
|
+
expect(resp.statusCode).toBe(200);
|
|
577
|
+
expect(resp.body).toBeDefined();
|
|
578
|
+
expect(resp.body.files).toBeDefined();
|
|
579
|
+
});
|
|
541
580
|
});
|
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
} = require("@saltcorn/admin-models/models/tenant");
|
|
10
10
|
const { resetToFixtures } = require("../auth/testhelp");
|
|
11
11
|
const db = require("@saltcorn/data/db");
|
|
12
|
+
const { get_store_items } = require("../routes/plugins");
|
|
12
13
|
|
|
13
14
|
beforeAll(async () => {
|
|
14
15
|
if (!db.isSQLite) await db.query(`drop schema if exists test101 CASCADE `);
|
|
@@ -87,6 +88,64 @@ describe("Tenant cannot install unsafe plugins", () => {
|
|
|
87
88
|
expect(dbPlugin).toBe(null);
|
|
88
89
|
});
|
|
89
90
|
});
|
|
91
|
+
it("cannot install git plugins on tenant when tenants_install_git is false", async () => {
|
|
92
|
+
await db.runWithTenant("test101", async () => {
|
|
93
|
+
const loadAndSaveNewPlugin = Plugin.loadAndSaveNewPlugin;
|
|
94
|
+
|
|
95
|
+
await install_pack(
|
|
96
|
+
plugin_pack({
|
|
97
|
+
name: "some-git-plugin",
|
|
98
|
+
source: "git",
|
|
99
|
+
location: "https://github.com/example/some-git-plugin",
|
|
100
|
+
}),
|
|
101
|
+
"Some git plugin",
|
|
102
|
+
loadAndSaveNewPlugin
|
|
103
|
+
);
|
|
104
|
+
const dbPlugin = await Plugin.findOne({ name: "some-git-plugin" });
|
|
105
|
+
expect(dbPlugin).toBe(null);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
it("cannot install github plugins on tenant when tenants_install_git is false", async () => {
|
|
109
|
+
await db.runWithTenant("test101", async () => {
|
|
110
|
+
const loadAndSaveNewPlugin = Plugin.loadAndSaveNewPlugin;
|
|
111
|
+
|
|
112
|
+
await install_pack(
|
|
113
|
+
plugin_pack({
|
|
114
|
+
name: "some-github-plugin",
|
|
115
|
+
source: "github",
|
|
116
|
+
location: "example/some-github-plugin",
|
|
117
|
+
}),
|
|
118
|
+
"Some github plugin",
|
|
119
|
+
loadAndSaveNewPlugin
|
|
120
|
+
);
|
|
121
|
+
const dbPlugin = await Plugin.findOne({ name: "some-github-plugin" });
|
|
122
|
+
expect(dbPlugin).toBe(null);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
it("loadPlugin skips git plugin on tenant when tenants_install_git is false", async () => {
|
|
126
|
+
await db.runWithTenant("test101", async () => {
|
|
127
|
+
const result = await Plugin.loadPlugin(
|
|
128
|
+
new Plugin({
|
|
129
|
+
name: "some-git-plugin",
|
|
130
|
+
source: "git",
|
|
131
|
+
location: "https://github.com/example/some-git-plugin",
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
expect(result).toBeUndefined();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
it("loadPlugin skips github plugin on tenant when tenants_install_git is false", async () => {
|
|
138
|
+
await db.runWithTenant("test101", async () => {
|
|
139
|
+
const result = await Plugin.loadPlugin(
|
|
140
|
+
new Plugin({
|
|
141
|
+
name: "some-github-plugin",
|
|
142
|
+
source: "github",
|
|
143
|
+
location: "example/some-github-plugin",
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
expect(result).toBeUndefined();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
90
149
|
it("can install unsafe plugins on tenant when permitted", async () => {
|
|
91
150
|
await getState().setConfig("tenants_unsafe_plugins", true);
|
|
92
151
|
await db.runWithTenant("test101", async () => {
|
|
@@ -346,3 +405,64 @@ describe("Stable versioning upgrade", () => {
|
|
|
346
405
|
expect(newPlugin.version).toBe("0.1.0");
|
|
347
406
|
});
|
|
348
407
|
});
|
|
408
|
+
|
|
409
|
+
describe("Tenant git plugin store filtering", () => {
|
|
410
|
+
const mockReq = { flash: () => {}, __: (s) => s };
|
|
411
|
+
|
|
412
|
+
if (!db.isSQLite) {
|
|
413
|
+
it("git plugin is excluded from installed list when tenants_install_git is false", async () => {
|
|
414
|
+
await db.runWithTenant("test101", async () => {
|
|
415
|
+
const gitPlugin = new Plugin({
|
|
416
|
+
name: "test-git-plugin",
|
|
417
|
+
source: "git",
|
|
418
|
+
location: "https://github.com/example/test-git-plugin",
|
|
419
|
+
});
|
|
420
|
+
await gitPlugin.upsert();
|
|
421
|
+
|
|
422
|
+
const items = await get_store_items(mockReq);
|
|
423
|
+
const names = items.map((i) => i.name);
|
|
424
|
+
expect(names).not.toContain("test-git-plugin");
|
|
425
|
+
|
|
426
|
+
await db.deleteWhere("_sc_plugins", { name: "test-git-plugin" });
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("github plugin is excluded from installed list when tenants_install_git is false", async () => {
|
|
431
|
+
await db.runWithTenant("test101", async () => {
|
|
432
|
+
const githubPlugin = new Plugin({
|
|
433
|
+
name: "test-github-plugin",
|
|
434
|
+
source: "github",
|
|
435
|
+
location: "example/test-github-plugin",
|
|
436
|
+
});
|
|
437
|
+
await githubPlugin.upsert();
|
|
438
|
+
|
|
439
|
+
const items = await get_store_items(mockReq);
|
|
440
|
+
const names = items.map((i) => i.name);
|
|
441
|
+
expect(names).not.toContain("test-github-plugin");
|
|
442
|
+
|
|
443
|
+
await db.deleteWhere("_sc_plugins", { name: "test-github-plugin" });
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("git plugin does not appear as installed in set=all when tenants_install_git is false", async () => {
|
|
448
|
+
await db.runWithTenant("test101", async () => {
|
|
449
|
+
const gitPlugin = new Plugin({
|
|
450
|
+
name: "test-git-plugin",
|
|
451
|
+
source: "git",
|
|
452
|
+
location: "https://github.com/example/test-git-plugin",
|
|
453
|
+
});
|
|
454
|
+
await gitPlugin.upsert();
|
|
455
|
+
|
|
456
|
+
const items = await get_store_items(mockReq);
|
|
457
|
+
const match = items.find((i) => i.name === "test-git-plugin");
|
|
458
|
+
expect(match).toBeUndefined();
|
|
459
|
+
|
|
460
|
+
await db.deleteWhere("_sc_plugins", { name: "test-git-plugin" });
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
} else {
|
|
464
|
+
it("does not support tenants on SQLite", async () => {
|
|
465
|
+
expect(db.isSQLite).toBe(true);
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
});
|
package/tests/sync.test.js
CHANGED
|
@@ -101,7 +101,7 @@ describe("load remote insert/updates", () => {
|
|
|
101
101
|
loadUntil: loadUntil.valueOf(),
|
|
102
102
|
syncInfos: {
|
|
103
103
|
books: {
|
|
104
|
-
|
|
104
|
+
lastModifiedAt: 0,
|
|
105
105
|
},
|
|
106
106
|
},
|
|
107
107
|
});
|
|
@@ -111,15 +111,16 @@ describe("load remote insert/updates", () => {
|
|
|
111
111
|
for (const row of data.books.rows) {
|
|
112
112
|
const fromDb = await books.getRows({ id: row._sync_info_tbl_ref_ });
|
|
113
113
|
expect(fromDb.length).toBe(1);
|
|
114
|
-
expect(row._sync_info_tbl_last_modified_).toBe(
|
|
115
|
-
expect(row._sync_info_tbl_deleted_).toBe(
|
|
114
|
+
expect(typeof row._sync_info_tbl_last_modified_).toBe("number");
|
|
115
|
+
expect(row._sync_info_tbl_deleted_).toBe(false);
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
it("with syncFrom,
|
|
119
|
+
it("with syncFrom, no changes in window", async () => {
|
|
120
120
|
const app = await getApp({ disableCsrf: true });
|
|
121
121
|
const loginCookie = await getAdminLoginCookie();
|
|
122
122
|
const loadUntil = new Date();
|
|
123
|
+
// syncFrom == loadUntil → empty time window → no rows
|
|
123
124
|
const resp = await request(app)
|
|
124
125
|
.post("/sync/load_changes")
|
|
125
126
|
.set("Cookie", loginCookie)
|
|
@@ -127,8 +128,8 @@ describe("load remote insert/updates", () => {
|
|
|
127
128
|
loadUntil: loadUntil.valueOf(),
|
|
128
129
|
syncInfos: {
|
|
129
130
|
books: {
|
|
130
|
-
|
|
131
|
-
syncFrom:
|
|
131
|
+
lastModifiedAt: 0,
|
|
132
|
+
syncFrom: loadUntil.valueOf(),
|
|
132
133
|
},
|
|
133
134
|
},
|
|
134
135
|
});
|
|
@@ -154,7 +155,7 @@ describe("load remote insert/updates", () => {
|
|
|
154
155
|
loadUntil: (await db.time()).valueOf(),
|
|
155
156
|
syncInfos: {
|
|
156
157
|
books: {
|
|
157
|
-
|
|
158
|
+
lastModifiedAt: 0,
|
|
158
159
|
syncFrom: dbTime.valueOf(),
|
|
159
160
|
},
|
|
160
161
|
},
|
|
@@ -169,7 +170,7 @@ describe("load remote insert/updates", () => {
|
|
|
169
170
|
_sync_info_tbl_deleted_,
|
|
170
171
|
...rest
|
|
171
172
|
} = data.books.rows[0];
|
|
172
|
-
expect(_sync_info_tbl_ref_).toBe(2);
|
|
173
|
+
expect(Number(_sync_info_tbl_ref_)).toBe(2);
|
|
173
174
|
expect(_sync_info_tbl_last_modified_).toBe(last_modified.valueOf());
|
|
174
175
|
expect(_sync_info_tbl_deleted_).toBe(false);
|
|
175
176
|
expect(rest.author).toBe("Leo Tolstoy");
|
|
@@ -183,7 +184,7 @@ describe("load remote insert/updates", () => {
|
|
|
183
184
|
loadUntil: (await db.time()).valueOf(),
|
|
184
185
|
syncInfos: {
|
|
185
186
|
books: {
|
|
186
|
-
|
|
187
|
+
lastModifiedAt: 0,
|
|
187
188
|
syncFrom: dbTime.valueOf(),
|
|
188
189
|
},
|
|
189
190
|
},
|
|
@@ -198,13 +199,13 @@ describe("load remote insert/updates", () => {
|
|
|
198
199
|
_sync_info_tbl_deleted_,
|
|
199
200
|
...rest
|
|
200
201
|
} = row;
|
|
201
|
-
expect(_sync_info_tbl_ref_).toBe(rest.id);
|
|
202
|
+
expect(Number(_sync_info_tbl_ref_)).toBe(rest.id);
|
|
202
203
|
const { last_modified } = await books.latestSyncInfo(rest.id);
|
|
203
204
|
expect(_sync_info_tbl_last_modified_).toBe(last_modified.valueOf());
|
|
204
205
|
expect(_sync_info_tbl_deleted_).toBe(false);
|
|
205
206
|
}
|
|
206
|
-
expect(data.books.rows[0].author).toBe("
|
|
207
|
-
expect(data.books.rows[1].author).toBe("
|
|
207
|
+
expect(data.books.rows[0].author).toBe("Leo Tolstoy");
|
|
208
|
+
expect(data.books.rows[1].author).toBe("Herman Melville");
|
|
208
209
|
}
|
|
209
210
|
});
|
|
210
211
|
|
|
@@ -246,7 +247,7 @@ describe("load remote insert/updates", () => {
|
|
|
246
247
|
loadUntil: (await db.time()).valueOf(),
|
|
247
248
|
syncInfos: {
|
|
248
249
|
"Table with capitals": {
|
|
249
|
-
|
|
250
|
+
lastModifiedAt: 0,
|
|
250
251
|
syncFrom: dbTime.valueOf(),
|
|
251
252
|
},
|
|
252
253
|
},
|
|
@@ -265,7 +266,7 @@ describe("load remote insert/updates", () => {
|
|
|
265
266
|
loadUntil: loadUntil.valueOf(),
|
|
266
267
|
syncInfos: {
|
|
267
268
|
patients: {
|
|
268
|
-
|
|
269
|
+
lastModifiedAt: 0,
|
|
269
270
|
syncFrom: 1000,
|
|
270
271
|
},
|
|
271
272
|
},
|
|
@@ -304,7 +305,7 @@ describe("load remote insert/updates", () => {
|
|
|
304
305
|
loadUntil: loadUntil.valueOf(),
|
|
305
306
|
syncInfos: {
|
|
306
307
|
patients: {
|
|
307
|
-
|
|
308
|
+
lastModifiedAt: 0,
|
|
308
309
|
},
|
|
309
310
|
},
|
|
310
311
|
});
|
|
@@ -334,7 +335,7 @@ describe("load remote insert/updates", () => {
|
|
|
334
335
|
loadUntil: loadUntil.valueOf(),
|
|
335
336
|
syncInfos: {
|
|
336
337
|
patients: {
|
|
337
|
-
|
|
338
|
+
lastModifiedAt: 0,
|
|
338
339
|
syncFrom: 1000,
|
|
339
340
|
},
|
|
340
341
|
},
|
|
@@ -913,9 +914,9 @@ describe("SQL injection protection", () => {
|
|
|
913
914
|
await initSyncInfo(["books"]);
|
|
914
915
|
});
|
|
915
916
|
|
|
916
|
-
// --- /sync/load_changes :
|
|
917
|
+
// --- /sync/load_changes : lastModifiedAt ---
|
|
917
918
|
|
|
918
|
-
it("rejects SQL injection in
|
|
919
|
+
it("rejects SQL injection in lastModifiedAt (OR 1=1)", async () => {
|
|
919
920
|
const app = await getApp({ disableCsrf: true });
|
|
920
921
|
const loginCookie = await getAdminLoginCookie();
|
|
921
922
|
await request(app)
|
|
@@ -923,14 +924,17 @@ describe("SQL injection protection", () => {
|
|
|
923
924
|
.set("Cookie", loginCookie)
|
|
924
925
|
.send({
|
|
925
926
|
loadUntil: new Date().valueOf(),
|
|
926
|
-
syncInfos: { books: {
|
|
927
|
+
syncInfos: { books: { lastModifiedAt: "0 OR 1=1--" } },
|
|
927
928
|
})
|
|
928
929
|
.expect(
|
|
929
|
-
respondJsonWith(
|
|
930
|
+
respondJsonWith(
|
|
931
|
+
400,
|
|
932
|
+
(resp) => resp.error === "Invalid lastModifiedAt"
|
|
933
|
+
)
|
|
930
934
|
);
|
|
931
935
|
});
|
|
932
936
|
|
|
933
|
-
it("rejects SQL injection in
|
|
937
|
+
it("rejects SQL injection in lastModifiedAt (UNION SELECT)", async () => {
|
|
934
938
|
const app = await getApp({ disableCsrf: true });
|
|
935
939
|
const loginCookie = await getAdminLoginCookie();
|
|
936
940
|
await request(app)
|
|
@@ -939,15 +943,18 @@ describe("SQL injection protection", () => {
|
|
|
939
943
|
.send({
|
|
940
944
|
loadUntil: new Date().valueOf(),
|
|
941
945
|
syncInfos: {
|
|
942
|
-
books: {
|
|
946
|
+
books: { lastModifiedAt: "0 UNION SELECT * FROM users--" },
|
|
943
947
|
},
|
|
944
948
|
})
|
|
945
949
|
.expect(
|
|
946
|
-
respondJsonWith(
|
|
950
|
+
respondJsonWith(
|
|
951
|
+
400,
|
|
952
|
+
(resp) => resp.error === "Invalid lastModifiedAt"
|
|
953
|
+
)
|
|
947
954
|
);
|
|
948
955
|
});
|
|
949
956
|
|
|
950
|
-
it("rejects SQL injection in
|
|
957
|
+
it("rejects SQL injection in lastModifiedAt (stacked query)", async () => {
|
|
951
958
|
const app = await getApp({ disableCsrf: true });
|
|
952
959
|
const loginCookie = await getAdminLoginCookie();
|
|
953
960
|
await request(app)
|
|
@@ -956,15 +963,18 @@ describe("SQL injection protection", () => {
|
|
|
956
963
|
.send({
|
|
957
964
|
loadUntil: new Date().valueOf(),
|
|
958
965
|
syncInfos: {
|
|
959
|
-
books: {
|
|
966
|
+
books: { lastModifiedAt: "0; DROP TABLE books; --" },
|
|
960
967
|
},
|
|
961
968
|
})
|
|
962
969
|
.expect(
|
|
963
|
-
respondJsonWith(
|
|
970
|
+
respondJsonWith(
|
|
971
|
+
400,
|
|
972
|
+
(resp) => resp.error === "Invalid lastModifiedAt"
|
|
973
|
+
)
|
|
964
974
|
);
|
|
965
975
|
});
|
|
966
976
|
|
|
967
|
-
it("rejects non-numeric string for
|
|
977
|
+
it("rejects non-numeric string for lastModifiedAt", async () => {
|
|
968
978
|
const app = await getApp({ disableCsrf: true });
|
|
969
979
|
const loginCookie = await getAdminLoginCookie();
|
|
970
980
|
await request(app)
|
|
@@ -972,14 +982,17 @@ describe("SQL injection protection", () => {
|
|
|
972
982
|
.set("Cookie", loginCookie)
|
|
973
983
|
.send({
|
|
974
984
|
loadUntil: new Date().valueOf(),
|
|
975
|
-
syncInfos: { books: {
|
|
985
|
+
syncInfos: { books: { lastModifiedAt: "abc" } },
|
|
976
986
|
})
|
|
977
987
|
.expect(
|
|
978
|
-
respondJsonWith(
|
|
988
|
+
respondJsonWith(
|
|
989
|
+
400,
|
|
990
|
+
(resp) => resp.error === "Invalid lastModifiedAt"
|
|
991
|
+
)
|
|
979
992
|
);
|
|
980
993
|
});
|
|
981
994
|
|
|
982
|
-
it("rejects float
|
|
995
|
+
it("rejects float lastModifiedAt", async () => {
|
|
983
996
|
const app = await getApp({ disableCsrf: true });
|
|
984
997
|
const loginCookie = await getAdminLoginCookie();
|
|
985
998
|
await request(app)
|
|
@@ -987,10 +1000,13 @@ describe("SQL injection protection", () => {
|
|
|
987
1000
|
.set("Cookie", loginCookie)
|
|
988
1001
|
.send({
|
|
989
1002
|
loadUntil: new Date().valueOf(),
|
|
990
|
-
syncInfos: { books: {
|
|
1003
|
+
syncInfos: { books: { lastModifiedAt: 1.5 } },
|
|
991
1004
|
})
|
|
992
1005
|
.expect(
|
|
993
|
-
respondJsonWith(
|
|
1006
|
+
respondJsonWith(
|
|
1007
|
+
400,
|
|
1008
|
+
(resp) => resp.error === "Invalid lastModifiedAt"
|
|
1009
|
+
)
|
|
994
1010
|
);
|
|
995
1011
|
});
|
|
996
1012
|
|
|
@@ -1004,7 +1020,7 @@ describe("SQL injection protection", () => {
|
|
|
1004
1020
|
.set("Cookie", loginCookie)
|
|
1005
1021
|
.send({
|
|
1006
1022
|
loadUntil: new Date().valueOf(),
|
|
1007
|
-
syncInfos: { books: {
|
|
1023
|
+
syncInfos: { books: { lastModifiedAt: 0, syncFrom: "not-a-date" } },
|
|
1008
1024
|
})
|
|
1009
1025
|
.expect(
|
|
1010
1026
|
respondJsonWith(400, (resp) => resp.error === "Invalid syncFrom")
|
|
@@ -1020,7 +1036,7 @@ describe("SQL injection protection", () => {
|
|
|
1020
1036
|
.send({
|
|
1021
1037
|
loadUntil: new Date().valueOf(),
|
|
1022
1038
|
syncInfos: {
|
|
1023
|
-
books: {
|
|
1039
|
+
books: { lastModifiedAt: 0, syncFrom: "0); SELECT pg_sleep(5)--" },
|
|
1024
1040
|
},
|
|
1025
1041
|
})
|
|
1026
1042
|
.expect(
|
|
@@ -1038,7 +1054,7 @@ describe("SQL injection protection", () => {
|
|
|
1038
1054
|
.set("Cookie", loginCookie)
|
|
1039
1055
|
.send({
|
|
1040
1056
|
loadUntil: "not-a-date",
|
|
1041
|
-
syncInfos: { books: {
|
|
1057
|
+
syncInfos: { books: { lastModifiedAt: 0 } },
|
|
1042
1058
|
})
|
|
1043
1059
|
.expect(
|
|
1044
1060
|
respondJsonWith(400, (resp) => resp.error === "Invalid syncUntil")
|
|
@@ -1113,7 +1129,7 @@ describe("SQL injection protection", () => {
|
|
|
1113
1129
|
|
|
1114
1130
|
// --- regression: valid requests still succeed ---
|
|
1115
1131
|
|
|
1116
|
-
it("valid
|
|
1132
|
+
it("valid lastModifiedAt value still works", async () => {
|
|
1117
1133
|
const app = await getApp({ disableCsrf: true });
|
|
1118
1134
|
const loginCookie = await getAdminLoginCookie();
|
|
1119
1135
|
const resp = await request(app)
|
|
@@ -1121,7 +1137,7 @@ describe("SQL injection protection", () => {
|
|
|
1121
1137
|
.set("Cookie", loginCookie)
|
|
1122
1138
|
.send({
|
|
1123
1139
|
loadUntil: new Date().valueOf(),
|
|
1124
|
-
syncInfos: { books: {
|
|
1140
|
+
syncInfos: { books: { lastModifiedAt: 0 } },
|
|
1125
1141
|
});
|
|
1126
1142
|
expect(resp.status).toBe(200);
|
|
1127
1143
|
expect(resp._body.books).toBeDefined();
|
|
@@ -1135,7 +1151,7 @@ describe("SQL injection protection", () => {
|
|
|
1135
1151
|
.set("Cookie", loginCookie)
|
|
1136
1152
|
.send({
|
|
1137
1153
|
loadUntil: new Date().valueOf(),
|
|
1138
|
-
syncInfos: { books: {
|
|
1154
|
+
syncInfos: { books: { lastModifiedAt: 0, syncFrom: 1000 } },
|
|
1139
1155
|
});
|
|
1140
1156
|
expect(resp.status).toBe(200);
|
|
1141
1157
|
});
|
|
@@ -1322,7 +1338,7 @@ describe("deletes authorization with ownership_formula", () => {
|
|
|
1322
1338
|
expect(resp.status).toBe(200);
|
|
1323
1339
|
const deletes = resp._body.deletes?.sync_owned || [];
|
|
1324
1340
|
expect(deletes.length).toBe(1);
|
|
1325
|
-
expect(deletes[0].ref).toBe(itemId);
|
|
1341
|
+
expect(Number(deletes[0].ref)).toBe(itemId);
|
|
1326
1342
|
});
|
|
1327
1343
|
|
|
1328
1344
|
it("direct formula: non-owner does not see deleted rows", async () => {
|
|
@@ -1373,7 +1389,7 @@ describe("deletes authorization with ownership_formula", () => {
|
|
|
1373
1389
|
expect(resp.status).toBe(200);
|
|
1374
1390
|
const deletes = resp._body.deletes?.sync_child || [];
|
|
1375
1391
|
expect(deletes.length).toBe(1);
|
|
1376
|
-
expect(deletes[0].ref).toBe(childId);
|
|
1392
|
+
expect(Number(deletes[0].ref)).toBe(childId);
|
|
1377
1393
|
});
|
|
1378
1394
|
|
|
1379
1395
|
it("join formula: non-owner does not see deleted child rows", async () => {
|
|
@@ -1613,7 +1629,7 @@ describe("load_changes authorization with ownership_formula", () => {
|
|
|
1613
1629
|
.send({
|
|
1614
1630
|
loadUntil: loadUntil.valueOf(),
|
|
1615
1631
|
syncInfos: {
|
|
1616
|
-
lc_owned: {
|
|
1632
|
+
lc_owned: { lastModifiedAt: 0 },
|
|
1617
1633
|
},
|
|
1618
1634
|
});
|
|
1619
1635
|
expect(resp.status).toBe(200);
|
|
@@ -1635,7 +1651,7 @@ describe("load_changes authorization with ownership_formula", () => {
|
|
|
1635
1651
|
.send({
|
|
1636
1652
|
loadUntil: loadUntil.valueOf(),
|
|
1637
1653
|
syncInfos: {
|
|
1638
|
-
lc_owned: {
|
|
1654
|
+
lc_owned: { lastModifiedAt: 0 },
|
|
1639
1655
|
},
|
|
1640
1656
|
});
|
|
1641
1657
|
expect(resp.status).toBe(200);
|
|
@@ -1661,7 +1677,7 @@ describe("load_changes authorization with ownership_formula", () => {
|
|
|
1661
1677
|
.send({
|
|
1662
1678
|
loadUntil: loadUntil.valueOf(),
|
|
1663
1679
|
syncInfos: {
|
|
1664
|
-
lc_child: {
|
|
1680
|
+
lc_child: { lastModifiedAt: 0 },
|
|
1665
1681
|
},
|
|
1666
1682
|
});
|
|
1667
1683
|
expect(resp.status).toBe(200);
|
|
@@ -1687,7 +1703,7 @@ describe("load_changes authorization with ownership_formula", () => {
|
|
|
1687
1703
|
.send({
|
|
1688
1704
|
loadUntil: loadUntil.valueOf(),
|
|
1689
1705
|
syncInfos: {
|
|
1690
|
-
lc_child: {
|
|
1706
|
+
lc_child: { lastModifiedAt: 0 },
|
|
1691
1707
|
},
|
|
1692
1708
|
});
|
|
1693
1709
|
expect(resp.status).toBe(200);
|
|
@@ -1712,7 +1728,7 @@ describe("load_changes authorization with ownership_formula", () => {
|
|
|
1712
1728
|
.send({
|
|
1713
1729
|
loadUntil: loadUntil.valueOf(),
|
|
1714
1730
|
syncInfos: {
|
|
1715
|
-
lc_owned: {
|
|
1731
|
+
lc_owned: { lastModifiedAt: 0, syncFrom: syncFrom.valueOf() },
|
|
1716
1732
|
},
|
|
1717
1733
|
});
|
|
1718
1734
|
expect(resp.status).toBe(200);
|
|
@@ -1737,7 +1753,7 @@ describe("load_changes authorization with ownership_formula", () => {
|
|
|
1737
1753
|
.send({
|
|
1738
1754
|
loadUntil: loadUntil.valueOf(),
|
|
1739
1755
|
syncInfos: {
|
|
1740
|
-
lc_owned: {
|
|
1756
|
+
lc_owned: { lastModifiedAt: 0, syncFrom: syncFrom.valueOf() },
|
|
1741
1757
|
},
|
|
1742
1758
|
});
|
|
1743
1759
|
expect(resp.status).toBe(200);
|