Checking record security locks that are more than 1 join away.

This commit is contained in:
2023-03-29 09:55:05 -05:00
parent e62d2332ac
commit ef6ccc61c3
18 changed files with 634 additions and 151 deletions

View File

@ -25,6 +25,11 @@ package com.kingsrook.qqq.backend.module.rdbms;
import java.io.InputStream;
import java.sql.Connection;
import java.util.List;
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
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.tables.query.QueryOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.authentication.QAuthenticationMetaData;
@ -38,6 +43,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleVal
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
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.module.rdbms.actions.RDBMSActionTest;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager;
@ -61,6 +67,7 @@ public class TestUtils
public static final String TABLE_NAME_ORDER = "order";
public static final String TABLE_NAME_ITEM = "item";
public static final String TABLE_NAME_ORDER_LINE = "orderLine";
public static final String TABLE_NAME_LINE_ITEM_EXTRINSIC = "orderLineExtrinsic";
public static final String TABLE_NAME_WAREHOUSE = "warehouse";
public static final String TABLE_NAME_WAREHOUSE_STORE_INT = "warehouseStoreInt";
@ -231,6 +238,7 @@ public class TestUtils
qInstance.addTable(defineBaseTable(TABLE_NAME_ORDER, "order")
.withRecordSecurityLock(new RecordSecurityLock().withSecurityKeyType(TABLE_NAME_STORE).withFieldName("storeId"))
.withAssociation(new Association().withName("orderLine").withAssociatedTableName(TABLE_NAME_ORDER_LINE).withJoinName("orderJoinOrderLine"))
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id").withPossibleValueSourceName(TABLE_NAME_STORE))
.withField(new QFieldMetaData("billToPersonId", QFieldType.INTEGER).withBackendName("bill_to_person_id").withPossibleValueSourceName(TABLE_NAME_PERSON))
.withField(new QFieldMetaData("shipToPersonId", QFieldType.INTEGER).withBackendName("ship_to_person_id").withPossibleValueSourceName(TABLE_NAME_PERSON))
@ -243,13 +251,28 @@ public class TestUtils
);
qInstance.addTable(defineBaseTable(TABLE_NAME_ORDER_LINE, "order_line")
.withRecordSecurityLock(new RecordSecurityLock().withSecurityKeyType(TABLE_NAME_STORE).withFieldName("storeId"))
.withRecordSecurityLock(new RecordSecurityLock()
.withSecurityKeyType(TABLE_NAME_STORE)
.withFieldName("order.storeId")
.withJoinNameChain(List.of("orderJoinOrderLine")))
.withAssociation(new Association().withName("extrinsics").withAssociatedTableName(TABLE_NAME_LINE_ITEM_EXTRINSIC).withJoinName("orderLineJoinLineItemExtrinsic"))
.withField(new QFieldMetaData("orderId", QFieldType.INTEGER).withBackendName("order_id"))
.withField(new QFieldMetaData("sku", QFieldType.STRING))
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id").withPossibleValueSourceName(TABLE_NAME_STORE))
.withField(new QFieldMetaData("quantity", QFieldType.INTEGER))
);
qInstance.addTable(defineBaseTable(TABLE_NAME_LINE_ITEM_EXTRINSIC, "line_item_extrinsic")
.withRecordSecurityLock(new RecordSecurityLock()
.withSecurityKeyType(TABLE_NAME_STORE)
.withFieldName("order.storeId")
.withJoinNameChain(List.of("orderJoinOrderLine", "orderLineJoinLineItemExtrinsic")))
.withField(new QFieldMetaData("id", QFieldType.INTEGER).withIsEditable(false))
.withField(new QFieldMetaData("orderLineId", QFieldType.INTEGER).withBackendName("order_line_id"))
.withField(new QFieldMetaData("key", QFieldType.STRING))
.withField(new QFieldMetaData("value", QFieldType.STRING))
);
qInstance.addTable(defineBaseTable(TABLE_NAME_WAREHOUSE_STORE_INT, "warehouse_store_int")
.withField(new QFieldMetaData("warehouseId", QFieldType.INTEGER).withBackendName("warehouse_id"))
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id"))
@ -321,6 +344,14 @@ public class TestUtils
.withJoinOn(new JoinOn("storeId", "storeId"))
);
qInstance.addJoin(new QJoinMetaData()
.withName("orderLineJoinLineItemExtrinsic")
.withLeftTable(TABLE_NAME_ORDER_LINE)
.withRightTable(TABLE_NAME_LINE_ITEM_EXTRINSIC)
.withType(JoinType.ONE_TO_MANY)
.withJoinOn(new JoinOn("id", "orderLineId"))
);
qInstance.addPossibleValueSource(new QPossibleValueSource()
.withName("store")
.withType(QPossibleValueSourceType.TABLE)
@ -349,4 +380,16 @@ public class TestUtils
.withField(new QFieldMetaData("id", QFieldType.INTEGER));
}
/*******************************************************************************
**
*******************************************************************************/
public static List<QRecord> queryTable(String tableName) throws QException
{
QueryInput queryInput = new QueryInput();
queryInput.setTableName(tableName);
QueryOutput queryOutput = new QueryAction().execute(queryInput);
return (queryOutput.getRecords());
}
}

View File

@ -329,8 +329,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1));
aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
aggregateResult = aggregateOutput.getResults().get(0);
// note - this would be 33, except for that one order line that has a contradictory store id...
Assertions.assertEquals(32, aggregateResult.getAggregateValue(sumOfQuantity));
Assertions.assertEquals(33, aggregateResult.getAggregateValue(sumOfQuantity));
}

