/******************************************************************************* * 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.security; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ServiceLoader; import javax.servlet.http.HttpSession; import org.apache.ofbiz.base.util.Assert; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.cache.UtilCache; 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.EntityConditionList; import org.apache.ofbiz.entity.condition.EntityExpr; import org.apache.ofbiz.entity.condition.EntityOperator; import org.apache.ofbiz.entity.util.EntityQuery; import org.apache.ofbiz.entity.util.EntityUtil; /** * A <code>Security</code> factory. */ public final class SecurityFactory { public static final String module = SecurityFactory.class.getName(); // The default implementation stores a Delegator reference, so we will cache by delegator name. // The goal is to remove Delegator references in the Security interface, then we can use a singleton // and eliminate the cache. private static final UtilCache<String, Security> authorizationCache = UtilCache.createUtilCache("security.AuthorizationCache"); /** * Returns a <code>Security</code> instance. The method uses Java's * <a href="http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html"><code>ServiceLoader</code></a> * to get a <code>Security</code> instance. If no instance is found, a default implementation is used. * The default implementation is based on/backed by the OFBiz entity engine. * * @param delegator The delegator * @return A <code>Security</code> instance */ @SuppressWarnings("deprecation") public static Security getInstance(Delegator delegator) throws SecurityConfigurationException { Assert.notNull("delegator", delegator); Security security = authorizationCache.get(delegator.getDelegatorName()); if (security == null) { Iterator<Security> iterator = ServiceLoader.load(Security.class).iterator(); if (iterator.hasNext()) { security = iterator.next(); } else { security = new OFBizSecurity(); } security.setDelegator(delegator); security = authorizationCache.putIfAbsentAndGet(delegator.getDelegatorName(), security); if (Debug.verboseOn()) { Debug.logVerbose("Security implementation " + security.getClass().getName() + " created for delegator " + delegator.getDelegatorName(), module); } } return security; } private SecurityFactory() {} private static final class OFBizSecurity implements Security { private Delegator delegator = null; protected static final Map<String, Map<String, String>> simpleRoleEntity = UtilMisc.toMap( "ORDERMGR", UtilMisc.<String, String>toMap("name", "OrderRole", "pkey", "orderId"), "FACILITY", UtilMisc.<String, String>toMap("name", "FacilityParty", "pkey", "facilityId"), "MARKETING", UtilMisc.<String, String>toMap("name", "MarketingCampaignRole", "pkey", "marketingCampaignId")); private OFBizSecurity() {} @Override public void clearUserData(GenericValue userLogin) { if (userLogin != null) { delegator.getCache().remove("UserLoginSecurityGroup", EntityCondition.makeCondition("userLoginId", EntityOperator.EQUALS, userLogin.getString("userLoginId"))); } } @Deprecated public Iterator<GenericValue> findUserLoginSecurityGroupByUserLoginId(String userLoginId) { try { List<GenericValue> collection = EntityUtil.filterByDate(EntityQuery.use(delegator).from("UserLoginSecurityGroup").where("userLoginId", userLoginId).cache(true).queryList()); return collection.iterator(); } catch (GenericEntityException e) { Debug.logWarning(e, module); return Collections.<GenericValue>emptyList().iterator(); } } @Deprecated public Delegator getDelegator() { return this.delegator; } @Override public boolean hasEntityPermission(String entity, String action, GenericValue userLogin) { if (userLogin == null || entity == null || action == null) return false; String permission = entity.concat(action); String adminPermission = entity.concat("_ADMIN"); Iterator<GenericValue> iterator = findUserLoginSecurityGroupByUserLoginId(userLogin.getString("userLoginId")); while (iterator.hasNext()) { GenericValue userLoginSecurityGroup = iterator.next(); if (securityGroupPermissionExists(userLoginSecurityGroup.getString("groupId"), permission)) return true; if (securityGroupPermissionExists(userLoginSecurityGroup.getString("groupId"), adminPermission)) return true; } return false; } @Override public boolean hasEntityPermission(String entity, String action, HttpSession session) { if (session == null) { return false; } GenericValue userLogin = (GenericValue) session.getAttribute("userLogin"); if (userLogin == null) { return false; } return hasEntityPermission(entity, action, userLogin); } @Override public boolean hasPermission(String permission, GenericValue userLogin) { if (userLogin == null) { return false; } Iterator<GenericValue> iterator = findUserLoginSecurityGroupByUserLoginId(userLogin.getString("userLoginId")); GenericValue userLoginSecurityGroup = null; while (iterator.hasNext()) { userLoginSecurityGroup = iterator.next(); if (securityGroupPermissionExists(userLoginSecurityGroup.getString("groupId"), permission)) return true; } return false; } @Override public boolean hasPermission(String permission, HttpSession session) { GenericValue userLogin = (GenericValue) session.getAttribute("userLogin"); if (userLogin == null) { return false; } return hasPermission(permission, userLogin); } /** * Like hasEntityPermission above, this checks the specified action, as well as for "_ADMIN" to allow for simplified * general administration permission, but also checks action_ROLE and validates the user is a member for the * application. * * @param application The name of the application corresponding to the desired permission. * @param action The action on the application corresponding to the desired permission. * @param entityName The name of the role entity to use for validation. * @param condition EntityCondition used to query the entityName. * @param userLogin The userLogin object for user to check against. * @return Returns true if the currently logged in userLogin has the specified permission, otherwise returns false. */ private boolean hasRolePermission(String application, String action, String entityName, EntityCondition condition, GenericValue userLogin) { if (userLogin == null) { return false; } // first check the standard permission if (hasEntityPermission(application, action, userLogin)) { return true; } // make sure we have what's needed for role security if (entityName == null || condition == null) { return false; } // now check the user for the role permission if (hasEntityPermission(application + "_ROLE", action, userLogin)) { // we have the permission now, we check to make sure we are allowed access try { List<GenericValue> roleTest = EntityQuery.use(delegator).from(entityName).where(condition).queryList(); if (!roleTest.isEmpty()) { return true; } } catch (GenericEntityException e) { Debug.logError(e, "Problems doing role security lookup on entity [" + entityName + "] using [" + condition + "]", module); return false; } } return false; } @Override public boolean hasRolePermission(String application, String action, String primaryKey, List<String> roles, GenericValue userLogin) { if (userLogin == null) { return false; } if (primaryKey.equals("") && roles == null) { if (hasEntityPermission(application, action, userLogin)) return true; if (hasEntityPermission(application + "_ROLE", action, userLogin)) return true; } String entityName = null; EntityCondition condition = null; Map<String, String> simpleRoleMap = OFBizSecurity.simpleRoleEntity.get(application); if (simpleRoleMap != null && roles != null) { entityName = simpleRoleMap.get("name"); String pkey = simpleRoleMap.get("pkey"); if (pkey != null) { List<EntityExpr> expressions = new ArrayList<EntityExpr>(); for (String role: roles) { expressions.add(EntityCondition.makeCondition("roleTypeId", EntityOperator.EQUALS, role)); } EntityConditionList<EntityExpr> exprList = EntityCondition.makeCondition(expressions, EntityOperator.OR); EntityExpr keyExpr = EntityCondition.makeCondition(pkey, primaryKey); EntityExpr partyExpr = EntityCondition.makeCondition("partyId", userLogin.getString("partyId")); condition = EntityCondition.makeCondition(exprList, keyExpr, partyExpr); } } return hasRolePermission(application, action, entityName, condition, userLogin); } @Override public boolean hasRolePermission(String application, String action, String primaryKey, List<String> roles, HttpSession session) { GenericValue userLogin = (GenericValue) session.getAttribute("userLogin"); return hasRolePermission(application, action, primaryKey, roles, userLogin); } @Override public boolean hasRolePermission(String application, String action, String primaryKey, String role, GenericValue userLogin) { List<String> roles = null; if (role != null && !role.equals("")) { roles = UtilMisc.toList(role); } return hasRolePermission(application, action, primaryKey, roles, userLogin); } @Override public boolean hasRolePermission(String application, String action, String primaryKey, String role, HttpSession session) { GenericValue userLogin = (GenericValue) session.getAttribute("userLogin"); return hasRolePermission(application, action, primaryKey, role, userLogin); } @Deprecated public boolean securityGroupPermissionExists(String groupId, String permission) { try { return EntityQuery.use(delegator).from("SecurityGroupPermission").where("groupId", groupId, "permissionId", permission).cache(true).queryOne() != null; } catch (GenericEntityException e) { Debug.logWarning(e, module); return false; } } @Deprecated public void setDelegator(Delegator delegator) { if (this.delegator != null) { throw new IllegalStateException("This object has been initialized already."); } Assert.notNull("delegator", delegator); this.delegator = delegator; } } }