/* * Copyright (c) JForum Team * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2) Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of "Rafael Steil" nor * the names of its contributors may be used to endorse * or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * This file creation date: 18/11/2003 / 23:09:15 * The JForum Project * http://www.jforum.net */ package net.jforum.repository; import net.jforum.JForumExecutionContext; import net.jforum.SessionFacade; import net.jforum.cache.CacheEngine; import net.jforum.cache.Cacheable; import net.jforum.dao.DataAccessDriver; import net.jforum.dao.GroupSecurityDAO; import net.jforum.dao.UserDAO; import net.jforum.entities.User; import net.jforum.entities.UserSession; import net.jforum.exceptions.SecurityLoadException; import net.jforum.security.PermissionControl; import org.apache.log4j.Logger; /** * @author Rafael Steil * @version $Id: SecurityRepository.java,v 1.25 2006/08/27 01:22:02 rafaelsteil Exp $ */ public class SecurityRepository implements Cacheable { private static final Logger logger = Logger.getLogger(SecurityRepository.class); private static CacheEngine cache; private static final String FQN = "security"; /** * @see net.jforum.cache.Cacheable#setCacheEngine(net.jforum.cache.CacheEngine) */ public void setCacheEngine(CacheEngine engine) { cache = engine; } /*** * Load user's roles. * * @param userId The user's id * @param force If <code>true</code>, forces a reload. If <code>false</code>, the call * will be ignored if the roles are already loaded. * * @see SecurityRepository#load(int) * @see SecurityRepository#load(User) * @see SecurityRepository#load(User, boolean) * @return PermissionControl */ public static PermissionControl load(int userId, boolean force) { if (force || cache.get(FQN, Integer.toString(userId)) == null) { UserDAO um = DataAccessDriver.getInstance().newUserDAO(); return SecurityRepository.load(um.selectById(userId), force); } return SecurityRepository.get(userId); } /** * Load user's roles. * * @param userId The users's id * * @see SecurityRepository#load(int, boolean) * @see SecurityRepository#load(User) * @see SecurityRepository#load(User, boolean) * @return PermissionControl */ public static PermissionControl load(int userId) { return SecurityRepository.load(userId, false); } /** * Load user's roles. * * @param user The <code>User</code> to load. * * @see SecurityRepository#load(int) * @see SecurityRepository#load(int, boolean), * @see SecurityRepository#load(User, boolean) * @return PermissionControl */ public static PermissionControl load(User user) { return SecurityRepository.load(user, false); } /** * Load user's roles. * * @param user The <code>User</code> to load * @param force If <code>true</code>, forces a reload. If <code>false</code>, the call * will be ignored if the roles are already loaded. * * @see SecurityRepository#load(int) * @see SecurityRepository#load(int, boolean) * @see SecurityRepository#load(User) * @return PermissionControl */ public static PermissionControl load(User user, boolean force) { String userId = Integer.toString(user.getId()); if (force || cache.get(FQN, userId) == null) { PermissionControl pc = new PermissionControl(); // load roles GroupSecurityDAO dao = DataAccessDriver.getInstance().newGroupSecurityDAO(); pc.setRoles(dao.loadRolesByUserGroups(user)); cache.add(FQN, userId, pc); return pc; } return SecurityRepository.get(user.getId()); } /** * Check if the logged user has access to the role. * This method gets user's id from its session. * * @param roleName The role name to verity * @return <code>true</code> if the user has access to the role, <code>false</code> if access is denied * @throws SecurityLoadException if case of erros while trying * to load the roles * @see #canAccess(String, String) * @see #canAccess(int, String, String) */ public static boolean canAccess(String roleName) { return canAccess(roleName, null); } public static boolean canAccess(int userId, String roleName) { return canAccess(userId, roleName, null); } /** * Check if the logged user has access to the role. * This method gets user's id from its session. * * @param roleName The role name to verify * @param value The value relacted to the role to verify for access * @return <code>true</code> if the user has access to the role, <code>false</code> if access is denied */ public static boolean canAccess(String roleName, String value) { UserSession us = SessionFacade.getUserSession(); if (us == null) { logger.warn("Found null userSession. Going anonymous. Session id #" + JForumExecutionContext.getRequest().getSessionContext().getId()); us = new UserSession(); us.makeAnonymous(); } return canAccess(us.getUserId(), roleName, value); } public static boolean canAccess(int userId, String roleName, String value) { PermissionControl pc = SecurityRepository.get(userId); if (pc == null) { throw new SecurityLoadException("Failed to load security roles for userId " + userId + " (null PermissionControl returned). " + "roleName=" + roleName + ", roleValue=" + value); } return (value != null ? pc.canAccess(roleName, value) : pc.canAccess(roleName)); } /** * Gets the permssion schema of some specific user. * If the roles of the user aren't loaded yet, a call * to {@link #load(int)} will be made. * * @param userId The user's id to get the permissions * @return The <code>PermissionControl</code> instance related * to the user id passed as argument * @throws SecurityLoadException if case of erros while trying * to load the roles */ public static PermissionControl get(int userId) { PermissionControl pc = (PermissionControl)cache.get(FQN, Integer.toString(userId)); if (pc == null) { try { pc = load(userId); } catch (Exception e) { throw new SecurityLoadException(e); } } return pc; } /** * Adds a new permission control schema to the cache * * @param userId The user's id to associate with the schema * @param pc The <code>PermissionControl</code> instance to add */ public static synchronized void add(int userId, PermissionControl pc) { cache.add(FQN, Integer.toString(userId), pc); } /** * Remove the cached roles from a specific user. * * @param userId The id of the user to remove from the cache */ public static synchronized void remove(int userId) { cache.remove(FQN, Integer.toString(userId)); } /** * Clear all cached security entries. */ public static synchronized void clean() { cache.remove(FQN); } }