View File

@ -24,6 +24,9 @@ package com.kingsrook.qqq.backend.module.rdbms.actions;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
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.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
@ -34,6 +37,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/*******************************************************************************
@ -140,6 +144,50 @@ public class RDBMSInsertActionTest extends RDBMSActionTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testInsertAssociations() throws QException
{
QContext.getQSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1);
int originalNoOfOrderLineExtrinsics = TestUtils.queryTable(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC).size();
int originalNoOfOrderLines = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER_LINE).size();
int originalNoOfOrders = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).size();
InsertInput insertInput = new InsertInput();
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
insertInput.setRecords(List.of(
new QRecord().withValue("storeId", 1).withValue("billToPersonId", 100).withValue("shipToPersonId", 200)
.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")))
));
new InsertAction().execute(insertInput);
List<QRecord> orders = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER);
assertEquals(originalNoOfOrders + 1, orders.size());
assertTrue(orders.stream().anyMatch(r -> Objects.equals(r.getValue("billToPersonId"), 100) && Objects.equals(r.getValue("shipToPersonId"), 200)));
List<QRecord> orderLines = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER_LINE);
assertEquals(originalNoOfOrderLines + 2, orderLines.size());
assertTrue(orderLines.stream().anyMatch(r -> Objects.equals(r.getValue("sku"), "BASIC1") && Objects.equals(r.getValue("quantity"), 1)));
assertTrue(orderLines.stream().anyMatch(r -> Objects.equals(r.getValue("sku"), "BASIC2") && Objects.equals(r.getValue("quantity"), 2)));
List<QRecord> lineItemExtrinsics = TestUtils.queryTable(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
assertEquals(originalNoOfOrderLineExtrinsics + 3, lineItemExtrinsics.size());
assertTrue(lineItemExtrinsics.stream().anyMatch(r -> Objects.equals(r.getValue("key"), "LINE-EXT-1.1") && Objects.equals(r.getValue("value"), "LINE-VAL-1")));
assertTrue(lineItemExtrinsics.stream().anyMatch(r -> Objects.equals(r.getValue("key"), "LINE-EXT-2.1") && Objects.equals(r.getValue("value"), "LINE-VAL-2")));
assertTrue(lineItemExtrinsics.stream().anyMatch(r -> Objects.equals(r.getValue("key"), "LINE-EXT-2.2") && Objects.equals(r.getValue("value"), "LINE-VAL-3")));
}
private void assertAnInsertedPersonRecord(String firstName, String lastName, Integer id) throws Exception
{
runTestSql("SELECT * FROM person WHERE last_name = '" + lastName + "'", (rs -> {

View File

@ -30,6 +30,7 @@ import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
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.model.actions.tables.query.QFilterOrderBy;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
@ -162,6 +163,7 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
.withDataSource(new QReportDataSource()
.withSourceTable(TestUtils.TABLE_NAME_ORDER_LINE)
.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ITEM).withAlias("i").withSelect(true))
.withQueryFilter(new QQueryFilter().withOrderBy(new QFilterOrderBy("id")))
)
.withView(new QReportView()
.withType(ReportType.TABLE)
@ -179,13 +181,13 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
assertEquals("""
"Line Item Id","Item SKU","Item Store Id","Item Store Name"
"1","QM-1","1","Q-Mart"
"5","QM-1","1","Q-Mart"
"2","QM-2","1","Q-Mart"
"3","QM-3","1","Q-Mart"
"4","QRU-1","2","QQQ 'R' Us"
"5","QM-1","1","Q-Mart"
"6","QRU-1","2","QQQ 'R' Us"
"8","QRU-1","2","QQQ 'R' Us"
"7","QRU-2","2","QQQ 'R' Us"
"8","QRU-1","2","QQQ 'R' Us"
"9","QD-1","3","QDepot"
"10","QD-1","3","QDepot"
"11","QD-1","3","QDepot"

View File

@ -79,6 +79,7 @@ INSERT INTO carrier (id, name, company_code, service_level) VALUES (9, 'USPS Sup
INSERT INTO carrier (id, name, company_code, service_level) VALUES (10, 'DHL International', 'DHL', 'I');
INSERT INTO carrier (id, name, company_code, service_level) VALUES (11, 'GSO', 'GSO', 'G');
DROP TABLE IF EXISTS line_item_extrinsic;
DROP TABLE IF EXISTS order_line;
DROP TABLE IF EXISTS item;
DROP TABLE IF EXISTS `order`;
@ -138,7 +139,7 @@ CREATE TABLE order_line
id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT REFERENCES `order`,
sku VARCHAR(80),
store_id INT REFERENCES store, -- todo - as a challenge, if this field wasn't here, so we had to join through order...
store_id INT REFERENCES store,
quantity INT
);
@ -177,3 +178,12 @@ CREATE TABLE warehouse_store_int
INSERT INTO warehouse_store_int (warehouse_id, store_id) VALUES (1, 1);
INSERT INTO warehouse_store_int (warehouse_id, store_id) VALUES (1, 2);
INSERT INTO warehouse_store_int (warehouse_id, store_id) VALUES (1, 3);
CREATE TABLE line_item_extrinsic
(
id INT AUTO_INCREMENT PRIMARY KEY,
order_line_id INT REFERENCES order_line,
`key` VARCHAR(80),
`value` VARCHAR(80)
);