/**********************************************************************************
* $URL$
* $Id$
***********************************************************************************
*
* Copyright (c) 2008 The Sakai Foundation.
*
* Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
*
* 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.theospi.portfolio.matrix.util;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.sakaiproject.authz.api.SecurityAdvisor;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.entitybroker.EntityBroker;
import org.sakaiproject.entitybroker.EntityReference;
import org.sakaiproject.entitybroker.access.HttpServletAccessProvider;
import org.sakaiproject.entitybroker.access.HttpServletAccessProviderManager;
import org.sakaiproject.tool.api.ActiveTool;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.api.Tool;
import org.sakaiproject.tool.api.ToolException;
import org.sakaiproject.tool.cover.ActiveToolManager;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.util.Web;
import org.theospi.portfolio.matrix.MatrixCellEntityProvider;
/**
* Does a redirect to allow basic DirectServlet access to matrix cell Entities
*
*/
public class RedirectingMatrixCellEntityServlet extends HttpServlet
implements HttpServletAccessProvider {
private static final long serialVersionUID = 0L;
private EntityBroker entityBroker;
private HttpServletAccessProviderManager accessProviderManager;
/**
* Initialize the servlet.
*
* @param config
* The servlet config.
* @throws ServletException
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
entityBroker = (EntityBroker) ComponentManager
.get("org.sakaiproject.entitybroker.EntityBroker");
accessProviderManager = (HttpServletAccessProviderManager) ComponentManager
.get("org.sakaiproject.entitybroker.access.HttpServletAccessProviderManager");
if (accessProviderManager != null)
accessProviderManager.registerProvider(MatrixCellEntityProvider.ENTITY_PREFIX, this);
}
public void handleAccess(HttpServletRequest req, HttpServletResponse res, EntityReference ref) {
Session session = SessionManager.getCurrentSession();
if (SessionManager.getCurrentSessionUserId() == null) {
doLogin(req, res, session, req.getPathInfo());
return;
}
Map<String, String> props = entityBroker.getProperties(req.getPathInfo());
String target = props.get("url");
String user = props.get("security.user");
String site_function = props.get("security.site.function");
String site_secref = props.get("security.site.ref");
//decPageId is used to determine if a user has access to this cell. It is a suggestion to make sure
//the user has access to that page and that that page is linked to the current cell.
String decPageId = props.get("decPageId");
try {
Object sessionAdvisors = session.getAttribute("sitevisit.security.advisor");
Set<SecurityAdvisor> siteAdvisors = new HashSet<SecurityAdvisor>();
if (sessionAdvisors != null) {
siteAdvisors = (Set<SecurityAdvisor>)sessionAdvisors;
}
siteAdvisors.add(new MySecurityAdvisor(user, site_function, site_secref));
//dump a couple of advisors into session so we can get at them outside of this threadlocal
session.setAttribute("sitevisit.security.advisor", siteAdvisors);
session.setAttribute("decPageId", decPageId);
res.sendRedirect(target);
}
catch (IOException e) {
e.printStackTrace();
}
return;
}
private void doLogin(HttpServletRequest req, HttpServletResponse res, Session session, String returnPath) {
session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(req, returnPath));
ActiveTool tool = ActiveToolManager.getActiveTool("sakai.login");
// to skip container auth for this one, forcing things to be handled
// internaly, set the "extreme" login path
String loginPath = "/login";
String context = req.getContextPath() + req.getServletPath() + loginPath;
try {
tool.help(req, res, context, loginPath);
} catch (ToolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* A simple SecurityAdviser that can be used to override permissions on one reference string for one user for one function.
*/
private class MySecurityAdvisor implements SecurityAdvisor
{
protected String m_userId;
protected String m_function;
protected String m_reference;
public MySecurityAdvisor(String userId, String function, String reference)
{
m_userId = userId;
m_function = function;
m_reference = reference;
}
public SecurityAdvice isAllowed(String userId, String function, String reference)
{
SecurityAdvice rv = SecurityAdvice.PASS;
if (m_userId.equals(userId) && m_function.equals(function) && m_reference.equals(reference))
{
rv = SecurityAdvice.ALLOWED;
}
return rv;
}
public boolean equals(Object obj) {
MySecurityAdvisor mine = (MySecurityAdvisor)obj;
if (mine == null) return false;
if (mine.m_userId == null && m_userId != null) return false;
if (mine.m_function == null && m_function != null) return false;
if (mine.m_reference == null && m_reference != null) return false;
if (mine.m_userId != null && m_userId == null) return false;
if (mine.m_function != null && m_function == null) return false;
if (mine.m_reference != null && m_reference == null) return false;
if (m_userId.equals(mine.m_userId) && m_function.equals(mine.m_function) && m_reference.equals(mine.m_reference))
return true;
return false;
}
public int hashCode() {
int result;
result = m_userId.hashCode();
result = 29 * result + (m_function != null ? m_function.hashCode() : 0);
result = 29 * result + (m_reference != null ? m_reference.hashCode() : 0);
return result;
}
}
}