From 74ea6a2d90164b50de3539a85cf5f0c8d11c8b25 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Thu, 31 Oct 2024 11:16:44 -0500 Subject: [PATCH] CE-1887 - Add MetaDataFilter to the QInstance and MetaDataAction --- .../metadata/AllowAllMetaDataFilter.java | 92 +++++++++++++ .../core/actions/metadata/MetaDataAction.java | 114 +++++++++++++++- .../metadata/MetaDataFilterInterface.java | 64 +++++++++ .../core/instances/QInstanceValidator.java | 15 +++ .../core/model/metadata/QInstance.java | 34 +++++ .../actions/metadata/MetaDataActionTest.java | 122 ++++++++++++++++++ .../instances/QInstanceValidatorTest.java | 16 +++ 7 files changed, 451 insertions(+), 6 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/AllowAllMetaDataFilter.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataFilterInterface.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/AllowAllMetaDataFilter.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/AllowAllMetaDataFilter.java new file mode 100644 index 00000000..c64c8954 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/AllowAllMetaDataFilter.java @@ -0,0 +1,92 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.actions.metadata; + + +import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; +import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** a default implementation of MetaDataFilterInterface, that allows all the things + *******************************************************************************/ +public class AllowAllMetaDataFilter implements MetaDataFilterInterface +{ + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowTable(MetaDataInput input, QTableMetaData table) + { + return (true); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowProcess(MetaDataInput input, QProcessMetaData process) + { + return (true); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowReport(MetaDataInput input, QReportMetaData report) + { + return (true); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowApp(MetaDataInput input, QAppMetaData app) + { + return (true); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowWidget(MetaDataInput input, QWidgetMetaDataInterface widget) + { + return (true); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataAction.java index b1f6b52b..56c76928 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataAction.java @@ -28,13 +28,18 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.kingsrook.qqq.backend.core.actions.ActionHelper; +import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader; import com.kingsrook.qqq.backend.core.actions.permissions.PermissionCheckResult; import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper; import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.exceptions.QRuntimeException; +import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput; import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput; import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNode; import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData; @@ -49,6 +54,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; +import com.kingsrook.qqq.backend.core.utils.memoization.Memoization; /******************************************************************************* @@ -57,6 +63,12 @@ import com.kingsrook.qqq.backend.core.utils.CollectionUtils; *******************************************************************************/ public class MetaDataAction { + private static final QLogger LOG = QLogger.getLogger(MetaDataAction.class); + + private static Memoization metaDataFilterMemoization = new Memoization<>(); + + + /******************************************************************************* ** *******************************************************************************/ @@ -64,10 +76,10 @@ public class MetaDataAction { ActionHelper.validateSession(metaDataInput); - // todo pre-customization - just get to modify the request? - MetaDataOutput metaDataOutput = new MetaDataOutput(); + MetaDataOutput metaDataOutput = new MetaDataOutput(); + Map treeNodes = new LinkedHashMap<>(); - Map treeNodes = new LinkedHashMap<>(); + MetaDataFilterInterface filter = getMetaDataFilter(); ///////////////////////////////////// // map tables to frontend metadata // @@ -78,6 +90,11 @@ public class MetaDataAction String tableName = entry.getKey(); QTableMetaData table = entry.getValue(); + if(!filter.allowTable(metaDataInput, table)) + { + continue; + } + PermissionCheckResult permissionResult = PermissionsHelper.getPermissionCheckResult(metaDataInput, table); if(permissionResult.equals(PermissionCheckResult.DENY_HIDE)) { @@ -102,6 +119,11 @@ public class MetaDataAction String processName = entry.getKey(); QProcessMetaData process = entry.getValue(); + if(!filter.allowProcess(metaDataInput, process)) + { + continue; + } + PermissionCheckResult permissionResult = PermissionsHelper.getPermissionCheckResult(metaDataInput, process); if(permissionResult.equals(PermissionCheckResult.DENY_HIDE)) { @@ -122,6 +144,11 @@ public class MetaDataAction String reportName = entry.getKey(); QReportMetaData report = entry.getValue(); + if(!filter.allowReport(metaDataInput, report)) + { + continue; + } + PermissionCheckResult permissionResult = PermissionsHelper.getPermissionCheckResult(metaDataInput, report); if(permissionResult.equals(PermissionCheckResult.DENY_HIDE)) { @@ -142,6 +169,11 @@ public class MetaDataAction String widgetName = entry.getKey(); QWidgetMetaDataInterface widget = entry.getValue(); + if(!filter.allowWidget(metaDataInput, widget)) + { + continue; + } + PermissionCheckResult permissionResult = PermissionsHelper.getPermissionCheckResult(metaDataInput, widget); if(permissionResult.equals(PermissionCheckResult.DENY_HIDE)) { @@ -174,9 +206,19 @@ public class MetaDataAction continue; } - apps.put(appName, new QFrontendAppMetaData(app, metaDataOutput)); - treeNodes.put(appName, new AppTreeNode(app)); + if(!filter.allowApp(metaDataInput, app)) + { + continue; + } + ////////////////////////////////////// + // build the frontend-app meta-data // + ////////////////////////////////////// + QFrontendAppMetaData frontendAppMetaData = new QFrontendAppMetaData(app, metaDataOutput); + + ///////////////////////////////////////// + // add children (if they're permitted) // + ///////////////////////////////////////// if(CollectionUtils.nullSafeHasContents(app.getChildren())) { for(QAppChildMetaData child : app.getChildren()) @@ -190,9 +232,42 @@ public class MetaDataAction } } - apps.get(appName).addChild(new AppTreeNode(child)); + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // if the child was filtered away, so it isn't in its corresponding map, then don't include it here // + ////////////////////////////////////////////////////////////////////////////////////////////////////// + if(child instanceof QTableMetaData table && !tables.containsKey(table.getName())) + { + continue; + } + if(child instanceof QProcessMetaData process && !processes.containsKey(process.getName())) + { + continue; + } + if(child instanceof QReportMetaData report && !reports.containsKey(report.getName())) + { + continue; + } + if(child instanceof QAppMetaData childApp && !apps.containsKey(childApp.getName())) + { + // continue; + } + + frontendAppMetaData.addChild(new AppTreeNode(child)); } } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // if the app ended up having no children, then discard it // + // todo - i think this was wrong, because it didn't take into account ... something nested maybe... // + ////////////////////////////////////////////////////////////////////////////////////////////////////// + if(CollectionUtils.nullSafeIsEmpty(frontendAppMetaData.getChildren()) && CollectionUtils.nullSafeIsEmpty(frontendAppMetaData.getWidgets())) + { + // LOG.debug("Discarding empty app", logPair("name", frontendAppMetaData.getName())); + // continue; + } + + apps.put(appName, frontendAppMetaData); + treeNodes.put(appName, new AppTreeNode(app)); } metaDataOutput.setApps(apps); @@ -228,6 +303,33 @@ public class MetaDataAction + /*************************************************************************** + ** + ***************************************************************************/ + private MetaDataFilterInterface getMetaDataFilter() + { + return metaDataFilterMemoization.getResult(QContext.getQInstance(), i -> + { + MetaDataFilterInterface filter = null; + QCodeReference metaDataFilterReference = QContext.getQInstance().getMetaDataFilter(); + if(metaDataFilterReference != null) + { + filter = QCodeLoader.getAdHoc(MetaDataFilterInterface.class, metaDataFilterReference); + LOG.debug("Using new meta-data filter of type: " + filter.getClass().getSimpleName()); + } + + if(filter == null) + { + filter = new AllowAllMetaDataFilter(); + LOG.debug("Using new default (allow-all) meta-data filter"); + } + + return (filter); + }).orElseThrow(() -> new QRuntimeException("Error getting metaDataFilter")); + } + + + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataFilterInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataFilterInterface.java new file mode 100644 index 00000000..a7abb74d --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataFilterInterface.java @@ -0,0 +1,64 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.actions.metadata; + + +import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; +import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** + *******************************************************************************/ +public interface MetaDataFilterInterface +{ + + /*************************************************************************** + ** + ***************************************************************************/ + boolean allowTable(MetaDataInput input, QTableMetaData table); + + /*************************************************************************** + ** + ***************************************************************************/ + boolean allowProcess(MetaDataInput input, QProcessMetaData process); + + /*************************************************************************** + ** + ***************************************************************************/ + boolean allowReport(MetaDataInput input, QReportMetaData report); + + /*************************************************************************** + ** + ***************************************************************************/ + boolean allowApp(MetaDataInput input, QAppMetaData app); + + /*************************************************************************** + ** + ***************************************************************************/ + boolean allowWidget(MetaDataInput input, QWidgetMetaDataInterface widget); + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java index 9ceacae1..58618c3e 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java @@ -43,6 +43,7 @@ import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationHandler import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers; import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer; import com.kingsrook.qqq.backend.core.actions.metadata.JoinGraph; +import com.kingsrook.qqq.backend.core.actions.metadata.MetaDataFilterInterface; import com.kingsrook.qqq.backend.core.actions.processes.BackendStep; import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportCustomRecordSourceInterface; import com.kingsrook.qqq.backend.core.actions.scripts.TestScriptActionInterface; @@ -186,6 +187,7 @@ public class QInstanceValidator ////////////////////////////////////////////////////////////////////////// try { + validateInstanceAttributes(qInstance); validateBackends(qInstance); validateAuthentication(qInstance); validateAutomationProviders(qInstance); @@ -226,6 +228,19 @@ public class QInstanceValidator + /*************************************************************************** + ** + ***************************************************************************/ + private void validateInstanceAttributes(QInstance qInstance) + { + if(qInstance.getMetaDataFilter() != null) + { + validateSimpleCodeReference("Instance metaDataFilter ", qInstance.getMetaDataFilter(), MetaDataFilterInterface.class); + } + } + + + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java index fea69209..a61971c8 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java @@ -43,6 +43,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.audits.QAuditRules; import com.kingsrook.qqq.backend.core.model.metadata.authentication.QAuthenticationMetaData; import com.kingsrook.qqq.backend.core.model.metadata.automation.QAutomationProviderMetaData; import com.kingsrook.qqq.backend.core.model.metadata.branding.QBrandingMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNode; import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNodeType; @@ -113,6 +114,8 @@ public class QInstance private QPermissionRules defaultPermissionRules = QPermissionRules.defaultInstance(); private QAuditRules defaultAuditRules = QAuditRules.defaultInstanceLevelNone(); + private QCodeReference metaDataFilter = null; + ////////////////////////////////////////////////////////////////////////////////////// // todo - lock down the object (no more changes allowed) after it's been validated? // // if doing so, may need to copy all of the collections into read-only versions... // @@ -1485,4 +1488,35 @@ public class QInstance QInstanceHelpContentManager.removeHelpContentByRoleSetFromList(roles, listForSlot); } + + /******************************************************************************* + ** Getter for metaDataFilter + *******************************************************************************/ + public QCodeReference getMetaDataFilter() + { + return (this.metaDataFilter); + } + + + + /******************************************************************************* + ** Setter for metaDataFilter + *******************************************************************************/ + public void setMetaDataFilter(QCodeReference metaDataFilter) + { + this.metaDataFilter = metaDataFilter; + } + + + + /******************************************************************************* + ** Fluent setter for metaDataFilter + *******************************************************************************/ + public QInstance withMetaDataFilter(QCodeReference metaDataFilter) + { + this.metaDataFilter = metaDataFilter; + return (this); + } + + } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataActionTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataActionTest.java index 44d6e8e6..58d85069 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataActionTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/metadata/MetaDataActionTest.java @@ -31,9 +31,13 @@ import java.util.stream.Collectors; import com.kingsrook.qqq.backend.core.BaseTest; import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.logging.QCollectingLogger; +import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput; import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNode; import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNodeType; import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData; @@ -41,9 +45,13 @@ import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMe import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendReportMetaData; import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendWidgetMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; import com.kingsrook.qqq.backend.core.model.metadata.permissions.DenyBehavior; import com.kingsrook.qqq.backend.core.model.metadata.permissions.PermissionLevel; import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.utils.TestUtils; import org.junit.jupiter.api.Test; @@ -350,4 +358,118 @@ class MetaDataActionTest extends BaseTest assertTrue(personMemoryTable.getDeletePermission()); } + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testFilter() throws QException + { + QCollectingLogger collectingLogger = QLogger.activateCollectingLoggerForClass(MetaDataAction.class); + + ////////////////////////////////////////////////////// + // run default version, and assert tables are found // + ////////////////////////////////////////////////////// + MetaDataOutput result = new MetaDataAction().execute(new MetaDataInput()); + assertFalse(result.getTables().isEmpty(), "should be some tables"); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // run again (with the same instance as before) to assert about memoization of the filter based on the QInstance // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + new MetaDataAction().execute(new MetaDataInput()); + assertThat(collectingLogger.getCollectedMessages()).filteredOn(clm -> clm.getMessage().contains("Using new default")).hasSize(1); + + ///////////////////////////////////////////////////////////// + // set up new instance to use a custom filter, to deny all // + ///////////////////////////////////////////////////////////// + QInstance instance = TestUtils.defineInstance(); + instance.setMetaDataFilter(new QCodeReference(DenyAllFilter.class)); + reInitInstanceInContext(instance); + + ///////////////////////////////////////////////////// + // re-run, and assert all tables are filtered away // + ///////////////////////////////////////////////////// + result = new MetaDataAction().execute(new MetaDataInput()); + assertTrue(result.getTables().isEmpty(), "should be no tables"); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // run again (with the same instance as before) to assert about memoization of the filter based on the QInstance // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + new MetaDataAction().execute(new MetaDataInput()); + assertThat(collectingLogger.getCollectedMessages()).filteredOn(clm -> clm.getMessage().contains("filter of type: DenyAllFilter")).hasSize(1); + + QLogger.deactivateCollectingLoggerForClass(MetaDataAction.class); + + //////////////////////////////////////////////////////////// + // run now with the AllowAllFilter, confirm we get tables // + //////////////////////////////////////////////////////////// + instance = TestUtils.defineInstance(); + instance.setMetaDataFilter(new QCodeReference(AllowAllMetaDataFilter.class)); + reInitInstanceInContext(instance); + result = new MetaDataAction().execute(new MetaDataInput()); + assertFalse(result.getTables().isEmpty(), "should be some tables"); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public static class DenyAllFilter implements MetaDataFilterInterface + { + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowTable(MetaDataInput input, QTableMetaData table) + { + return false; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowProcess(MetaDataInput input, QProcessMetaData process) + { + return false; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowReport(MetaDataInput input, QReportMetaData report) + { + return false; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowApp(MetaDataInput input, QAppMetaData app) + { + return false; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean allowWidget(MetaDataInput input, QWidgetMetaDataInterface widget) + { + return false; + } + } + } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java index 612d575b..89c69734 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java @@ -38,6 +38,7 @@ import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers; import com.kingsrook.qqq.backend.core.actions.dashboard.PersonsByCreateDateBarChart; import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer; import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.ParentWidgetRenderer; +import com.kingsrook.qqq.backend.core.actions.metadata.AllowAllMetaDataFilter; import com.kingsrook.qqq.backend.core.actions.processes.CancelProcessActionTest; import com.kingsrook.qqq.backend.core.actions.reporting.RecordPipe; import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportCustomRecordSourceInterface; @@ -139,6 +140,21 @@ public class QInstanceValidatorTest extends BaseTest + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testMetaDataFilter() + { + assertValidationFailureReasons((qInstance) -> qInstance.setMetaDataFilter(new QCodeReference(QInstanceValidator.class)), + "Instance metaDataFilter CodeReference is not of the expected type"); + + assertValidationSuccess((qInstance) -> qInstance.setMetaDataFilter(new QCodeReference(AllowAllMetaDataFilter.class))); + assertValidationSuccess((qInstance) -> qInstance.setMetaDataFilter(null)); + } + + + /******************************************************************************* ** Test an instance with null backends - should throw. **