/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *******************************************************************************/ package org.apache.ofbiz.entityext.permission; import static org.apache.ofbiz.base.util.UtilGenerics.checkList; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.StringUtil; import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.base.util.UtilXml; import org.apache.ofbiz.base.util.string.FlexibleStringExpander; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.GenericEntityException; import org.apache.ofbiz.entity.GenericValue; import org.apache.ofbiz.entity.condition.EntityCondition; import org.apache.ofbiz.entity.condition.EntityExpr; import org.apache.ofbiz.entity.condition.EntityOperator; import org.apache.ofbiz.entity.model.ModelEntity; import org.apache.ofbiz.entity.util.EntityQuery; import org.apache.ofbiz.entity.util.EntityUtil; import org.apache.ofbiz.security.Security; import org.apache.ofbiz.service.ServiceUtil; import org.w3c.dom.Element; /** * EntityPermissionChecker Class * Services for granting operation permissions on Content entities in a data-driven manner. */ public class EntityPermissionChecker { public static final String module = EntityPermissionChecker.class.getName(); protected FlexibleStringExpander entityIdExdr; protected FlexibleStringExpander entityNameExdr; protected boolean displayFailCond; protected List<String> targetOperationList; protected PermissionConditionGetter permissionConditionGetter; protected RelatedRoleGetter relatedRoleGetter; protected AuxiliaryValueGetter auxiliaryValueGetter; public EntityPermissionChecker(Element element) { this.entityNameExdr = FlexibleStringExpander.getInstance(element.getAttribute("entity-name")); this.entityIdExdr = FlexibleStringExpander.getInstance(element.getAttribute("entity-id")); this.displayFailCond = "true".equals(element.getAttribute("display-fail-cond")); Element permissionConditionElement = UtilXml.firstChildElement(element, "permission-condition-getter"); if (permissionConditionElement == null) { permissionConditionGetter = new StdPermissionConditionGetter(); } else { permissionConditionGetter = new StdPermissionConditionGetter(permissionConditionElement); } Element auxiliaryValueElement = UtilXml.firstChildElement(element, "auxiliary-value-getter"); if (auxiliaryValueElement == null) { auxiliaryValueGetter = new StdAuxiliaryValueGetter(); } else { auxiliaryValueGetter = new StdAuxiliaryValueGetter(auxiliaryValueElement); } Element relatedRoleElement = UtilXml.firstChildElement(element, "related-role-getter"); if (relatedRoleElement == null) { relatedRoleGetter = new StdRelatedRoleGetter(); } else { relatedRoleGetter = new StdRelatedRoleGetter(relatedRoleElement); } String targetOperationString = element.getAttribute("target-operation"); if (UtilValidate.isNotEmpty(targetOperationString)) { List<String> operationsFromString = StringUtil.split(targetOperationString, "|"); if (targetOperationList == null) { targetOperationList = new ArrayList<String>(); } targetOperationList.addAll(operationsFromString); } permissionConditionGetter.setOperationList(targetOperationList); } public boolean runPermissionCheck(Map<String, ?> context) { boolean passed = false; String idString = entityIdExdr.expandString(context); List<String> entityIdList = null; if (UtilValidate.isNotEmpty(idString)) { entityIdList = StringUtil.split(idString, "|"); } else { entityIdList = new LinkedList<String>(); } String entityName = entityNameExdr.expandString(context); HttpServletRequest request = (HttpServletRequest)context.get("request"); GenericValue userLogin = null; String partyId = null; Delegator delegator = null; if (request != null) { HttpSession session = request.getSession(); userLogin = (GenericValue)session.getAttribute("userLogin"); if (userLogin != null) { partyId = userLogin.getString("partyId"); } delegator = (Delegator)request.getAttribute("delegator"); } if (auxiliaryValueGetter != null) auxiliaryValueGetter.clearList(); if (relatedRoleGetter != null) relatedRoleGetter.clearList(); try { permissionConditionGetter.init(delegator); passed = checkPermissionMethod(delegator, partyId, entityName, entityIdList, auxiliaryValueGetter, relatedRoleGetter, permissionConditionGetter); if (!passed && displayFailCond) { String errMsg = "Permission is denied. \nThese are the conditions of which one must be met:\n" + permissionConditionGetter.dumpAsText(); List<Object> errorMessageList = checkList(context.get("errorMessageList")); errorMessageList.add(errMsg); } } catch (GenericEntityException e) { throw new RuntimeException(e.getMessage()); } return passed; } public static Map<String, Object> checkPermission(GenericValue content, String statusId, GenericValue userLogin, List<String> passedPurposes, List<String> targetOperations, List<String> passedRoles, Delegator delegator , Security security, String entityAction) { String privilegeEnumId = null; return checkPermission(content, statusId, userLogin, passedPurposes, targetOperations, passedRoles, delegator, security, entityAction, privilegeEnumId, null); } public static Map<String, Object> checkPermission(GenericValue content, String statusId, GenericValue userLogin, List<String> passedPurposes, List<String> targetOperations, List<String> passedRoles, Delegator delegator , Security security, String entityAction, String privilegeEnumId, String quickCheckContentId) { List<String> statusList = null; if (statusId != null) { statusList = StringUtil.split(statusId, "|"); } return checkPermission(content, statusList, userLogin, passedPurposes, targetOperations, passedRoles, delegator, security, entityAction, privilegeEnumId, quickCheckContentId); } public static Map<String, Object> checkPermission(GenericValue content, List<String> statusList, GenericValue userLogin, List<String> passedPurposes, List<String> targetOperations, List<String> passedRoles, Delegator delegator , Security security, String entityAction, String privilegeEnumId) { return checkPermission(content, statusList, userLogin, passedPurposes, targetOperations, passedRoles, delegator, security, entityAction, privilegeEnumId, null); } public static Map<String, Object> checkPermission(GenericValue content, List<String> statusList, GenericValue userLogin, List<String> passedPurposes, List<String> targetOperations, List<String> passedRoles, Delegator delegator , Security security, String entityAction, String privilegeEnumId, String quickCheckContentId) { List<Object> entityIds = new LinkedList<Object>(); if (content != null) entityIds.add(content); if (UtilValidate.isNotEmpty(quickCheckContentId)) { List<String> quickList = StringUtil.split(quickCheckContentId, "|"); if (UtilValidate.isNotEmpty(quickList)) entityIds.addAll(quickList); } Map<String, Object> results = new HashMap<String, Object>(); boolean passed = false; if (userLogin != null && entityAction != null) { passed = security.hasEntityPermission("CONTENTMGR", entityAction, userLogin); } if (passed) { results.put("permissionStatus", "granted"); return results; } try { boolean check = checkPermissionMethod(delegator, userLogin, targetOperations, "Content", entityIds, passedPurposes, null, privilegeEnumId); if (check) { results.put("permissionStatus", "granted"); } else { results.put("permissionStatus", "rejected"); } } catch (GenericEntityException e) { return ServiceUtil.returnError(e.getMessage()); } return results; } public static boolean checkPermissionMethod(Delegator delegator, GenericValue userLogin, List<String> targetOperationList, String entityName, List<? extends Object> entityIdList, List<String> purposeList, List<String> roleList, String privilegeEnumId) throws GenericEntityException { boolean passed = false; String lcEntityName = entityName.toLowerCase(); String userLoginId = null; String partyId = null; if (userLogin != null) { userLoginId = userLogin.getString("userLoginId"); partyId = userLogin.getString("partyId"); } boolean hasRoleOperation = false; if (!(targetOperationList == null) && userLoginId != null) { hasRoleOperation = checkHasRoleOperations(partyId, targetOperationList, delegator); } if (hasRoleOperation) { return true; } ModelEntity modelEntity = delegator.getModelEntity(entityName); boolean hasStatusField = false; if (modelEntity.getField("statusId") != null) hasStatusField = true; boolean hasPrivilegeField = false; if (modelEntity.getField("privilegeEnumId") != null) hasPrivilegeField = true; ModelEntity modelOperationEntity = delegator.getModelEntity(entityName + "PurposeOperation"); if (modelOperationEntity == null) { modelOperationEntity = delegator.getModelEntity(entityName + "Operation"); } if (modelOperationEntity == null) { Debug.logError("No operation entity found for " + entityName, module); throw new RuntimeException("No operation entity found for " + entityName); } boolean hasPurposeOp = false; if (modelOperationEntity.getField(lcEntityName + "PurposeTypeId") != null) hasPurposeOp = true; boolean hasStatusOp = false; if (modelOperationEntity.getField("statusId") != null) hasStatusOp = true; boolean hasPrivilegeOp = false; if (modelOperationEntity.getField("privilegeEnumId") != null) hasPrivilegeOp = true; // Get all the condition operations that could apply, rather than having to go thru // entire table each time. //List condList = new LinkedList(); //Iterator iterType = targetOperationList.iterator(); //while (iterType.hasNext()) { // String op = (String)iterType.next(); // condList.add(EntityCondition.makeCondition(lcEntityName + "OperationId", op)); //} //EntityCondition opCond = EntityCondition.makeCondition(condList, EntityOperator.OR); List<GenericValue> targetOperationEntityList = EntityQuery.use(delegator) .from(modelOperationEntity.getEntityName()) .where(EntityCondition.makeCondition(lcEntityName + "OperationId", EntityOperator.IN, targetOperationList)) .cache(true) .queryList(); Map<String, GenericValue> entities = new HashMap<String, GenericValue>(); String pkFieldName = modelEntity.getFirstPkFieldName(); //TODO: privilegeEnumId test /* if (hasPrivilegeOp && hasPrivilegeField) { int privilegeEnumSeq = -1; if (UtilValidate.isNotEmpty(privilegeEnumId)) { GenericValue privEnum = EntityQuery.use(delegator).from("Enumeration").where("enumId", privilegeEnumId).cache().queryOne(); if (privEnum != null) { String sequenceId = privEnum.getString("sequenceId"); try { privilegeEnumSeq = Integer.parseInt(sequenceId); } catch (NumberFormatException e) { // just leave it at -1 } } } boolean thisPassed = true; Iterator iter = entityIdList.iterator(); while (iter.hasNext()) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, iter.next(), entities); if (entity == null) continue; String entityId = entity.getString(pkFieldName); String targetPrivilegeEnumId = entity.getString("privilegeEnumId"); if (UtilValidate.isNotEmpty(targetPrivilegeEnumId)) { int targetPrivilegeEnumSeq = -1; GenericValue privEnum = EntityQuery.use(delegator).from("Enumeration").where("enumId", privilegeEnumId).cache().queryOne(); if (privEnum != null) { String sequenceId = privEnum.getString("sequenceId"); try { targetPrivilegeEnumSeq = Integer.parseInt(sequenceId); } catch (NumberFormatException e) { // just leave it at -1 } if (targetPrivilegeEnumSeq > privilegeEnumSeq) { return false; } } } entities.put(entityId, entity); } } */ // check permission for each id in passed list until success. // Note that "quickCheck" id come first in the list // Check with no roles or purposes on the chance that the permission fields contain _NA_ s. Map<String, List<String>> purposes = new HashMap<String, List<String>>(); Map<String, List<String>> roles = new HashMap<String, List<String>>(); //List purposeList = null; //List roleList = null; for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; String statusId = null; if (hasStatusOp && hasStatusField) { statusId = entity.getString("statusId"); } if (hasPrivilegeOp && hasPrivilegeField) { privilegeEnumId = entity.getString("privilegeEnumId"); getPrivilegeEnumSeq(delegator, privilegeEnumId); } passed = hasMatch(entityName, targetOperationEntityList, roleList, hasPurposeOp, purposeList, hasStatusOp, statusId); if (passed) { break; } } if (passed) { return true; } if (hasPurposeOp) { // Check with just purposes next. for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; String entityId = entity.getString(pkFieldName); purposeList = getRelatedPurposes(entity, null); String statusId = null; if (hasStatusOp && hasStatusField) { statusId = entity.getString("statusId"); } if (purposeList.size() > 0) { passed = hasMatch(entityName, targetOperationEntityList, roleList, hasPurposeOp, purposeList, hasStatusOp, statusId); } if (passed) { break; } purposes.put(entityId, purposeList); } } if (passed) return true; if (userLogin == null) return false; // Check with roles. for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; String entityId = entity.getString(pkFieldName); List<String> tmpPurposeList = purposes.get(entityId); if (purposeList != null) { if (tmpPurposeList != null) { purposeList.addAll(tmpPurposeList); } } else { purposeList = tmpPurposeList; } List<String> tmpRoleList = getUserRoles(entity, userLogin, delegator); if (roleList != null) { if (tmpRoleList != null) { roleList.addAll(tmpRoleList); } } else { roleList = tmpRoleList; } String statusId = null; if (hasStatusOp && hasStatusField) { statusId = entity.getString("statusId"); } passed = hasMatch(entityName, targetOperationEntityList, roleList, hasPurposeOp, purposeList, hasStatusOp, statusId); if (passed) { break; } roles.put(entityId, roleList); } if (passed) return true; // Follow ownedEntityIds if (modelEntity.getField("owner" + entityName + "Id") != null) { for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; String entityId = entity.getString(pkFieldName); List<String> ownedContentIdList = new LinkedList<String>(); getEntityOwners(delegator, entity, ownedContentIdList, "Content", "ownerContentId"); List<String> ownedContentRoleIds = getUserRolesFromList(delegator, ownedContentIdList, partyId, "contentId", "partyId", "roleTypeId", "ContentRole"); String statusId = null; if (hasStatusOp && hasStatusField) { statusId = entity.getString("statusId"); } purposeList = purposes.get(entityId); passed = hasMatch(entityName, targetOperationEntityList, ownedContentRoleIds, hasPurposeOp, purposeList, hasStatusOp, statusId); if (passed) break; /* String ownedEntityId = entity.getString("owner" + entityName + "Id"); GenericValue ownedEntity = delegator.findOne(entityName,UtilMisc.toMap(pkFieldName, ownedEntityId), true); while (ownedEntity != null) { if (!alreadyCheckedIds.contains(ownedEntityId)) { // Decided to let the original purposes only be used in permission checking // //purposeList = (List)purposes.get(entityId); //purposeList = getRelatedPurposes(ownedEntity, purposeList); roleList = getUserRoles(ownedEntity, userLogin, delegator); String statusId = null; if (hasStatusOp && hasStatusField) { statusId = entity.getString("statusId"); } passed = hasMatch(entityName, targetOperationEntityList, roleList, hasPurposeOp, purposeList, hasStatusOp, statusId); if (passed) break; alreadyCheckedIds.add(ownedEntityId); //purposes.put(ownedEntityId, purposeList); //roles.put(ownedEntityId, roleList); ownedEntityId = ownedEntity.getString("owner" + entityName + "Id"); ownedEntity = delegator.findOne(entityName,UtilMisc.toMap(pkFieldName, ownedEntityId), true); } else { ownedEntity = null; } } if (passed) break; */ } } /* seems like repeat // Check parents iter = entityIdList.iterator(); while (iter.hasNext()) { String entityId = (String)iter.next(); GenericValue entity = (GenericValue)entities.get(entityId); purposeList = (List)purposes.get(entityId); roleList = getUserRoles(entity, userLogin, delegator); String statusId = null; if (hasStatusOp && hasStatusField) { statusId = entity.getString("statusId"); } String targetPrivilegeEnumId = null; if (hasPrivilegeOp && hasPrivilegeField) { targetPrivilegeEnumId = entity.getString("privilegeEnumId"); } passed = hasMatch(entityName, targetOperationEntityList, roleList, hasPurposeOp, purposeList, hasStatusOp, statusId); if (passed) break; alreadyCheckedIds.add(entityId); } */ return passed; } public static boolean checkPermissionMethod(Delegator delegator, String partyId, String entityName, List<? extends Object> entityIdList, AuxiliaryValueGetter auxiliaryValueGetter, RelatedRoleGetter relatedRoleGetter, PermissionConditionGetter permissionConditionGetter) throws GenericEntityException { permissionConditionGetter.init(delegator); if (Debug.verboseOn()) Debug.logVerbose(permissionConditionGetter.dumpAsText(), module); boolean passed = false; boolean checkAncestors = false; boolean hasRoleOperation = checkHasRoleOperations(partyId, permissionConditionGetter, delegator); if (hasRoleOperation) { return true; } ModelEntity modelEntity = delegator.getModelEntity(entityName); if (relatedRoleGetter != null) { if (UtilValidate.isNotEmpty(partyId)) { relatedRoleGetter.setList(UtilMisc.toList("LOGGEDIN")); } } // check permission for each id in passed list until success. // Note that "quickCheck" id come first in the list // Check with no roles or purposes on the chance that the permission fields contain _NA_ s. String pkFieldName = modelEntity.getFirstPkFieldName(); if (Debug.infoOn()) { String entityIdString = "ENTITIES: "; for (Object obj: entityIdList) { if (obj instanceof GenericValue) { String s = ((GenericValue)obj).getString(pkFieldName); entityIdString += s + " "; } else { entityIdString += obj + " "; } } //if (Debug.infoOn()) Debug.logInfo(entityIdString, module); } Map<String, GenericValue> entities = new HashMap<String, GenericValue>(); //List purposeList = null; //List roleList = null; for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; checkAncestors = false; passed = hasMatch(entity, permissionConditionGetter, relatedRoleGetter, null, partyId, checkAncestors); if (passed) { break; } } if (passed) { return true; } if (auxiliaryValueGetter != null) { //if (Debug.infoOn()) Debug.logInfo(auxiliaryValueGetter.dumpAsText(), module); // Check with just purposes next. for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; checkAncestors = false; passed = hasMatch(entity, permissionConditionGetter, relatedRoleGetter, auxiliaryValueGetter, partyId, checkAncestors); if (passed) { break; } } } if (passed) return true; // TODO: need to return some information here about why it failed if (partyId == null) return false; // Check with roles. if (relatedRoleGetter != null) { for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; checkAncestors = false; passed = hasMatch(entity, permissionConditionGetter, relatedRoleGetter, auxiliaryValueGetter, partyId, checkAncestors); if (passed) { break; } } } if (passed) return true; if (relatedRoleGetter != null) { for (Object id: entityIdList) { GenericValue entity = getNextEntity(delegator, entityName, pkFieldName, id, entities); if (entity == null) continue; checkAncestors = true; passed = hasMatch(entity, permissionConditionGetter, relatedRoleGetter, auxiliaryValueGetter, partyId, checkAncestors); if (passed) { break; } } } return passed; } public static GenericValue getNextEntity(Delegator delegator, String entityName, String pkFieldName, Object obj, Map<String, GenericValue> entities) throws GenericEntityException { GenericValue entity = null; if (obj instanceof String) { String entityId = (String)obj; if (entities != null) entity = entities.get(entityId); if (entity == null) entity = EntityQuery.use(delegator).from(entityName).where(pkFieldName, entityId).cache(true).queryOne(); } else if (obj instanceof GenericValue) { entity = (GenericValue)obj; } return entity; } public static boolean checkHasRoleOperations(String partyId, PermissionConditionGetter permissionConditionGetter , Delegator delegator) { List<String> targetOperations = permissionConditionGetter.getOperationList(); return checkHasRoleOperations(partyId, targetOperations, delegator); } public static boolean checkHasRoleOperations(String partyId, List<String> targetOperations, Delegator delegator) { //if (Debug.infoOn()) Debug.logInfo("targetOperations:" + targetOperations, module); //if (Debug.infoOn()) Debug.logInfo("userLoginId:" + userLoginId, module); if (targetOperations == null) return false; if (partyId != null && targetOperations.contains("HAS_USER_ROLE")) return true; boolean hasRoleOperation = false; boolean hasNeed = false; List<String> newHasRoleList = new LinkedList<String>(); for (String roleOp: targetOperations) { int idx1 = roleOp.indexOf("HAS_"); if (idx1 == 0) { String roleOp1 = roleOp.substring(4); // lop off "HAS_" int idx2 = roleOp1.indexOf("_ROLE"); if (idx2 == roleOp1.length() - 5) { String roleOp2 = roleOp1.substring(0, roleOp1.indexOf("_ROLE") - 1); // lop off "_ROLE" //if (Debug.infoOn()) Debug.logInfo("roleOp2:" + roleOp2, module); newHasRoleList.add(roleOp2); hasNeed = true; } } } if (hasNeed) { try { if (UtilValidate.isNotEmpty(partyId)) { List<GenericValue> partyRoleList = EntityQuery.use(delegator).from("PartyRole").where("partyId", partyId).cache(true).queryList(); for (GenericValue partyRole: partyRoleList) { String roleTypeId = partyRole.getString("roleTypeId"); for (String thisRole: newHasRoleList) { if (roleTypeId.indexOf(thisRole) >= 0) { hasRoleOperation = true; break; } } if (hasRoleOperation) break; } } } catch (GenericEntityException e) { Debug.logError(e, module); return hasRoleOperation; } } return hasRoleOperation; } public static boolean hasMatch(String entityName, List<GenericValue> targetOperations, List<String> roles, boolean hasPurposeOp, List<String> purposes, boolean hasStatusOp, String targStatusId) { boolean isMatch = false; // if (UtilValidate.isNotEmpty(targPrivilegeEnumId) && !targPrivilegeEnumId.equals("_NA_") && !targPrivilegeEnumId.equals("_00_")) { // need to do a lookup here to find the seq value of targPrivilegeEnumId. // The lookup could be a static store or it could be done on Enumeration entity. // } String lcEntityName = entityName.toLowerCase(); for (GenericValue targetOp: targetOperations) { String testRoleTypeId = (String)targetOp.get("roleTypeId"); String testContentPurposeTypeId = null; if (hasPurposeOp) testContentPurposeTypeId = (String)targetOp.get(lcEntityName + "PurposeTypeId"); String testStatusId = null; if (hasStatusOp) testStatusId = (String)targetOp.get("statusId"); //String testPrivilegeEnumId = null; //if (hasPrivilegeOp) //testPrivilegeEnumId = (String)targetOp.get("privilegeEnumId"); //int testPrivilegeSeq = 0; boolean purposesCond = (!hasPurposeOp || (purposes != null && purposes.contains(testContentPurposeTypeId)) || testContentPurposeTypeId.equals("_NA_")); boolean statusCond = (!hasStatusOp || testStatusId.equals("_NA_") || (targStatusId != null && targStatusId.equals(testStatusId))); //boolean privilegeCond = (!hasPrivilegeOp || testPrivilegeEnumId.equals("_NA_") || testPrivilegeSeq <= targPrivilegeSeq || testPrivilegeEnumId.equals(targPrivilegeEnumId)); boolean roleCond = (testRoleTypeId.equals("_NA_") || (roles != null && roles.contains(testRoleTypeId))); if (purposesCond && statusCond && roleCond) { isMatch = true; break; } } return isMatch; } public static boolean hasMatch(GenericValue entity, PermissionConditionGetter permissionConditionGetter, RelatedRoleGetter relatedRoleGetter, AuxiliaryValueGetter auxiliaryValueGetter, String partyId, boolean checkAncestors) throws GenericEntityException { ModelEntity modelEntity = entity.getModelEntity(); Delegator delegator = entity.getDelegator(); String pkFieldName = modelEntity.getFirstPkFieldName(); String entityId = entity.getString(pkFieldName); if (Debug.verboseOn()) Debug.logVerbose("\n\nIN hasMatch: entityId:" + entityId + " partyId:" + partyId + " checkAncestors:" + checkAncestors, module); boolean isMatch = false; permissionConditionGetter.restart(); List<String> auxiliaryValueList = null; if (auxiliaryValueGetter != null) { auxiliaryValueGetter.init(delegator, entityId); auxiliaryValueList = auxiliaryValueGetter.getList(); if (Debug.verboseOn()) Debug.logVerbose(auxiliaryValueGetter.dumpAsText(), module); } else { if (Debug.verboseOn()) Debug.logVerbose("NO AUX GETTER", module); } List<String> roleValueList = null; if (relatedRoleGetter != null) { if (checkAncestors) { relatedRoleGetter.initWithAncestors(delegator, entity, partyId); } else { relatedRoleGetter.init(delegator, entityId, partyId, entity); } roleValueList = relatedRoleGetter.getList(); if (Debug.verboseOn()) Debug.logVerbose(relatedRoleGetter.dumpAsText(), module); } else { if (Debug.verboseOn()) Debug.logVerbose("NO ROLE GETTER", module); } String targStatusId = null; if (modelEntity.getField("statusId") != null) { targStatusId = entity.getString("statusId"); } if (Debug.verboseOn()) Debug.logVerbose("STATUS:" + targStatusId, module); while (permissionConditionGetter.getNext()) { String roleConditionId = permissionConditionGetter.getRoleValue(); String auxiliaryConditionId = permissionConditionGetter.getAuxiliaryValue(); String statusConditionId = permissionConditionGetter.getStatusValue(); boolean auxiliaryCond = (auxiliaryConditionId == null || auxiliaryConditionId.equals("_NA_") || (auxiliaryValueList != null && auxiliaryValueList.contains(auxiliaryConditionId)) ); boolean statusCond = (statusConditionId == null || statusConditionId.equals("_NA_") || (targStatusId != null && targStatusId.equals(statusConditionId))); boolean roleCond = (roleConditionId == null || roleConditionId.equals("_NA_") || (roleValueList != null && roleValueList.contains(roleConditionId))); if (auxiliaryCond && statusCond && roleCond) { if (Debug.verboseOn()) Debug.logVerbose("MATCHED: role:" + roleConditionId + " status:" + statusConditionId + " aux:" + auxiliaryConditionId, module); isMatch = true; break; } } return isMatch; } /** * getRelatedPurposes */ public static List<String> getRelatedPurposes(GenericValue entity, List<String> passedPurposes) { if (entity == null) return passedPurposes; List<String> purposeIds = null; if (passedPurposes == null) { purposeIds = new LinkedList<String>(); } else { purposeIds = new LinkedList<String>(); purposeIds.addAll(passedPurposes); } String entityName = entity.getEntityName(); String lcEntityName = entityName.toLowerCase(); List<GenericValue> purposes = null; try { purposes = entity.getRelated(entityName + "Purpose", null, null, true); } catch (GenericEntityException e) { Debug.logError(e, "No associated purposes found. ", module); return purposeIds; } for (GenericValue val: purposes) { purposeIds.add((String) val.get(lcEntityName + "PurposeTypeId")); } return purposeIds; } /** * getUserRoles * Queries for the ContentRoles associated with a Content entity * and returns the ones that match the user. * Follows group parties to see if the user is a member. */ public static List<String> getUserRoles(GenericValue entity, GenericValue userLogin, Delegator delegator) throws GenericEntityException { List<String> roles = new LinkedList<String>(); if (entity == null) return roles; String entityName = entity.getEntityName(); // TODO: Need to use ContentManagementWorker.getAuthorContent first roles.remove("OWNER"); // always test with the owner of the current content if (entity.get("createdByUserLogin") != null && userLogin != null) { String userLoginId = (String)userLogin.get("userLoginId"); String userLoginIdCB = (String)entity.get("createdByUserLogin"); //if (Debug.infoOn()) Debug.logInfo("userLoginId:" + userLoginId + ": userLoginIdCB:" + userLoginIdCB + ":", null); if (userLoginIdCB.equals(userLoginId)) { roles.add("OWNER"); //if (Debug.infoOn()) Debug.logInfo("in getUserRoles, passedRoles(0):" + passedRoles, null); } } String partyId = (String)userLogin.get("partyId"); List<GenericValue> relatedRoles = null; List<GenericValue> tmpRelatedRoles = entity.getRelated(entityName + "Role", null, null, true); relatedRoles = EntityUtil.filterByDate(tmpRelatedRoles); if (relatedRoles != null) { for (GenericValue contentRole: relatedRoles) { String roleTypeId = (String)contentRole.get("roleTypeId"); String targPartyId = (String)contentRole.get("partyId"); if (targPartyId.equals(partyId)) { if (!roles.contains(roleTypeId)) roles.add(roleTypeId); if (roleTypeId.equals("AUTHOR") && !roles.contains("OWNER")) roles.add("OWNER"); } else { // Party may be of "PARTY_GROUP" type, in which case the userLogin may still possess this role GenericValue party = null; String partyTypeId = null; try { party = contentRole.getRelatedOne("Party", false); partyTypeId = (String)party.get("partyTypeId"); if (partyTypeId != null && partyTypeId.equals("PARTY_GROUP")) { Map<String, Object> map = new HashMap<String, Object>(); // At some point from/thru date will need to be added map.put("partyIdFrom", partyId); map.put("partyIdTo", targPartyId); if (isGroupMember(map, delegator)) { if (!roles.contains(roleTypeId)) roles.add(roleTypeId); } } } catch (GenericEntityException e) { Debug.logError(e, "Error in finding related party. " + e.getMessage(), module); } } } } return roles; } /** * Tests to see if the user belongs to a group */ public static boolean isGroupMember(Map<String, ?> partyRelationshipValues, Delegator delegator) { boolean isMember = false; String partyIdFrom = (String)partyRelationshipValues.get("partyIdFrom") ; String partyIdTo = (String)partyRelationshipValues.get("partyIdTo") ; //String roleTypeIdFrom = "PERMISSION_GROUP_MBR"; //String roleTypeIdTo = "PERMISSION_GROUP"; //Timestamp fromDate = UtilDateTime.nowTimestamp(); //Timestamp thruDate = UtilDateTime.getDayStart(UtilDateTime.nowTimestamp(), 1); //if (partyRelationshipValues.get("roleTypeIdFrom") != null) { // roleTypeIdFrom = (String)partyRelationshipValues.get("roleTypeIdFrom") ; //} //if (partyRelationshipValues.get("roleTypeIdTo") != null) { // roleTypeIdTo = (String)partyRelationshipValues.get("roleTypeIdTo") ; //} //if (partyRelationshipValues.get("fromDate") != null) { // fromDate = (Timestamp)partyRelationshipValues.get("fromDate") ; //} //if (partyRelationshipValues.get("thruDate") != null) { // thruDate = (Timestamp)partyRelationshipValues.get("thruDate") ; //} //EntityExpr relationExpr = EntityCondition.makeCondition("partyRelationshipTypeId", "CONTENT_PERMISSION"); //EntityExpr roleTypeIdFromExpr = EntityCondition.makeCondition("roleTypeIdFrom", "CONTENT_PERMISSION_GROUP_MEMBER"); //EntityExpr roleTypeIdToExpr = EntityCondition.makeCondition("roleTypeIdTo", "CONTENT_PERMISSION_GROUP"); //EntityExpr fromExpr = EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN_EQUAL_TO, fromDate); //EntityCondition thruCond = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("thruDate", null), // EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, thruDate)), EntityOperator.OR); // This method is simplified to make it work, these conditions need to be added back in. //List joinList = UtilMisc.toList(fromExpr, thruCond, partyFromExpr, partyToExpr, relationExpr); List<GenericValue> partyRelationships = null; try { partyRelationships = EntityQuery.use(delegator).from("PartyRelationship").where("partyIdFrom", partyIdFrom, "partyIdTo", partyIdTo).queryList(); } catch (GenericEntityException e) { Debug.logError(e, "Problem finding PartyRelationships. ", module); return false; } if (partyRelationships.size() > 0) { isMember = true; } return isMember; } public interface PermissionConditionGetter { public boolean getNext(); public String getRoleValue(); public String getOperationValue(); public String getStatusValue(); public int getPrivilegeValue() throws GenericEntityException; public String getAuxiliaryValue(); public void init(Delegator delegator) throws GenericEntityException; public void restart(); public void setOperationList(String operationIdString); public void setOperationList(List<String> opList); public List<String> getOperationList(); public String dumpAsText(); public void clearList(); } public static class StdPermissionConditionGetter implements PermissionConditionGetter { protected List<GenericValue> entityList; protected List<String> operationList; protected ListIterator<GenericValue> iter; protected GenericValue currentValue; protected String operationFieldName; protected String roleFieldName; protected String statusFieldName; protected String privilegeFieldName; protected String auxiliaryFieldName; protected String entityName; public StdPermissionConditionGetter () { this.operationFieldName = "contentOperationId"; this.roleFieldName = "roleTypeId"; this.statusFieldName = "statusId"; this.privilegeFieldName = "privilegeEnumId"; this.auxiliaryFieldName = "contentPurposeTypeId"; this.entityName = "ContentPurposeOperation"; } public StdPermissionConditionGetter (String entityName, String operationFieldName, String roleFieldName, String statusFieldName, String auxiliaryFieldName, String privilegeFieldName) { this.operationFieldName = operationFieldName; this.roleFieldName = roleFieldName ; this.statusFieldName = statusFieldName ; this.privilegeFieldName = privilegeFieldName ; this.auxiliaryFieldName = auxiliaryFieldName ; this.entityName = entityName; } public StdPermissionConditionGetter (Element getterElement) { this.operationFieldName = getterElement.getAttribute("operation-field-name"); this.roleFieldName = getterElement.getAttribute("role-field-name"); this.statusFieldName = getterElement.getAttribute("status-field-name"); this.privilegeFieldName = getterElement.getAttribute("privilege-field-name"); this.auxiliaryFieldName = getterElement.getAttribute("auxiliary-field-name"); this.entityName = getterElement.getAttribute("entity-name"); } public boolean getNext() { boolean hasNext = false; if (iter != null && iter.hasNext()) { currentValue = iter.next(); hasNext = true; } return hasNext; } public String getRoleValue() { return this.currentValue.getString(this.roleFieldName); } public String getOperationValue() { return this.currentValue.getString(this.operationFieldName); } public String getStatusValue() { return this.currentValue.getString(this.statusFieldName); } public int getPrivilegeValue() throws GenericEntityException { int privilegeEnumSeq = -1; String privilegeEnumId = null; Delegator delegator = currentValue.getDelegator(); if (UtilValidate.isNotEmpty(privilegeFieldName)) { privilegeEnumId = currentValue.getString(this.privilegeFieldName); } if (UtilValidate.isNotEmpty(privilegeEnumId)) { GenericValue privEnum = EntityQuery.use(delegator).from("Enumeration").where("enumId", privilegeEnumId).cache().queryOne(); if (privEnum != null) { String sequenceId = privEnum.getString("sequenceId"); try { privilegeEnumSeq = Integer.parseInt(sequenceId); } catch (NumberFormatException e) { // just leave it at -1 } } } return privilegeEnumSeq; } public String getAuxiliaryValue() { return this.currentValue.getString(this.auxiliaryFieldName); } public void setOperationList(String operationIdString) { this.operationList = null; if (UtilValidate.isNotEmpty(operationIdString)) { this.operationList = StringUtil.split(operationIdString, "|"); } } public void setOperationList(List<String> operationList) { this.operationList = operationList; } public List<String> getOperationList() { return this.operationList; } public void clearList() { this.entityList = new LinkedList<GenericValue>(); } public void init(Delegator delegator) throws GenericEntityException { this.entityList = EntityQuery.use(delegator) .from(this.entityName) .where(EntityCondition.makeCondition(operationFieldName, EntityOperator.IN, this.operationList)) .cache(true) .queryList(); } public void restart() { this.iter = null; if (this.entityList != null) { this.iter = this.entityList.listIterator(); } } public String dumpAsText() { List<String> fieldNames = UtilMisc.toList("roleFieldName", "auxiliaryFieldName", "statusFieldName"); Map<String, Integer> widths = UtilMisc.toMap("roleFieldName", Integer.valueOf(24), "auxiliaryFieldName", Integer.valueOf(24), "statusFieldName", Integer.valueOf(24)); StringBuilder buf = new StringBuilder(); Integer wid = null; buf.append("Dump for "); buf.append(this.entityName); buf.append(" ops:"); buf.append(StringUtil.join(this.operationList, ",")); buf.append("\n"); for (String fld: fieldNames) { wid = widths.get(fld); buf.append(fld); for (int i=0; i < (wid.intValue() - fld.length()); i++) buf.append("^"); buf.append(" "); } buf.append("\n"); for (String fld: fieldNames) { wid = widths.get(fld); for (int i=0; i < wid.intValue(); i++) buf.append("-"); buf.append(" "); } buf.append("\n"); if (entityList != null) { for (GenericValue contentPurposeOperation: this.entityList) { /* String contentOperationId = contentPurposeOperation.getString(this.operationFieldName); if (UtilValidate.isEmpty(contentOperationId)) { contentOperationId = ""; } wid = (Integer)widths.get("operationFieldName"); buf.append(contentOperationId); for (int i=0; i < (wid.intValue() - contentOperationId.length()); i++) buf.append("^"); buf.append(" "); */ String roleTypeId = contentPurposeOperation.getString(this.roleFieldName); if (UtilValidate.isEmpty(roleTypeId)) { roleTypeId = ""; } wid = widths.get("roleFieldName"); buf.append(roleTypeId); for (int i=0; i < (wid.intValue() - roleTypeId.length()); i++) buf.append("^"); buf.append(" "); String auxiliaryFieldValue = contentPurposeOperation.getString(this.auxiliaryFieldName); if (UtilValidate.isEmpty(auxiliaryFieldValue)) { auxiliaryFieldValue = ""; } wid = widths.get("auxiliaryFieldName"); buf.append(auxiliaryFieldValue); for (int i=0; i < (wid.intValue() - auxiliaryFieldValue.length()); i++) buf.append("^"); buf.append(" "); String statusId = contentPurposeOperation.getString(this.statusFieldName); if (UtilValidate.isEmpty(statusId)) { statusId = ""; } buf.append(statusId); /* wid = (Integer)widths.get("statusFieldName"); for (int i=0; i < (wid.intValue() - statusId.length()); i++) buf.append(" "); */ buf.append(" "); buf.append("\n"); } } return buf.toString(); } } public interface AuxiliaryValueGetter { public void init(Delegator delegator, String entityId) throws GenericEntityException; public List<String> getList(); public void clearList(); public String dumpAsText(); } public static class StdAuxiliaryValueGetter implements AuxiliaryValueGetter { protected List<String> entityList = new LinkedList<String>(); protected String auxiliaryFieldName; protected String entityName; protected String entityIdName; public StdAuxiliaryValueGetter () { this.auxiliaryFieldName = "contentPurposeTypeId"; this.entityName = "ContentPurpose"; this.entityIdName = "contentId"; } public StdAuxiliaryValueGetter (String entityName, String auxiliaryFieldName, String entityIdName) { this.auxiliaryFieldName = auxiliaryFieldName ; this.entityName = entityName; this.entityIdName = entityIdName; } public StdAuxiliaryValueGetter (Element getterElement) { this.auxiliaryFieldName = getterElement.getAttribute("auxiliary-field-name"); this.entityName = getterElement.getAttribute("entity-name"); this.entityIdName = getterElement.getAttribute("entity-id-name"); } public List<String> getList() { return entityList; } public void clearList() { this.entityList = new LinkedList<String>(); } public void setList(List<String> lst) { this.entityList = lst; } public void init(Delegator delegator, String entityId) throws GenericEntityException { if (this.entityList == null) { this.entityList = new LinkedList<String>(); } if (UtilValidate.isEmpty(this.entityName)) { return; } List<GenericValue> values = EntityQuery.use(delegator).from(this.entityName).where(this.entityIdName, entityId).cache(true).queryList(); for (GenericValue entity: values) { this.entityList.add(entity.getString(this.auxiliaryFieldName)); } } public String dumpAsText() { StringBuilder buf = new StringBuilder(); buf.append("AUXILIARY: "); if (entityList != null) { for (String val: entityList) { buf.append(val); buf.append(" "); } } return buf.toString(); } } public interface RelatedRoleGetter { public void init(Delegator delegator, String entityId, String partyId, GenericValue entity) throws GenericEntityException; public void initWithAncestors(Delegator delegator, GenericValue entity, String partyId) throws GenericEntityException; public List<String> getList(); public void clearList(); public void setList(List<String> lst); public String dumpAsText(); public boolean isOwner(GenericValue entity, String targetPartyId); } public static class StdRelatedRoleGetter implements RelatedRoleGetter { protected List<String> roleIdList = new LinkedList<String>(); protected String roleTypeFieldName; protected String partyFieldName; protected String entityName; protected String roleEntityIdName; protected String roleEntityName; protected String ownerEntityFieldName; public StdRelatedRoleGetter () { this.roleTypeFieldName = "roleTypeId"; this.partyFieldName = "partyId"; this.ownerEntityFieldName = "ownerContentId"; this.entityName = "Content"; this.roleEntityName = "ContentRole"; this.roleEntityIdName = "contentId"; } public StdRelatedRoleGetter (String entityName, String roleTypeFieldName, String roleEntityIdName, String partyFieldName, String ownerEntityFieldName, String roleEntityName) { this.roleTypeFieldName = roleTypeFieldName ; this.partyFieldName = partyFieldName ; this.ownerEntityFieldName = ownerEntityFieldName ; this.entityName = entityName; this.roleEntityName = roleEntityName; this.roleEntityIdName = roleEntityIdName; } public StdRelatedRoleGetter (Element getterElement) { this.roleTypeFieldName = getterElement.getAttribute("role-type-field-name"); this.partyFieldName = getterElement.getAttribute("party-field-name"); this.ownerEntityFieldName = getterElement.getAttribute("owner-entity-field-name"); this.entityName = getterElement.getAttribute("entity-name"); this.roleEntityName = getterElement.getAttribute("role-entity-name"); this.roleEntityIdName = getterElement.getAttribute("entity-id-name"); } public List<String> getList() { return this.roleIdList; } public void clearList() { this.roleIdList = new LinkedList<String>(); } public void setList(List<String> lst) { this.roleIdList = lst; } public void init(Delegator delegator, String entityId, String partyId, GenericValue entity) throws GenericEntityException { List<String> lst = getUserRolesFromList(delegator, UtilMisc.toList(entityId), partyId, this.roleEntityIdName, this.partyFieldName, this.roleTypeFieldName, this.roleEntityName); this.roleIdList.addAll(lst); if (isOwner(entity, partyId)) { this.roleIdList.add("OWNER"); } } public void initWithAncestors(Delegator delegator, GenericValue entity, String partyId) throws GenericEntityException { List<String> ownedContentIdList = new LinkedList<String>(); getEntityOwners(delegator, entity, ownedContentIdList, this.entityName, this.ownerEntityFieldName); if (ownedContentIdList.size() > 0) { List<String> lst = getUserRolesFromList(delegator, ownedContentIdList, partyId, this.roleEntityIdName, this.partyFieldName, this.roleTypeFieldName, this.roleEntityName); this.roleIdList.addAll(lst); } } public boolean isOwner(GenericValue entity, String targetPartyId) { boolean isOwner = false; if (entity == null || targetPartyId == null) { return false; } Delegator delegator = entity.getDelegator(); ModelEntity modelEntity = delegator.getModelEntity(entityName); if (modelEntity.getField("createdByUserLogin") == null) { return false; } if (entity.get("createdByUserLogin") != null) { String userLoginIdCB = (String)entity.get("createdByUserLogin"); try { GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginIdCB).cache().queryOne(); if (userLogin != null) { String partyIdCB = userLogin.getString("partyId"); if (partyIdCB != null) { if (partyIdCB.equals(targetPartyId)) { isOwner = true; } } } } catch (GenericEntityException e) { Debug.logInfo(e.getMessage() + " Returning false for 'isOwner'.", module); } } return isOwner; } public String dumpAsText() { StringBuilder buf = new StringBuilder(); buf.append("ROLES: "); if (roleIdList != null) { for (String val: roleIdList) { buf.append(val); buf.append(" "); } } return buf.toString(); } } public static List<String> getUserRolesFromList(Delegator delegator, List<String> idList, String partyId, String entityIdFieldName, String partyIdFieldName, String roleTypeIdFieldName, String entityName) throws GenericEntityException { EntityExpr expr = EntityCondition.makeCondition(entityIdFieldName, EntityOperator.IN, idList); EntityExpr expr2 = EntityCondition.makeCondition(partyIdFieldName, partyId); List<GenericValue> roleList = EntityQuery.use(delegator) .from(entityName) .where(EntityCondition.makeCondition(UtilMisc.toList(expr, expr2))) .cache(true) .queryList(); List<GenericValue> roleListFiltered = EntityUtil.filterByDate(roleList); Set<String> distinctSet = new HashSet<String>(); for (GenericValue contentRole: roleListFiltered) { String roleTypeId = contentRole.getString(roleTypeIdFieldName); distinctSet.add(roleTypeId); } List<String> distinctList = Arrays.asList(distinctSet.toArray(new String[distinctSet.size()])); return distinctList; } public static void getEntityOwners(Delegator delegator, GenericValue entity, List<String> contentOwnerList, String entityName, String ownerIdFieldName) throws GenericEntityException { String ownerContentId = entity.getString(ownerIdFieldName); if (UtilValidate.isNotEmpty(ownerContentId)) { contentOwnerList.add(ownerContentId); ModelEntity modelEntity = delegator.getModelEntity(entityName); String pkFieldName = modelEntity.getFirstPkFieldName(); GenericValue ownerContent = EntityQuery.use(delegator).from(entityName).where(pkFieldName, ownerContentId).cache(true).queryOne(); if (ownerContent != null) { getEntityOwners(delegator, ownerContent, contentOwnerList, entityName, ownerIdFieldName); } } } public static int getPrivilegeEnumSeq(Delegator delegator, String privilegeEnumId) throws GenericEntityException { int privilegeEnumSeq = -1; if (UtilValidate.isNotEmpty(privilegeEnumId)) { GenericValue privEnum = EntityQuery.use(delegator).from("Enumeration").where("enumId", privilegeEnumId).cache().queryOne(); if (privEnum != null) { String sequenceId = privEnum.getString("sequenceId"); try { privilegeEnumSeq = Integer.parseInt(sequenceId); } catch (NumberFormatException e) { // just leave it at -1 } } } return privilegeEnumSeq; } }