mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Add check for records pre-delete action (for security and better errors); 404s and ids in 207s for bulk update & delete; ignore non-editable fields;
This commit is contained in:
@ -24,7 +24,11 @@ package com.kingsrook.qqq.backend.core.actions.tables;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.audits.DMLAuditAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
||||
@ -41,12 +45,14 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.audits.AuditLevel;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -57,6 +63,8 @@ public class DeleteAction
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(DeleteAction.class);
|
||||
|
||||
public static final String NOT_FOUND_ERROR_PREFIX = "No record was found to delete";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -68,7 +76,6 @@ public class DeleteAction
|
||||
|
||||
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend());
|
||||
// todo pre-customization - just get to modify the request?
|
||||
|
||||
if(CollectionUtils.nullSafeHasContents(deleteInput.getPrimaryKeys()) && deleteInput.getQueryFilter() != null)
|
||||
{
|
||||
@ -92,13 +99,24 @@ public class DeleteAction
|
||||
}
|
||||
}
|
||||
|
||||
List<QRecord> recordListForAudit = getRecordListForAuditIfNeeded(deleteInput);
|
||||
List<QRecord> recordListForAudit = getRecordListForAuditIfNeeded(deleteInput);
|
||||
List<QRecord> recordsWithValidationErrors = validateRecordsExistAndCanBeAccessed(deleteInput, recordListForAudit);
|
||||
|
||||
DeleteOutput deleteOutput = deleteInterface.execute(deleteInput);
|
||||
|
||||
manageAssociations(deleteInput);
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// merge the backend's output with any validation errors we found (whose ids wouldn't have gotten into the backend delete) //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
List<QRecord> outputRecordsWithErrors = deleteOutput.getRecordsWithErrors();
|
||||
if(outputRecordsWithErrors == null)
|
||||
{
|
||||
deleteOutput.setRecordsWithErrors(new ArrayList<>());
|
||||
outputRecordsWithErrors = deleteOutput.getRecordsWithErrors();
|
||||
}
|
||||
|
||||
// todo post-customization - can do whatever w/ the result if you want
|
||||
outputRecordsWithErrors.addAll(recordsWithValidationErrors);
|
||||
|
||||
manageAssociations(deleteInput);
|
||||
|
||||
new DMLAuditAction().execute(new DMLAuditInput().withTableActionInput(deleteInput).withRecordList(recordListForAudit));
|
||||
|
||||
@ -188,6 +206,84 @@ public class DeleteAction
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Note - the "can be accessed" part of this method name - it implies that
|
||||
** records that you can't see because of security - that they won't be found
|
||||
** by the query here, so it's the same to you as if they don't exist at all!
|
||||
**
|
||||
** This method, if it finds any missing records, will:
|
||||
** - remove those ids from the deleteInput
|
||||
** - create a QRecord with that id and a not-found error message.
|
||||
*******************************************************************************/
|
||||
private List<QRecord> validateRecordsExistAndCanBeAccessed(DeleteInput deleteInput, List<QRecord> oldRecordList) throws QException
|
||||
{
|
||||
List<QRecord> recordsWithErrors = new ArrayList<>();
|
||||
|
||||
QTableMetaData table = deleteInput.getTable();
|
||||
QFieldMetaData primaryKeyField = table.getField(table.getPrimaryKeyField());
|
||||
|
||||
Set<Serializable> primaryKeysToRemoveFromInput = new HashSet<>();
|
||||
|
||||
List<List<Serializable>> pages = CollectionUtils.getPages(deleteInput.getPrimaryKeys(), 1000);
|
||||
for(List<Serializable> page : pages)
|
||||
{
|
||||
List<Serializable> primaryKeysToLookup = new ArrayList<>();
|
||||
for(Serializable primaryKeyValue : page)
|
||||
{
|
||||
if(primaryKeyValue != null)
|
||||
{
|
||||
primaryKeysToLookup.add(primaryKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
Map<Serializable, QRecord> lookedUpRecords = new HashMap<>();
|
||||
if(CollectionUtils.nullSafeHasContents(oldRecordList))
|
||||
{
|
||||
for(QRecord record : oldRecordList)
|
||||
{
|
||||
lookedUpRecords.put(record.getValue(table.getPrimaryKeyField()), record);
|
||||
}
|
||||
}
|
||||
else if(!primaryKeysToLookup.isEmpty())
|
||||
{
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(table.getName());
|
||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, primaryKeysToLookup)));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
for(QRecord record : queryOutput.getRecords())
|
||||
{
|
||||
lookedUpRecords.put(record.getValue(table.getPrimaryKeyField()), record);
|
||||
}
|
||||
}
|
||||
|
||||
for(Serializable primaryKeyValue : page)
|
||||
{
|
||||
primaryKeyValue = ValueUtils.getValueAsFieldType(primaryKeyField.getType(), primaryKeyValue);
|
||||
if(!lookedUpRecords.containsKey(primaryKeyValue))
|
||||
{
|
||||
QRecord recordWithError = new QRecord();
|
||||
recordsWithErrors.add(recordWithError);
|
||||
recordWithError.setValue(primaryKeyField.getName(), primaryKeyValue);
|
||||
recordWithError.addError(NOT_FOUND_ERROR_PREFIX + " for " + primaryKeyField.getLabel() + " = " + primaryKeyValue);
|
||||
primaryKeysToRemoveFromInput.add(primaryKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// do one mass removal of any bad keys from the input key list //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
if(!primaryKeysToRemoveFromInput.isEmpty())
|
||||
{
|
||||
deleteInput.getPrimaryKeys().removeAll(primaryKeysToRemoveFromInput);
|
||||
primaryKeysToRemoveFromInput.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return (recordsWithErrors);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** For an implementation that doesn't support a queryFilter as its input,
|
||||
** but a scenario where a query filter was passed in - run the query, to
|
||||
|
@ -72,6 +72,8 @@ public class UpdateAction
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(UpdateAction.class);
|
||||
|
||||
public static final String NOT_FOUND_ERROR_PREFIX = "No record was found to update";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -193,7 +195,7 @@ public class UpdateAction
|
||||
|
||||
if(!lookedUpRecords.containsKey(value))
|
||||
{
|
||||
record.addError("No record was found to update for " + primaryKeyField.getLabel() + " = " + value);
|
||||
record.addError(NOT_FOUND_ERROR_PREFIX + " for " + primaryKeyField.getLabel() + " = " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.MutableList;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -101,7 +102,10 @@ public class DeleteInput extends AbstractTableActionInput
|
||||
*******************************************************************************/
|
||||
public void setPrimaryKeys(List<Serializable> primaryKeys)
|
||||
{
|
||||
this.primaryKeys = primaryKeys;
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// the action may edit this list (e.g., to remove keys w/ errors), so wrap it in MutableList //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
this.primaryKeys = new MutableList<>(primaryKeys);
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +116,7 @@ public class DeleteInput extends AbstractTableActionInput
|
||||
*******************************************************************************/
|
||||
public DeleteInput withPrimaryKeys(List<Serializable> primaryKeys)
|
||||
{
|
||||
this.primaryKeys = primaryKeys;
|
||||
setPrimaryKeys(primaryKeys);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
@ -348,7 +348,7 @@ public class BackendQueryFilterUtils
|
||||
}
|
||||
}
|
||||
|
||||
if(!criterion.getValues().contains(value))
|
||||
if(value == null || !criterion.getValues().contains(value))
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
@ -27,10 +27,15 @@ import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
@SuppressWarnings({ "checkstyle:javadoc", "DanglingJavadoc" })
|
||||
/*******************************************************************************
|
||||
** Map.of is "great", but annoying because it makes unmodifiable maps, and it
|
||||
** NPE's on nulls... So, replace it with this, which returns HashMaps, which
|
||||
** "don't suck"
|
||||
** NPE's on nulls... So, replace it with this, which returns HashMaps (or maps
|
||||
** of the type you choose).
|
||||
**
|
||||
** Can use it 2 ways:
|
||||
** MapBuilder.of(key, value, key2, value2, ...) => Map (a HashMap)
|
||||
** MapBuilder.<KeyType ValueType>of(SomeMap::new).with(key, value).with(key2, value2)...build() => SomeMap (the type you specify)
|
||||
*******************************************************************************/
|
||||
public class MapBuilder<K, V>
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.actions.tables;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
@ -40,8 +41,9 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.audits.AuditLevel;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.audits.QAuditRules;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@ -57,8 +59,6 @@ class DeleteActionTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** At the core level, there isn't much that can be asserted, as it uses the
|
||||
** mock implementation - just confirming that all of the "wiring" works.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
@ -66,11 +66,17 @@ class DeleteActionTest extends BaseTest
|
||||
{
|
||||
DeleteInput request = new DeleteInput();
|
||||
request.setTableName("person");
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// the mock backend - it'll find a record for id=1, but not for id=2 - so we can test both a found & deleted, and a not-found here //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
request.setPrimaryKeys(List.of(1, 2));
|
||||
DeleteOutput result = new DeleteAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.getDeletedRecordCount());
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(result.getRecordsWithErrors()));
|
||||
assertEquals(1, result.getDeletedRecordCount());
|
||||
assertEquals(1, result.getRecordsWithErrors().size());
|
||||
assertEquals(2, result.getRecordsWithErrors().get(0).getValueInteger("id"));
|
||||
assertEquals("No record was found to delete for Id = 2", result.getRecordsWithErrors().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
|
||||
@ -295,4 +301,102 @@ class DeleteActionTest extends BaseTest
|
||||
return (queryOutput.getRecords());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testSecurityKeys() throws QException
|
||||
{
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(1)));
|
||||
insert2OrdersWith3Lines3LineExtrinsicsAnd4OrderExtrinsicAssociations();
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// make sure we inserted the records we think we did //
|
||||
///////////////////////////////////////////////////////
|
||||
assertIdsExist(TestUtils.TABLE_NAME_ORDER, List.of(1, 2));
|
||||
assertIdsExist(TestUtils.TABLE_NAME_LINE_ITEM, List.of(1, 2, 3));
|
||||
assertIdsExist(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC, List.of(1, 2, 3));
|
||||
assertIdsExist(TestUtils.TABLE_NAME_ORDER_EXTRINSIC, List.of(1, 2, 3, 4));
|
||||
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(2)));
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// assert can't delete the records at any level //
|
||||
//////////////////////////////////////////////////
|
||||
DeleteInput deleteInput = new DeleteInput();
|
||||
deleteInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
deleteInput.setPrimaryKeys(List.of(1));
|
||||
DeleteOutput deleteOutput = new DeleteAction().execute(deleteInput);
|
||||
assertEquals(0, deleteOutput.getDeletedRecordCount());
|
||||
assertEquals(1, deleteOutput.getRecordsWithErrors().size());
|
||||
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0));
|
||||
|
||||
deleteInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
deleteInput.setPrimaryKeys(List.of(1));
|
||||
deleteOutput = new DeleteAction().execute(deleteInput);
|
||||
assertEquals(0, deleteOutput.getDeletedRecordCount());
|
||||
assertEquals(1, deleteOutput.getRecordsWithErrors().size());
|
||||
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0));
|
||||
|
||||
deleteInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
deleteInput.setPrimaryKeys(List.of(1));
|
||||
deleteOutput = new DeleteAction().execute(deleteInput);
|
||||
assertEquals(0, deleteOutput.getDeletedRecordCount());
|
||||
assertEquals(1, deleteOutput.getRecordsWithErrors().size());
|
||||
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0));
|
||||
|
||||
deleteInput.setTableName(TestUtils.TABLE_NAME_ORDER_EXTRINSIC);
|
||||
deleteInput.setPrimaryKeys(List.of(1));
|
||||
deleteOutput = new DeleteAction().execute(deleteInput);
|
||||
assertEquals(0, deleteOutput.getDeletedRecordCount());
|
||||
assertEquals(1, deleteOutput.getRecordsWithErrors().size());
|
||||
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertIdsExist(String tableName, List<Integer> ids) throws QException
|
||||
{
|
||||
List<QRecord> records = TestUtils.queryTable(tableName);
|
||||
for(Integer id : ids)
|
||||
{
|
||||
assertTrue(records.stream().anyMatch(r -> Objects.equals(id, r.getValueInteger("id"))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void insert2OrdersWith3Lines3LineExtrinsicsAnd4OrderExtrinsicAssociations() throws QException
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("storeId", 1).withValue("orderNo", "ORD123")
|
||||
|
||||
.withAssociatedRecord("orderLine", new QRecord().withValue("sku", "BASIC1").withValue("quantity", 1)
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "LINE-EXT-1.1").withValue("value", "LINE-VAL-1")))
|
||||
|
||||
.withAssociatedRecord("orderLine", new QRecord().withValue("sku", "BASIC2").withValue("quantity", 2)
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "LINE-EXT-2.1").withValue("value", "LINE-VAL-2"))
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "LINE-EXT-2.2").withValue("value", "LINE-VAL-3")))
|
||||
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "MY-FIELD-1").withValue("value", "MY-VALUE-1"))
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "MY-FIELD-2").withValue("value", "MY-VALUE-2"))
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "MY-FIELD-3").withValue("value", "MY-VALUE-3")),
|
||||
|
||||
new QRecord().withValue("storeId", 1).withValue("orderNo", "ORD124")
|
||||
.withAssociatedRecord("orderLine", new QRecord().withValue("sku", "BASIC3").withValue("quantity", 3))
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "YOUR-FIELD-1").withValue("value", "YOUR-VALUE-1"))
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.actions.tables;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
@ -33,6 +34,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
|
||||
@ -393,237 +395,114 @@ class UpdateActionTest extends BaseTest
|
||||
assertEquals("Missing value in required field: Order No", updateOutput.getRecords().get(3).getErrors().get(0));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
/*
|
||||
@Test
|
||||
void testInsertMultiLevelSecurityJoins() throws QException
|
||||
{
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE, 1);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// null value in the foreign key to the join-table that provides the security value //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("lineItemId", null).withValue("key", "kidsCanCallYou").withValue("value", "HoJu")));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// value in the foreign key to the join-table that provides the security value, but the referenced record isn't found //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("lineItemId", 1701).withValue("key", "kidsCanCallYou").withValue("value", "HoJu")));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// insert an order and lineItem with storeId=2 - then, reset our session to only have storeId=1 in it - and try to insert an order-line referencing that order. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
QContext.getQSession().withSecurityKeyValues(new HashMap<>());
|
||||
QContext.getQSession().withSecurityKeyValues(TestUtils.SECURITY_KEY_TYPE_STORE, List.of(2));
|
||||
InsertInput insertOrderInput = new InsertInput();
|
||||
insertOrderInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertOrderInput.setRecords(List.of(new QRecord().withValue("id", 42).withValue("storeId", 2)));
|
||||
InsertOutput insertOrderOutput = new InsertAction().execute(insertOrderInput);
|
||||
assertEquals(42, insertOrderOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
InsertInput insertLineItemInput = new InsertInput();
|
||||
insertLineItemInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertLineItemInput.setRecords(List.of(new QRecord().withValue("id", 4200).withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 24)));
|
||||
InsertOutput insertLineItemOutput = new InsertAction().execute(insertLineItemInput);
|
||||
assertEquals(4200, insertLineItemOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
QContext.getQSession().withSecurityKeyValues(new HashMap<>());
|
||||
QContext.getQSession().withSecurityKeyValues(TestUtils.SECURITY_KEY_TYPE_STORE, List.of(1));
|
||||
InsertInput insertLineItemExtrinsicInput = new InsertInput();
|
||||
insertLineItemExtrinsicInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
insertLineItemExtrinsicInput.setRecords(List.of(new QRecord().withValue("lineItemId", 4200).withValue("key", "kidsCanCallYou").withValue("value", "HoJu")));
|
||||
InsertOutput insertLineItemExtrinsicOutput = new InsertAction().execute(insertLineItemExtrinsicInput);
|
||||
assertEquals("You do not have permission to insert this record.", insertLineItemExtrinsicOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
{
|
||||
QContext.getQSession().withSecurityKeyValues(new HashMap<>());
|
||||
QContext.getQSession().withSecurityKeyValues(TestUtils.SECURITY_KEY_TYPE_STORE, List.of(1));
|
||||
InsertInput insertOrderInput = new InsertInput();
|
||||
insertOrderInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertOrderInput.setRecords(List.of(new QRecord().withValue("id", 47).withValue("storeId", 1)));
|
||||
InsertOutput insertOrderOutput = new InsertAction().execute(insertOrderInput);
|
||||
assertEquals(47, insertOrderOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
InsertInput insertLineItemInput = new InsertInput();
|
||||
insertLineItemInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertLineItemInput.setRecords(List.of(new QRecord().withValue("id", 4700).withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 74)));
|
||||
InsertOutput insertLineItemOutput = new InsertAction().execute(insertLineItemInput);
|
||||
assertEquals(4700, insertLineItemOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// combine all the above, plus one record that works //
|
||||
///////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("lineItemId", null).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 1701).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 4200).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu")
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record.", insertOutput.getRecords().get(2).getErrors().get(0));
|
||||
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
|
||||
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
|
||||
}
|
||||
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// one more time, but with multiple input records referencing each foreign key //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("lineItemId", null).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 1701).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 4200).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", null).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 1701).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 4200).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu"),
|
||||
new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu")
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record.", insertOutput.getRecords().get(2).getErrors().get(0));
|
||||
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
|
||||
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(4).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(5).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record.", insertOutput.getRecords().get(6).getErrors().get(0));
|
||||
assertEquals(0, insertOutput.getRecords().get(7).getErrors().size());
|
||||
assertNotNull(insertOutput.getRecords().get(7).getValueInteger("id"));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
/*
|
||||
@Test
|
||||
void testInsertSingleLevelSecurityJoins() throws QException
|
||||
void testUpdateSecurityJoins() throws QException
|
||||
{
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE, 1);
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(1, 2)));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// null value in the foreign key to the join-table that provides the security value //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////
|
||||
// insert an order in each of store 1 and store 2 //
|
||||
// with some lines and line-extrinsics //
|
||||
////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("orderNo", "O1").withValue("storeId", 1),
|
||||
new QRecord().withValue("id", 2).withValue("orderNo", "O2").withValue("storeId", 2)
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 10).withValue("orderId", 1).withValue("sku", "BASIC1"),
|
||||
new QRecord().withValue("id", 20).withValue("orderId", 2).withValue("sku", "BASIC2")
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 100).withValue("lineItemId", 10).withValue("key", "Key1").withValue("value", "Value1"),
|
||||
new QRecord().withValue("id", 200).withValue("lineItemId", 20).withValue("key", "Key2").withValue("value", "Value2")
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// try to remove the value that provides the foreign key //
|
||||
///////////////////////////////////////////////////////////
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("orderId", null).withValue("sku", "BASIC1").withValue("quantity", 1)));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 10).withValue("orderId", null).withValue("sku", "BASIC2")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// value in the foreign key to the join-table that provides the security value, but the referenced record isn't found //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// with a session that can only access store 1, try to update the line in store 2 //
|
||||
// should fail as a not-found - you can't see that record. //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("orderId", 1701).withValue("sku", "BASIC1").withValue("quantity", 1)));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// insert an order with storeId=2 - then, reset our session to only have storeId=1 in it - and try to insert an order-line referencing that order. //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
QContext.getQSession().withSecurityKeyValues(new HashMap<>());
|
||||
QContext.getQSession().withSecurityKeyValues(TestUtils.SECURITY_KEY_TYPE_STORE, List.of(2));
|
||||
InsertInput insertOrderInput = new InsertInput();
|
||||
insertOrderInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertOrderInput.setRecords(List.of(new QRecord().withValue("id", 42).withValue("storeId", 2)));
|
||||
InsertOutput insertOrderOutput = new InsertAction().execute(insertOrderInput);
|
||||
assertEquals(42, insertOrderOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
QContext.getQSession().withSecurityKeyValues(new HashMap<>());
|
||||
QContext.getQSession().withSecurityKeyValues(TestUtils.SECURITY_KEY_TYPE_STORE, List.of(1));
|
||||
InsertInput insertLineItemInput = new InsertInput();
|
||||
insertLineItemInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertLineItemInput.setRecords(List.of(new QRecord().withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 1)));
|
||||
InsertOutput insertLineItemOutput = new InsertAction().execute(insertLineItemInput);
|
||||
assertEquals("You do not have permission to insert this record.", insertLineItemOutput.getRecords().get(0).getErrors().get(0));
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(1)));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 20).withValue("sku", "BASIC3")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("No record was found to update for Id = 20", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// with a session that can only access store 1, try to update the line from the order in store 1 to be in store 2 //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
QContext.getQSession().withSecurityKeyValues(new HashMap<>());
|
||||
QContext.getQSession().withSecurityKeyValues(TestUtils.SECURITY_KEY_TYPE_STORE, List.of(1));
|
||||
InsertInput insertOrderInput = new InsertInput();
|
||||
insertOrderInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertOrderInput.setRecords(List.of(new QRecord().withValue("id", 47).withValue("storeId", 1)));
|
||||
new InsertAction().execute(insertOrderInput);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// combine all the above, plus one record that works //
|
||||
///////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("orderId", null).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 1701).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1)
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record.", insertOutput.getRecords().get(2).getErrors().get(0));
|
||||
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
|
||||
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(1)));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 10).withValue("orderId", 2).withValue("sku", "BASIC3")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// try to remove the value that provides the foreign key //
|
||||
///////////////////////////////////////////////////////////
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// one more time, but with multiple input records referencing each foreign key //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("orderId", null).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 1701).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", null).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 1701).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 1),
|
||||
new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1)
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record.", insertOutput.getRecords().get(2).getErrors().get(0));
|
||||
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
|
||||
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(4).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(5).getErrors().get(0));
|
||||
assertEquals("You do not have permission to insert this record.", insertOutput.getRecords().get(6).getErrors().get(0));
|
||||
assertEquals(0, insertOutput.getRecords().get(7).getErrors().size());
|
||||
assertNotNull(insertOutput.getRecords().get(7).getValueInteger("id"));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 100).withValue("lineItemId", null).withValue("key", "updatedKey")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// with a session that can only access store 1, try to update the line-extrinsic in store 2 //
|
||||
// should fail as a not-found - you can't see that record. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(1)));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 200).withValue("key", "updatedKey")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("No record was found to update for Id = 200", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// with a session that can only access store 1, try to update the line-extrinsic from the order in store 1 to be in store 2 //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE, ListBuilder.of(1)));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 100).withValue("lineItemId", 20).withValue("key", "updatedKey")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@ -690,62 +569,101 @@ class UpdateActionTest extends BaseTest
|
||||
assertThat(TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER)).anyMatch(r -> r.getValueString("orderNo").equals("original"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
/*
|
||||
@Test
|
||||
void testSecurityKeyNullDenied() throws QException
|
||||
{
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
////////////////////////////////
|
||||
// insert an order in store 1 //
|
||||
////////////////////////////////
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE, 1);
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertInput.setRecords(List.of(new QRecord()));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals("You do not have permission to insert a record without a value in the field: Store Id", insertOutput.getRecords().get(0).getErrors().get(0));
|
||||
assertEquals(0, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).size());
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("orderNo", "original").withValue("storeId", 1)));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
///////////////////////////////////////////
|
||||
// try to update its storeId to null now //
|
||||
///////////////////////////////////////////
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("storeId", null)));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals("You do not have permission to update a record without a value in the field: Store Id", updateOutput.getRecords().get(0).getErrors().get(0));
|
||||
assertEquals(0, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).stream().filter(r -> r.getValue("storeId") == null).count());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
/*
|
||||
@Test
|
||||
void testSecurityKeyNullAllowed() throws QException
|
||||
{
|
||||
/////////////////////////////////////
|
||||
// change storeId to be allow-null //
|
||||
/////////////////////////////////////
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
qInstance.getTable(TestUtils.TABLE_NAME_ORDER).getRecordSecurityLocks().get(0).setNullValueBehavior(RecordSecurityLock.NullValueBehavior.ALLOW);
|
||||
|
||||
////////////////////////////////
|
||||
// insert an order in store 1 //
|
||||
////////////////////////////////
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE, 1);
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertInput.setRecords(List.of(new QRecord()));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals(0, insertOutput.getRecords().get(0).getErrors().size());
|
||||
assertEquals(1, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).size());
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("orderNo", "original").withValue("storeId", 1)));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE, 1);
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("storeId", null)));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals(0, updateOutput.getRecords().get(0).getErrors().size());
|
||||
assertEquals(1, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).stream().filter(r -> r.getValue("storeId") == null).count());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
/*
|
||||
@Test
|
||||
void testSecurityKeyAllAccess() throws QException
|
||||
{
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
qInstance.getTable(TestUtils.TABLE_NAME_ORDER).getRecordSecurityLocks().get(0).setNullValueBehavior(RecordSecurityLock.NullValueBehavior.ALLOW);
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, true);
|
||||
////////////////////////////////
|
||||
// insert 2 orders in store 1 //
|
||||
////////////////////////////////
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE, 1);
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("storeId", 999),
|
||||
new QRecord().withValue("storeId", null)
|
||||
new QRecord().withValue("id", 1).withValue("orderNo", "O1").withValue("storeId", 1),
|
||||
new QRecord().withValue("id", 2).withValue("orderNo", "O2").withValue("storeId", 1)
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals(2, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).size());
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// make sure with all-access key we can update however //
|
||||
/////////////////////////////////////////////////////////
|
||||
QContext.getQSession().setSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, ListBuilder.of(true)));
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
updateInput.setRecords(List.of(
|
||||
new QRecord().withValue("id", 1).withValue("storeId", 999),
|
||||
new QRecord().withValue("id", 2).withValue("storeId", null)
|
||||
));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals(0, updateOutput.getRecords().get(0).getErrors().size());
|
||||
assertEquals(0, updateOutput.getRecords().get(1).getErrors().size());
|
||||
assertEquals(1, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).stream().filter(r -> Objects.equals(r.getValue("storeId"), 999)).count());
|
||||
assertEquals(1, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).stream().filter(r -> r.getValue("storeId") == null).count());
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.modules.backend.implementations.utils;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@ -97,6 +98,21 @@ class BackendQueryFilterUtilsTest
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_LIKE, "Test"), "f", "Tst"));
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_LIKE, "T%"), "f", "Rest"));
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_LIKE, "T_st"), "f", "Toast"));
|
||||
|
||||
//////////////
|
||||
// IN & NOT //
|
||||
//////////////
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.IN, "A"), "f", "A"));
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.IN, "A", "B"), "f", "A"));
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.IN, "A", "B"), "f", "B"));
|
||||
assertFalse(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.IN, List.of()), "f", "A"));
|
||||
assertFalse(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.IN, ListBuilder.of(null)), "f", "A"));
|
||||
|
||||
assertFalse(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_IN, "A"), "f", "A"));
|
||||
assertFalse(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_IN, "A", "B"), "f", "A"));
|
||||
assertFalse(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_IN, "A", "B"), "f", "B"));
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_IN, List.of()), "f", "A"));
|
||||
assertTrue(BackendQueryFilterUtils.doesCriteriaMatch(new QFilterCriteria("f", QCriteriaOperator.NOT_IN, ListBuilder.of(null)), "f", "A"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -619,6 +619,10 @@ public class TestUtils
|
||||
.withName(TABLE_NAME_ORDER_EXTRINSIC)
|
||||
.withBackendName(MEMORY_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withRecordSecurityLock(new RecordSecurityLock()
|
||||
.withSecurityKeyType(SECURITY_KEY_TYPE_STORE)
|
||||
.withFieldName("order.storeId")
|
||||
.withJoinNameChain(List.of("orderOrderExtrinsic")))
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
|
@ -23,8 +23,10 @@ package com.kingsrook.qqq.backend.core.utils.collections;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -50,6 +52,7 @@ class MapBuilderTest
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -61,9 +64,22 @@ class MapBuilderTest
|
||||
///////////////////////////////
|
||||
Map<String, Object> map = MapBuilder.of("1", null);
|
||||
|
||||
///////////////////////////////////////
|
||||
// this too, doesn't freaking throw. //
|
||||
///////////////////////////////////////
|
||||
map.put("2", null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testTypeYouRequest()
|
||||
{
|
||||
Map<String, Integer> myTreeMap = MapBuilder.<String, Integer>of(TreeMap::new).with("1", 1).with("2", 2).build();
|
||||
assertTrue(myTreeMap instanceof TreeMap);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user