Remove single-parent concept on app-children; more working version of recordLock from join

This commit is contained in:
2023-01-13 09:23:06 -06:00
parent 9a58c7683b
commit 2b0974f4a5
16 changed files with 162 additions and 157 deletions

View File

@ -25,7 +25,6 @@ package com.kingsrook.qqq.backend.core.actions.permissions;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.stream.Collectors;
@ -121,7 +120,7 @@ public class PermissionsHelper
////////////////////////////////////////////////////////////////////////
// if the entity just has a 'has access', then check for 'has access' //
////////////////////////////////////////////////////////////////////////
return getPermissionCheckResult(actionInput, rules, permissionBaseName, PrivatePermissionSubType.HAS_ACCESS);
return getPermissionCheckResult(actionInput, rules, permissionBaseName, metaDataWithPermissionRules, PrivatePermissionSubType.HAS_ACCESS);
}
case READ_WRITE_PERMISSIONS:
{
@ -130,9 +129,9 @@ public class PermissionsHelper
////////////////////////////////////////////////////////////////
if(metaDataWithPermissionRules instanceof QTableMetaData)
{
return getPermissionCheckResult(actionInput, rules, permissionBaseName, PrivatePermissionSubType.READ, PrivatePermissionSubType.WRITE);
return getPermissionCheckResult(actionInput, rules, permissionBaseName, metaDataWithPermissionRules, PrivatePermissionSubType.READ, PrivatePermissionSubType.WRITE);
}
return getPermissionCheckResult(actionInput, rules, permissionBaseName, PrivatePermissionSubType.HAS_ACCESS);
return getPermissionCheckResult(actionInput, rules, permissionBaseName, metaDataWithPermissionRules, PrivatePermissionSubType.HAS_ACCESS);
}
case READ_INSERT_EDIT_DELETE_PERMISSIONS:
{
@ -141,9 +140,9 @@ public class PermissionsHelper
//////////////////////////////////////////////////////////////////////////
if(metaDataWithPermissionRules instanceof QTableMetaData)
{
return getPermissionCheckResult(actionInput, rules, permissionBaseName, TablePermissionSubType.READ, TablePermissionSubType.INSERT, TablePermissionSubType.EDIT, TablePermissionSubType.DELETE);
return getPermissionCheckResult(actionInput, rules, permissionBaseName, metaDataWithPermissionRules, TablePermissionSubType.READ, TablePermissionSubType.INSERT, TablePermissionSubType.EDIT, TablePermissionSubType.DELETE);
}
return getPermissionCheckResult(actionInput, rules, permissionBaseName, PrivatePermissionSubType.HAS_ACCESS);
return getPermissionCheckResult(actionInput, rules, permissionBaseName, metaDataWithPermissionRules, PrivatePermissionSubType.HAS_ACCESS);
}
default:
{
@ -164,10 +163,6 @@ public class PermissionsHelper
static Map<String, CustomPermissionChecker> customPermissionCheckerMap = new HashMap<>();
/*******************************************************************************
**
*******************************************************************************/
@ -181,12 +176,7 @@ public class PermissionsHelper
/////////////////////////////////////
// todo - avoid stack overflows... //
/////////////////////////////////////
if(!customPermissionCheckerMap.containsKey(effectivePermissionRules.getCustomPermissionChecker().getName()))
{
CustomPermissionChecker customPermissionChecker = QCodeLoader.getAdHoc(CustomPermissionChecker.class, effectivePermissionRules.getCustomPermissionChecker());
customPermissionCheckerMap.put(effectivePermissionRules.getCustomPermissionChecker().getName(), customPermissionChecker);
}
CustomPermissionChecker customPermissionChecker = customPermissionCheckerMap.get(effectivePermissionRules.getCustomPermissionChecker().getName());
CustomPermissionChecker customPermissionChecker = QCodeLoader.getAdHoc(CustomPermissionChecker.class, effectivePermissionRules.getCustomPermissionChecker());
customPermissionChecker.checkPermissionsThrowing(actionInput, process);
return;
}
@ -421,11 +411,26 @@ public class PermissionsHelper
/*******************************************************************************
**
*******************************************************************************/
static PermissionCheckResult getPermissionCheckResult(AbstractActionInput actionInput, QPermissionRules rules, String permissionBaseName, PermissionSubType... permissionSubTypes)
static PermissionCheckResult getPermissionCheckResult(AbstractActionInput actionInput, QPermissionRules rules, String permissionBaseName, MetaDataWithPermissionRules metaDataWithPermissionRules, PermissionSubType... permissionSubTypes)
{
for(PermissionSubType permissionSubType : permissionSubTypes)
{
PermissionSubType effectivePermissionSubType = getEffectivePermissionSubType(rules, permissionSubType);
if(rules.getCustomPermissionChecker() != null)
{
try
{
CustomPermissionChecker customPermissionChecker = QCodeLoader.getAdHoc(CustomPermissionChecker.class, rules.getCustomPermissionChecker());
customPermissionChecker.checkPermissionsThrowing(actionInput, metaDataWithPermissionRules);
return (PermissionCheckResult.ALLOW);
}
catch(QPermissionDeniedException e)
{
return (getPermissionDeniedCheckResult(rules));
}
}
if(hasPermission(actionInput.getSession(), permissionBaseName, effectivePermissionSubType))
{
return (PermissionCheckResult.ALLOW);
@ -526,7 +531,7 @@ public class PermissionsHelper
if(!hasPermission(actionInput.getSession(), permissionBaseName, effectivePermissionSubType))
{
LOG.debug("Throwing permission denied for: " + getPermissionName(permissionBaseName, effectivePermissionSubType) + " for " + actionInput.getSession().getUser());
// LOG.debug("Throwing permission denied for: " + getPermissionName(permissionBaseName, effectivePermissionSubType) + " for " + actionInput.getSession().getUser());
throw (new QPermissionDeniedException("Permission denied."));
}
}

View File

@ -51,6 +51,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.ValueTooLongBehavior;
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppSection;
@ -356,7 +357,6 @@ public class QInstanceValidator
qInstance.getTables().forEach((tableName, table) ->
{
assertCondition(Objects.equals(tableName, table.getName()), "Inconsistent naming for table: " + tableName + "/" + table.getName() + ".");
validateAppChildHasValidParentAppName(qInstance, table);
////////////////////////////////////////
// validate the backend for the table //
@ -465,10 +465,37 @@ public class QInstanceValidator
prefix = "Table " + table.getName() + " recordSecurityLock (of key type " + securityKeyTypeName + ") ";
String fieldName = recordSecurityLock.getFieldName();
if(assertCondition(StringUtils.hasContent(fieldName), prefix + "is missing a fieldName"))
boolean hasAnyBadJoins = false;
for(String joinName : CollectionUtils.nonNullList(recordSecurityLock.getJoinNameChain()))
{
assertCondition(findField(qInstance, table, null, fieldName), prefix + "has an unrecognized fieldName: " + fieldName);
if(!assertCondition(qInstance.getJoin(joinName) != null, prefix + "has an unrecognized joinName: " + joinName))
{
hasAnyBadJoins = true;
}
}
String fieldName = recordSecurityLock.getFieldName();
////////////////////////////////////////////////////////////////////////////////
// don't bother trying to validate field names if we know we have a bad join. //
////////////////////////////////////////////////////////////////////////////////
if(assertCondition(StringUtils.hasContent(fieldName), prefix + "is missing a fieldName") && !hasAnyBadJoins)
{
List<QueryJoin> joins = new ArrayList<>();
for(String joinName : CollectionUtils.nonNullList(recordSecurityLock.getJoinNameChain()))
{
QJoinMetaData join = qInstance.getJoin(joinName);
if(join.getLeftTable().equals(table.getName()))
{
joins.add(new QueryJoin(join));
}
else if(join.getRightTable().equals(table.getName()))
{
joins.add(new QueryJoin(join.flip()));
}
}
assertCondition(findField(qInstance, table, joins, fieldName), prefix + "has an unrecognized fieldName: " + fieldName);
}
assertCondition(recordSecurityLock.getNullValueBehavior() != null, prefix + "is missing a nullValueBehavior");
@ -960,8 +987,6 @@ public class QInstanceValidator
{
assertCondition(Objects.equals(processName, process.getName()), "Inconsistent naming for process: " + processName + "/" + process.getName() + ".");
validateAppChildHasValidParentAppName(qInstance, process);
/////////////////////////////////////////////
// validate the table name for the process //
/////////////////////////////////////////////
@ -1015,7 +1040,6 @@ public class QInstanceValidator
qInstance.getReports().forEach((reportName, report) ->
{
assertCondition(Objects.equals(reportName, report.getName()), "Inconsistent naming for report: " + reportName + "/" + report.getName() + ".");
validateAppChildHasValidParentAppName(qInstance, report);
////////////////////////////////////////
// validate dataSources in the report //
@ -1172,6 +1196,7 @@ public class QInstanceValidator
{
joinTable.getField(fieldNameAfterDot);
foundField = true;
break;
}
catch(Exception e2)
{
@ -1216,7 +1241,10 @@ public class QInstanceValidator
Set<String> childNames = new HashSet<>();
for(QAppChildMetaData child : app.getChildren())
{
assertCondition(Objects.equals(appName, child.getParentAppName()), "Child " + child.getName() + " of app " + appName + " does not have its parent app properly set.");
if(child instanceof QAppMetaData childApp)
{
assertCondition(Objects.equals(appName, childApp.getParentAppName()), "Child app " + child.getName() + " of app " + appName + " does not have its parent app properly set.");
}
assertCondition(!childNames.contains(child.getName()), "App " + appName + " contains more than one child named " + child.getName());
childNames.add(child.getName());
}
@ -1442,7 +1470,7 @@ public class QInstanceValidator
/*******************************************************************************
**
*******************************************************************************/
private void validateAppChildHasValidParentAppName(QInstance qInstance, QAppChildMetaData appChild)
private void validateAppChildHasValidParentAppName(QInstance qInstance, QAppMetaData appChild)
{
if(appChild.getParentAppName() != null)
{

View File

@ -28,6 +28,7 @@ import java.util.Map;
import com.kingsrook.qqq.backend.core.exceptions.QException;
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.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@ -76,7 +77,7 @@ public class JoinsContext
///////////////////////////////////////////////////////////////
for(RecordSecurityLock recordSecurityLock : CollectionUtils.nonNullList(instance.getTable(tableName).getRecordSecurityLocks()))
{
for(String joinName : CollectionUtils.nonNullList(recordSecurityLock.getJoinChain()))
for(String joinName : CollectionUtils.nonNullList(recordSecurityLock.getJoinNameChain()))
{
if(this.queryJoins.stream().anyMatch(qj -> qj.getJoinMetaData().getName().equals(joinName)))
{
@ -86,7 +87,12 @@ public class JoinsContext
}
else
{
this.queryJoins.add(new QueryJoin().withJoinMetaData(instance.getJoin(joinName)).withType(QueryJoin.Type.INNER)); // todo aliases? probably.
QJoinMetaData join = instance.getJoin(joinName);
if(tableName.equals(join.getRightTable()))
{
join = join.flip();
}
this.queryJoins.add(new QueryJoin().withJoinMetaData(join).withType(QueryJoin.Type.INNER)); // todo aliases? probably.
}
}
}

View File

@ -300,10 +300,20 @@ public class QJoinMetaData
*******************************************************************************/
public QJoinMetaData withInferredName()
{
if(!StringUtils.hasContent(getLeftTable()) || !StringUtils.hasContent(getRightTable()))
return (withName(makeInferredJoinName(getLeftTable(), getRightTable())));
}
/*******************************************************************************
**
*******************************************************************************/
public static String makeInferredJoinName(String leftTable, String rightTable)
{
if(!StringUtils.hasContent(leftTable) || !StringUtils.hasContent(rightTable))
{
throw (new IllegalStateException("Missing either a left or right table name when trying to set inferred name for join"));
}
return (withName(getLeftTable() + "Join" + StringUtils.ucFirst(getRightTable())));
return (leftTable + "Join" + StringUtils.ucFirst(rightTable));
}
}

View File

@ -28,16 +28,6 @@ package com.kingsrook.qqq.backend.core.model.metadata.layout;
*******************************************************************************/
public interface QAppChildMetaData
{
/*******************************************************************************
**
*******************************************************************************/
void setParentAppName(String parentAppName);
/*******************************************************************************
**
*******************************************************************************/
String getParentAppName();
/*******************************************************************************
**
*******************************************************************************/

View File

@ -169,7 +169,11 @@ public class QAppMetaData implements QAppChildMetaData, MetaDataWithPermissionRu
this.children = new ArrayList<>();
}
this.children.add(child);
child.setParentAppName(this.getName());
if(child instanceof QAppMetaData childApp)
{
childApp.setParentAppName(this.getName());
}
}
@ -202,7 +206,6 @@ public class QAppMetaData implements QAppChildMetaData, MetaDataWithPermissionRu
** Getter for parentAppName
**
*******************************************************************************/
@Override
public String getParentAppName()
{
return parentAppName;
@ -214,7 +217,6 @@ public class QAppMetaData implements QAppChildMetaData, MetaDataWithPermissionRu
** Setter for parentAppName
**
*******************************************************************************/
@Override
public void setParentAppName(String parentAppName)
{
this.parentAppName = parentAppName;

View File

@ -54,8 +54,7 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi
private List<QStepMetaData> stepList; // these are the steps that are ran, by-default, in the order they are ran in
private Map<String, QStepMetaData> steps; // this is the full map of possible steps
private String parentAppName;
private QIcon icon;
private QIcon icon;
private QScheduleMetaData schedule;
@ -388,30 +387,6 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi
/*******************************************************************************
** Getter for parentAppName
**
*******************************************************************************/
@Override
public String getParentAppName()
{
return parentAppName;
}
/*******************************************************************************
** Setter for parentAppName
**
*******************************************************************************/
@Override
public void setParentAppName(String parentAppName)
{
this.parentAppName = parentAppName;
}
/*******************************************************************************
** Getter for icon
**

View File

@ -48,8 +48,7 @@ public class QReportMetaData implements QAppChildMetaData, MetaDataWithPermissio
private List<QReportDataSource> dataSources;
private List<QReportView> views;
private String parentAppName;
private QIcon icon;
private QIcon icon;
@ -304,28 +303,6 @@ public class QReportMetaData implements QAppChildMetaData, MetaDataWithPermissio
/*******************************************************************************
**
*******************************************************************************/
@Override
public void setParentAppName(String parentAppName)
{
this.parentAppName = parentAppName;
}
/*******************************************************************************
**
*******************************************************************************/
@Override
public String getParentAppName()
{
return (this.parentAppName);
}
/*******************************************************************************
** Getter for icon
**

View File

@ -34,7 +34,7 @@ public class RecordSecurityLock
{
private String securityKeyType;
private String fieldName;
private List<String> joinChain; // todo - add validation in validator!!
private List<String> joinNameChain; // todo - add validation in validator!!
private NullValueBehavior nullValueBehavior = NullValueBehavior.DENY;
@ -152,34 +152,34 @@ public class RecordSecurityLock
}
/*******************************************************************************
** Getter for joinChain
** Getter for joinNameChain
*******************************************************************************/
public List<String> getJoinChain()
public List<String> getJoinNameChain()
{
return (this.joinChain);
return (this.joinNameChain);
}
/*******************************************************************************
** Setter for joinChain
** Setter for joinNameChain
*******************************************************************************/
public void setJoinChain(List<String> joinChain)
public void setJoinNameChain(List<String> joinNameChain)
{
this.joinChain = joinChain;
this.joinNameChain = joinNameChain;
}
/*******************************************************************************
** Fluent setter for joinChain
** Fluent setter for joinNameChain
*******************************************************************************/
public RecordSecurityLock withJoinChain(List<String> joinChain)
public RecordSecurityLock withJoinNameChain(List<String> joinNameChain)
{
this.joinChain = joinChain;
this.joinNameChain = joinNameChain;
return (this);
}
}

View File

@ -80,8 +80,7 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData
private Map<String, QCodeReference> customizers;
private String parentAppName;
private QIcon icon;
private QIcon icon;
private String recordLabelFormat;
private List<String> recordLabelFields;
@ -538,30 +537,6 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData
/*******************************************************************************
** Getter for parentAppName
**
*******************************************************************************/
@Override
public String getParentAppName()
{
return parentAppName;
}
/*******************************************************************************
** Setter for parentAppName
**
*******************************************************************************/
@Override
public void setParentAppName(String parentAppName)
{
this.parentAppName = parentAppName;
}
/*******************************************************************************
** Getter for icon
**