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.
**