mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Change tables PVS to be custom type, respecting session permissions; refactor some PVS search logic to make custom implementations a little better
This commit is contained in:
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.actions.values;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
|
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
|
||||||
@ -74,6 +75,29 @@ public interface QCustomPossibleValueProvider<T extends Serializable>
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
default List<QPossibleValue<T>> _defaultSearch(SearchPossibleValueSourceInput input, List<QPossibleValue<T>> possibleValues)
|
||||||
|
{
|
||||||
|
SearchPossibleValueSourceAction.PreparedSearchPossibleValueSourceInput preparedInput = SearchPossibleValueSourceAction.prepareSearchPossibleValueSourceInput(input);
|
||||||
|
|
||||||
|
List<QPossibleValue<T>> rs = new ArrayList<>();
|
||||||
|
|
||||||
|
for(QPossibleValue<T> possibleValue : possibleValues)
|
||||||
|
{
|
||||||
|
if(possibleValue != null && SearchPossibleValueSourceAction.doesPossibleValueMatchSearchInput(possibleValue, preparedInput))
|
||||||
|
{
|
||||||
|
rs.add(possibleValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.sort(Comparator.nullsLast(Comparator.comparing((QPossibleValue<T> pv) -> pv.getLabel())));
|
||||||
|
|
||||||
|
return (rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -26,6 +26,7 @@ import java.io.Serializable;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -51,7 +52,6 @@ import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleVal
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
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.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
@ -108,60 +108,54 @@ public class SearchPossibleValueSourceAction
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
** record to store "computed" values as part of a possible-value search -
|
||||||
|
** e.g., ids type-convered, and lower-cased labels.
|
||||||
|
***************************************************************************/
|
||||||
|
public record PreparedSearchPossibleValueSourceInput(Collection<?> inputIdsAsCorrectType, Collection<String> lowerCaseLabels, String searchTerm) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
public static PreparedSearchPossibleValueSourceInput prepareSearchPossibleValueSourceInput(SearchPossibleValueSourceInput input)
|
||||||
|
{
|
||||||
|
QPossibleValueSource possibleValueSource = QContext.getQInstance().getPossibleValueSource(input.getPossibleValueSourceName());
|
||||||
|
List<?> inputIdsAsCorrectType = convertInputIdsToPossibleValueSourceIdType(possibleValueSource, input.getIdList());
|
||||||
|
|
||||||
|
Set<String> lowerCaseLabels = null;
|
||||||
|
if(input.getLabelList() != null)
|
||||||
|
{
|
||||||
|
lowerCaseLabels = input.getLabelList().stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(l -> l.toLowerCase())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (new PreparedSearchPossibleValueSourceInput(inputIdsAsCorrectType, lowerCaseLabels, input.getSearchTerm()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private SearchPossibleValueSourceOutput searchPossibleValueEnum(SearchPossibleValueSourceInput input, QPossibleValueSource possibleValueSource)
|
private SearchPossibleValueSourceOutput searchPossibleValueEnum(SearchPossibleValueSourceInput input, QPossibleValueSource possibleValueSource)
|
||||||
{
|
{
|
||||||
|
PreparedSearchPossibleValueSourceInput preparedSearchPossibleValueSourceInput = prepareSearchPossibleValueSourceInput(input);
|
||||||
|
|
||||||
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceOutput();
|
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceOutput();
|
||||||
List<Serializable> matchingIds = new ArrayList<>();
|
List<Serializable> matchingIds = new ArrayList<>();
|
||||||
|
|
||||||
List<?> inputIdsAsCorrectType = convertInputIdsToEnumIdType(possibleValueSource, input.getIdList());
|
|
||||||
Set<String> labels = null;
|
|
||||||
|
|
||||||
for(QPossibleValue<?> possibleValue : possibleValueSource.getEnumValues())
|
for(QPossibleValue<?> possibleValue : possibleValueSource.getEnumValues())
|
||||||
{
|
{
|
||||||
boolean match = false;
|
boolean match = doesPossibleValueMatchSearchInput(possibleValue, preparedSearchPossibleValueSourceInput);
|
||||||
|
|
||||||
if(input.getIdList() != null)
|
|
||||||
{
|
|
||||||
if(inputIdsAsCorrectType.contains(possibleValue.getId()))
|
|
||||||
{
|
|
||||||
match = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(input.getLabelList() != null)
|
|
||||||
{
|
|
||||||
if(labels == null)
|
|
||||||
{
|
|
||||||
labels = input.getLabelList().stream().filter(Objects::nonNull).map(l -> l.toLowerCase()).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(labels.contains(possibleValue.getLabel().toLowerCase()))
|
|
||||||
{
|
|
||||||
match = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(StringUtils.hasContent(input.getSearchTerm()))
|
|
||||||
{
|
|
||||||
match = (Objects.equals(ValueUtils.getValueAsString(possibleValue.getId()).toLowerCase(), input.getSearchTerm().toLowerCase())
|
|
||||||
|| possibleValue.getLabel().toLowerCase().startsWith(input.getSearchTerm().toLowerCase()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
match = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(match)
|
if(match)
|
||||||
{
|
{
|
||||||
matchingIds.add((Serializable) possibleValue.getId());
|
matchingIds.add(possibleValue.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo - skip & limit?
|
|
||||||
// todo - default filter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<QPossibleValue<?>> qPossibleValues = possibleValueTranslator.buildTranslatedPossibleValueList(possibleValueSource, matchingIds);
|
List<QPossibleValue<?>> qPossibleValues = possibleValueTranslator.buildTranslatedPossibleValueList(possibleValueSource, matchingIds);
|
||||||
@ -172,42 +166,84 @@ public class SearchPossibleValueSourceAction
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
public static boolean doesPossibleValueMatchSearchInput(QPossibleValue<?> possibleValue, PreparedSearchPossibleValueSourceInput input)
|
||||||
|
{
|
||||||
|
boolean match = false;
|
||||||
|
|
||||||
|
if(input.inputIdsAsCorrectType() != null)
|
||||||
|
{
|
||||||
|
if(input.inputIdsAsCorrectType().contains(possibleValue.getId()))
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(input.lowerCaseLabels() != null)
|
||||||
|
{
|
||||||
|
if(input.lowerCaseLabels().contains(possibleValue.getLabel().toLowerCase()))
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(StringUtils.hasContent(input.searchTerm()))
|
||||||
|
{
|
||||||
|
match = (Objects.equals(ValueUtils.getValueAsString(possibleValue.getId()).toLowerCase(), input.searchTerm().toLowerCase())
|
||||||
|
|| possibleValue.getLabel().toLowerCase().startsWith(input.searchTerm().toLowerCase()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** The input list of ids might come through as a type that isn't the same as
|
** The input list of ids might come through as a type that isn't the same as
|
||||||
** the type of the ids in the enum (e.g., strings from a frontend, integers
|
** the type of the ids in the enum (e.g., strings from a frontend, integers
|
||||||
** in an enum). So, this method looks at the first id in the enum, and then
|
** in an enum). So, this method type-converts them.
|
||||||
** maps all the inputIds to be of the same type.
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private List<Object> convertInputIdsToEnumIdType(QPossibleValueSource possibleValueSource, List<Serializable> inputIdList)
|
private static List<Object> convertInputIdsToPossibleValueSourceIdType(QPossibleValueSource possibleValueSource, List<Serializable> inputIdList)
|
||||||
{
|
{
|
||||||
List<Object> rs = new ArrayList<>();
|
List<Object> rs = new ArrayList<>();
|
||||||
if(CollectionUtils.nullSafeIsEmpty(inputIdList))
|
|
||||||
|
if(inputIdList == null)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
else if(inputIdList.isEmpty())
|
||||||
{
|
{
|
||||||
return (rs);
|
return (rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object anIdFromTheEnum = possibleValueSource.getEnumValues().get(0).getId();
|
QFieldType type = possibleValueSource.getIdType();
|
||||||
|
|
||||||
for(Serializable inputId : inputIdList)
|
for(Serializable inputId : inputIdList)
|
||||||
{
|
{
|
||||||
Object properlyTypedId = null;
|
Object properlyTypedId = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(anIdFromTheEnum instanceof Integer)
|
if(type.equals(QFieldType.INTEGER))
|
||||||
{
|
{
|
||||||
properlyTypedId = ValueUtils.getValueAsInteger(inputId);
|
properlyTypedId = ValueUtils.getValueAsInteger(inputId);
|
||||||
}
|
}
|
||||||
else if(anIdFromTheEnum instanceof String)
|
else if(type.isStringLike())
|
||||||
{
|
{
|
||||||
properlyTypedId = ValueUtils.getValueAsString(inputId);
|
properlyTypedId = ValueUtils.getValueAsString(inputId);
|
||||||
}
|
}
|
||||||
else if(anIdFromTheEnum instanceof Boolean)
|
else if(type.equals(QFieldType.BOOLEAN))
|
||||||
{
|
{
|
||||||
properlyTypedId = ValueUtils.getValueAsBoolean(inputId);
|
properlyTypedId = ValueUtils.getValueAsBoolean(inputId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG.warn("Unexpected type [" + anIdFromTheEnum.getClass().getSimpleName() + "] for ids in enum: " + possibleValueSource.getName());
|
LOG.warn("Unexpected type [" + type + "] for ids in enum: " + possibleValueSource.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
@ -397,7 +433,7 @@ public class SearchPossibleValueSourceAction
|
|||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
String message = "Error sending searching custom possible value source [" + input.getPossibleValueSourceName() + "]";
|
String message = "Error searching custom possible value source [" + input.getPossibleValueSourceName() + "]";
|
||||||
LOG.warn(message, e);
|
LOG.warn(message, e);
|
||||||
throw (new QException(message));
|
throw (new QException(message));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2025. 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.tables;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionCheckResult;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.values.QCustomPossibleValueProvider;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class TablesCustomPossibleValueProvider implements QCustomPossibleValueProvider<String>
|
||||||
|
{
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QPossibleValue<String> getPossibleValue(Serializable idValue)
|
||||||
|
{
|
||||||
|
QTableMetaData table = QContext.getQInstance().getTable(ValueUtils.getValueAsString(idValue));
|
||||||
|
if(table != null && !table.getIsHidden())
|
||||||
|
{
|
||||||
|
PermissionCheckResult permissionCheckResult = PermissionsHelper.getPermissionCheckResult(new QueryInput(table.getName()), table);
|
||||||
|
if(PermissionCheckResult.ALLOW.equals(permissionCheckResult))
|
||||||
|
{
|
||||||
|
return (new QPossibleValue<>(table.getName(), table.getLabel()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
@Override
|
||||||
|
public List<QPossibleValue<String>> search(SearchPossibleValueSourceInput input) throws QException
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// build all of the possible values (note, will be filtered by user's permissions) //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
List<QPossibleValue<String>> allPossibleValues = new ArrayList<>();
|
||||||
|
for(QTableMetaData table : QContext.getQInstance().getTables().values())
|
||||||
|
{
|
||||||
|
QPossibleValue<String> possibleValue = getPossibleValue(table.getName());
|
||||||
|
if(possibleValue != null)
|
||||||
|
{
|
||||||
|
allPossibleValues.add(possibleValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _defaultSearch(input, allPossibleValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,17 +22,11 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.metadata.tables;
|
package com.kingsrook.qqq.backend.core.model.metadata.tables;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
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.possiblevalues.PVSValueFormatAndFields;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PVSValueFormatAndFields;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
|
||||||
import org.apache.commons.lang.BooleanUtils;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -51,22 +45,10 @@ public class TablesPossibleValueSourceMetaDataProvider
|
|||||||
{
|
{
|
||||||
QPossibleValueSource possibleValueSource = new QPossibleValueSource()
|
QPossibleValueSource possibleValueSource = new QPossibleValueSource()
|
||||||
.withName(NAME)
|
.withName(NAME)
|
||||||
.withType(QPossibleValueSourceType.ENUM)
|
.withType(QPossibleValueSourceType.CUSTOM)
|
||||||
|
.withCustomCodeReference(new QCodeReference(TablesCustomPossibleValueProvider.class))
|
||||||
.withValueFormatAndFields(PVSValueFormatAndFields.LABEL_ONLY);
|
.withValueFormatAndFields(PVSValueFormatAndFields.LABEL_ONLY);
|
||||||
|
|
||||||
List<QPossibleValue<?>> enumValues = new ArrayList<>();
|
|
||||||
for(QTableMetaData table : qInstance.getTables().values())
|
|
||||||
{
|
|
||||||
if(BooleanUtils.isNotTrue(table.getIsHidden()))
|
|
||||||
{
|
|
||||||
String label = StringUtils.hasContent(table.getLabel()) ? table.getLabel() : QInstanceEnricher.nameToLabel(table.getName());
|
|
||||||
enumValues.add(new QPossibleValue<>(table.getName(), label));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enumValues.sort(Comparator.comparing(QPossibleValue::getLabel));
|
|
||||||
|
|
||||||
possibleValueSource.withEnumValues(enumValues);
|
|
||||||
return (possibleValueSource);
|
return (possibleValueSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2025. 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.tables;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
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.model.actions.values.SearchPossibleValueSourceInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
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.possiblevalues.QPossibleValue;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for TablesCustomPossibleValueProvider
|
||||||
|
*******************************************************************************/
|
||||||
|
class TablesCustomPossibleValueProviderTest extends BaseTest
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@BeforeEach
|
||||||
|
void beforeEach()
|
||||||
|
{
|
||||||
|
QInstance qInstance = TestUtils.defineInstance();
|
||||||
|
|
||||||
|
qInstance.addTable(new QTableMetaData()
|
||||||
|
.withName("hidden")
|
||||||
|
.withIsHidden(true)
|
||||||
|
.withBackendName(TestUtils.MEMORY_BACKEND_NAME)
|
||||||
|
.withPrimaryKeyField("id")
|
||||||
|
.withField(new QFieldMetaData("id", QFieldType.INTEGER)));
|
||||||
|
|
||||||
|
qInstance.addTable(new QTableMetaData()
|
||||||
|
.withName("restricted")
|
||||||
|
.withPermissionRules(new QPermissionRules().withLevel(PermissionLevel.HAS_ACCESS_PERMISSION))
|
||||||
|
.withBackendName(TestUtils.MEMORY_BACKEND_NAME)
|
||||||
|
.withPrimaryKeyField("id")
|
||||||
|
.withField(new QFieldMetaData("id", QFieldType.INTEGER)));
|
||||||
|
|
||||||
|
qInstance.addPossibleValueSource(TablesPossibleValueSourceMetaDataProvider.defineTablesPossibleValueSource(qInstance));
|
||||||
|
|
||||||
|
QContext.init(qInstance, newSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testGetPossibleValue()
|
||||||
|
{
|
||||||
|
TablesCustomPossibleValueProvider provider = new TablesCustomPossibleValueProvider();
|
||||||
|
|
||||||
|
QPossibleValue<String> possibleValue = provider.getPossibleValue(TestUtils.TABLE_NAME_PERSON);
|
||||||
|
assertEquals(TestUtils.TABLE_NAME_PERSON, possibleValue.getId());
|
||||||
|
assertEquals("Person", possibleValue.getLabel());
|
||||||
|
|
||||||
|
assertNull(provider.getPossibleValue("no-such-table"));
|
||||||
|
assertNull(provider.getPossibleValue("hidden"));
|
||||||
|
assertNull(provider.getPossibleValue("restricted"));
|
||||||
|
|
||||||
|
QContext.getQSession().withPermission("restricted.hasAccess");
|
||||||
|
assertNotNull(provider.getPossibleValue("restricted"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testSearchPossibleValue() throws QException
|
||||||
|
{
|
||||||
|
TablesCustomPossibleValueProvider provider = new TablesCustomPossibleValueProvider();
|
||||||
|
|
||||||
|
List<QPossibleValue<String>> list = provider.search(new SearchPossibleValueSourceInput()
|
||||||
|
.withPossibleValueSourceName(TablesPossibleValueSourceMetaDataProvider.NAME));
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_PERSON));
|
||||||
|
assertThat(list).noneMatch(p -> p.getId().equals("no-such-table"));
|
||||||
|
assertThat(list).noneMatch(p -> p.getId().equals("hidden"));
|
||||||
|
assertThat(list).noneMatch(p -> p.getId().equals("restricted"));
|
||||||
|
assertNull(provider.getPossibleValue("restricted"));
|
||||||
|
|
||||||
|
list = provider.search(new SearchPossibleValueSourceInput()
|
||||||
|
.withPossibleValueSourceName(TablesPossibleValueSourceMetaDataProvider.NAME)
|
||||||
|
.withIdList(List.of(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_SHAPE, "hidden")));
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_PERSON));
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_SHAPE));
|
||||||
|
assertThat(list).noneMatch(p -> p.getId().equals("hidden"));
|
||||||
|
|
||||||
|
list = provider.search(new SearchPossibleValueSourceInput()
|
||||||
|
.withPossibleValueSourceName(TablesPossibleValueSourceMetaDataProvider.NAME)
|
||||||
|
.withLabelList(List.of("Person", "Shape", "Restricted")));
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_PERSON));
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_SHAPE));
|
||||||
|
assertThat(list).noneMatch(p -> p.getId().equals("restricted"));
|
||||||
|
|
||||||
|
list = provider.search(new SearchPossibleValueSourceInput()
|
||||||
|
.withPossibleValueSourceName(TablesPossibleValueSourceMetaDataProvider.NAME)
|
||||||
|
.withSearchTerm("restricted"));
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// add permission for restricted table //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
QContext.getQSession().withPermission("restricted.hasAccess");
|
||||||
|
list = provider.search(new SearchPossibleValueSourceInput()
|
||||||
|
.withPossibleValueSourceName(TablesPossibleValueSourceMetaDataProvider.NAME)
|
||||||
|
.withSearchTerm("restricted"));
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
|
||||||
|
list = provider.search(new SearchPossibleValueSourceInput()
|
||||||
|
.withPossibleValueSourceName(TablesPossibleValueSourceMetaDataProvider.NAME)
|
||||||
|
.withLabelList(List.of("Person", "Shape", "Restricted")));
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_PERSON));
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals(TestUtils.TABLE_NAME_SHAPE));
|
||||||
|
assertThat(list).anyMatch(p -> p.getId().equals("restricted"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user