mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-19 21:50:45 +00:00
Remove single-parent concept on app-children; more working version of recordLock from join
This commit is contained in:
@ -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."));
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -28,16 +28,6 @@ package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
||||
*******************************************************************************/
|
||||
public interface QAppChildMetaData
|
||||
{
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
void setParentAppName(String parentAppName);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
String getParentAppName();
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
**
|
||||
|
@ -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
|
||||
**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
**
|
||||
|
Reference in New Issue
Block a user