package org.sakaiproject.assignment.tool; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; 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.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.assignment.entityproviders.AssignmentEntityProvider; import org.sakaiproject.authz.api.SecurityAdvisor; import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.entitybroker.EntityBroker; import org.sakaiproject.entitybroker.EntityView; import org.sakaiproject.entitybroker.access.EntityViewAccessProvider; import org.sakaiproject.entitybroker.access.EntityViewAccessProviderManager; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.SessionManager; /** * Does a redirect to allow basic DirectServlet access to old assignment * Entities * * @author Joshua Ryan josh@asu.edu alt^I * */ public class RedirectingAssignmentEntityServlet extends HttpServlet implements EntityViewAccessProvider { private static Log M_log = LogFactory .getLog(RedirectingAssignmentEntityServlet.class); private static final long serialVersionUID = 0L; private EntityBroker entityBroker; private SessionManager sessionManager; private EntityViewAccessProviderManager accessProviderManager; /** * Initialize the servlet. * * @param config * The servlet config. * @throws ServletException */ public void init(ServletConfig config) throws ServletException { M_log.info("init()"); super.init(config); entityBroker = (EntityBroker) ComponentManager .get("org.sakaiproject.entitybroker.EntityBroker"); sessionManager = (SessionManager) ComponentManager .get("org.sakaiproject.tool.api.SessionManager"); accessProviderManager = (EntityViewAccessProviderManager) ComponentManager .get("org.sakaiproject.entitybroker.access.EntityViewAccessProviderManager"); if (accessProviderManager != null) { accessProviderManager.registerProvider( AssignmentEntityProvider.ENTITY_PREFIX, this); } } public void handleAccess(EntityView view, HttpServletRequest req, HttpServletResponse res) { M_log.debug("handleAccess()"); Map<String, String> props = entityBroker.getProperties(req .getPathInfo()); String target = props.get("url"); M_log.debug("handleAccess() -> " + target); String user = props.get("security.user"); String site_function = props.get("security.site.function"); String site_secref = props.get("security.site.ref"); String assignment_function = props.get("security.assignment.function"); String assignment_grade_function = props .get("security.assignment.grade.function"); String assignment_secref = props.get("security.assignment.ref"); String assignment_grade_secref = props .get("security.assignment.grade.ref"); String submissionAttachmentRefStrs = props .get("submissionAttachmentRefs"); Session session = sessionManager.getCurrentSession(); clearSessionAttributes(session); if (submissionAttachmentRefStrs != null) { String[] submissionAttachmentRefs = submissionAttachmentRefStrs .split(":::"); session.setAttribute( "assignment.content.security.advisor", new MySecurityAdvisor(user, "content.read", Arrays .asList(submissionAttachmentRefs))); session.setAttribute("assignment.content.decoration.wrapper.refs", submissionAttachmentRefs); } String decoratedContentWrapper = props .get("assignment.content.decoration.wrapper"); Object sessionAdvisors = session .getAttribute("sitevisit.security.advisor"); Set siteAdvisors = new HashSet(); if (sessionAdvisors != null) { siteAdvisors = (Set) 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); List<String> assignment_functions = new ArrayList<String>(); assignment_functions.add(assignment_function); assignment_functions.add(assignment_grade_function); List<String> assignment_secrefs = new ArrayList<String>(); assignment_secrefs.add(assignment_secref); assignment_secrefs.add(assignment_grade_secref); SecurityAdvisor secAdv = new MySecurityAdvisor(user, assignment_functions, assignment_secrefs); session.setAttribute("assignment.security.advisor", secAdv); session.setAttribute("assignment.grade.security.advisor", secAdv); session.setAttribute("assignment.content.decoration.wrapper", decoratedContentWrapper); try { setNoCacheHeaders(res); res.sendRedirect(target); } catch (IOException e) { e.printStackTrace(); } return; } // set standard no-cache headers protected void setNoCacheHeaders(HttpServletResponse resp) { resp.setContentType("text/html; charset=UTF-8"); // some old date resp.addHeader("Expires", "Mon, 01 Jan 2001 00:00:00 GMT"); // TODO: do we need this? adding a date header is expensive contention // for the date formatter, ours or Tomcats. // resp.addDateHeader("Last-Modified", System.currentTimeMillis()); resp.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); resp.addHeader("Pragma", "no-cache"); } private void clearSessionAttributes(Session session) { session.removeAttribute("assignment.content.security.advisor"); session.removeAttribute("assignment.content.decoration.wrapper.refs"); } /** * 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 List<String> m_functions = new ArrayList<String>(); protected List<String> m_references = new ArrayList<String>(); public MySecurityAdvisor(String userId, String function, String reference) { m_userId = userId; m_functions.add(function); m_references.add(reference); } public MySecurityAdvisor(String userId, String function, List<String> references) { m_userId = userId; m_functions.add(function); m_references = references; } public MySecurityAdvisor(String userId, List<String> functions, List<String> references) { m_userId = userId; m_functions = functions; m_references = references; } public MySecurityAdvisor(String userId, List<String> functions, String reference) { m_userId = userId; m_functions = functions; m_references.add(reference); } public SecurityAdvice isAllowed(String userId, String function, String reference) { SecurityAdvice rv = SecurityAdvice.PASS; if (m_userId.equals(userId) && m_functions.contains(function) && m_references.contains(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_functions == null && m_functions != null) return false; if (mine.m_functions != null && mine.m_functions.isEmpty() && m_functions != null && !m_functions.isEmpty()) return false; if (mine.m_references == null && m_references != null) return false; if (mine.m_references != null && mine.m_references.isEmpty() && m_references != null && !m_references.isEmpty()) return false; if (mine.m_userId != null && m_userId == null) return false; if (mine.m_functions != null && m_functions == null) return false; if (mine.m_functions != null && !mine.m_functions.isEmpty() && m_functions != null && m_functions.isEmpty()) return false; if (mine.m_references != null && m_references == null) return false; if (mine.m_references != null && !mine.m_references.isEmpty() && m_references != null && m_references.isEmpty()) return false; // if both m_references == null, return true? if (mine.m_references == null && m_references == null) return true; Set<String> mineRSet = new HashSet<String>(mine.m_references); Set<String> thisRSet = new HashSet<String>(m_references); if (mineRSet.hashCode() != thisRSet.hashCode()) return false; Set<String> mineFSet = new HashSet<String>(mine.m_functions); Set<String> thisFSet = new HashSet<String>(m_functions); if (mineFSet.hashCode() != thisFSet.hashCode()) return false; if (m_userId.equals(mine.m_userId) && thisFSet.equals(mineFSet) && thisRSet.equals(mineRSet)) return true; return false; } public int hashCode() { int result; result = m_userId.hashCode(); result = 29 * result + (m_functions != null ? m_functions.hashCode() : 0); result = 29 * result + (m_references != null ? m_references.hashCode() : 0); return result; } } }