/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/servlet/delivery/LoginServlet.java $ * $Id: LoginServlet.java 114375 2012-10-15 21:06:59Z ktsao@stanford.edu $ *********************************************************************************** * * Copyright (c) 2004, 2005, 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.tool.assessment.ui.servlet.delivery; import java.io.IOException; import java.net.URLEncoder; import java.util.Collection; import java.util.Iterator; import java.util.List; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.authz.cover.AuthzGroupService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.site.api.Group; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.tool.assessment.data.dao.assessment.AssessmentAccessControl; import org.sakaiproject.tool.assessment.data.dao.authz.AuthorizationData; import org.sakaiproject.tool.assessment.facade.AgentFacade; import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacade; import org.sakaiproject.tool.assessment.services.PersistenceService; import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService; import org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean; import org.sakaiproject.tool.assessment.ui.bean.shared.PersonBean; import org.sakaiproject.tool.assessment.ui.listener.delivery.BeginDeliveryActionListener; import org.sakaiproject.tool.assessment.ui.listener.delivery.DeliveryActionListener; import org.sakaiproject.tool.assessment.ui.listener.delivery.LinearAccessDeliveryActionListener; import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil; import org.sakaiproject.user.cover.UserDirectoryService; /** * <p>Title: Samigo</p> * <p>Description: Sakai Assessment Manager</p> * @author Ed Smiley * @version $Id: LoginServlet.java 114375 2012-10-15 21:06:59Z ktsao@stanford.edu $ */ public class LoginServlet extends HttpServlet { /** * */ private static final long serialVersionUID = -5495078878170443939L; private static Log log = LogFactory.getLog(LoginServlet.class); private SiteService siteService; public LoginServlet() { } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doPost(req,res); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String alias = req.getParameter("id"); if ((alias==null) ||("").equals(alias)){ log.warn("The published URL you have entered is incorrect. id is missing. Please check in Published Settings."); return; } HttpSession httpSession = req.getSession(true); httpSession.setMaxInactiveInterval(3600); // one hour PersonBean person = (PersonBean) ContextUtil.lookupBeanFromExternalServlet( "person", req, res); // we are going to use the delivery bean to flag that this access is via url // this is the flag that we will use in deliverAssessment.jsp to decide what // button to display - daisyf DeliveryBean delivery = (DeliveryBean) ContextUtil.lookupBeanFromExternalServlet( "delivery", req, res); // For SAK-7132. // As this class is only used for taking assessment via URL, // there should not be any assessment grading data at this point delivery.setAssessmentGrading(null); delivery.setActionString("takeAssessmentViaUrl"); // reset timer in case this is a timed assessment delivery.setTimeElapse("0"); delivery.setLastTimer(0); delivery.setTimeLimit("0"); delivery.setBeginAssessment(true); // set path delivery.setContextPath(req.getContextPath()); // 1. get publishedAssessment and check if anonymous is allowed // 2. If so, goto welcome.faces // 3. If not, goto login.faces // both pages will set agentId and then direct user to BeginAssessment PublishedAssessmentService service = new PublishedAssessmentService(); PublishedAssessmentFacade pub = service.getPublishedAssessmentIdByAlias(alias); if (pub==null){ log.warn("The published URL you have entered is incorrect. Please check in Published Settings."); return; } delivery.setAssessmentId(pub.getPublishedAssessmentId().toString()); delivery.setAssessmentTitle(pub.getTitle()); delivery.setPublishedAssessment(pub); RequestDispatcher dispatcher = null; String path = "/jsf/delivery/invalidAssessment.faces"; boolean relativePath = true; String agentIdString = ""; boolean isAuthorized = false; boolean isAuthenticated = false; // Determine if assessment accept Anonymous Users. If so, starting in version 2.0.1 // all users will be authenticated as anonymous for the assessment in this case. //boolean anonymousAllowed = false; String releaseTo = pub.getAssessmentAccessControl().getReleaseTo(); if (releaseTo != null && releaseTo.indexOf("Anonymous Users")> -1){ //anonymousAllowed = true; agentIdString = AgentFacade.createAnonymous(); isAuthenticated = true; isAuthorized = true; delivery.setAnonymousLogin(true); person.setAnonymousId(agentIdString); } else { // check membership agentIdString = req.getRemoteUser(); isAuthenticated = ( agentIdString!= null && !("").equals(agentIdString)); if (isAuthenticated){ if (releaseTo.indexOf(AssessmentAccessControl.RELEASE_TO_SELECTED_GROUPS)>-1) { isAuthorized = checkMembershipForGroupRelease(pub, req, res); } else { isAuthorized = checkMembership(pub, req, res); } // in 2.2, agentId is differnt from req.getRemoteUser() agentIdString = AgentFacade.getAgentString(); } } log.debug("*** agentIdString: "+agentIdString); String nextAction = delivery.checkFromViaUrlLogin(); log.debug("nextAction="+nextAction); if (isAuthorized){ // Assessment has been permanently removed if ("isRemoved".equals(nextAction)){ path = "/jsf/delivery/isRemoved.faces"; } // Assessment is available for taking else if ("safeToProceed".equals(nextAction)){ // if assessment is available, set it in delivery bean for display in deliverAssessment.jsp BeginDeliveryActionListener listener = new BeginDeliveryActionListener(); listener.processAction(null); path = "/jsf/delivery/beginTakingAssessment_viaurl.faces"; } // Assessment is currently not available (eg., retracted for edit, due date has passed, submission limit has been reached, etc) else if ("assessmentNotAvailable".equals(nextAction)){ path = "/jsf/delivery/assessmentNotAvailable.faces"; } else if ("isRetracted".equals(nextAction)){ path = "/jsf/delivery/isRetracted.faces"; } else if ("isRetractedForEdit".equals(nextAction)){ path = "/jsf/delivery/isRetractedForEdit.faces"; } else if ("discrepancyInData".equals(nextAction)){ path = "/jsf/delivery/discrepancyInData.faces"; } else if ("assessmentHasBeenSubmitted".equals(nextAction)){ path = "/jsf/delivery/assessmentHasBeenSubmitted.faces"; } else if ("noSubmissionLeft".equals(nextAction)){ path = "/jsf/delivery/noSubmissionLeft.faces"; } else if ("noLateSubmission".equals(nextAction)){ path = "/jsf/delivery/noLateSubmission.faces"; } else if ("timeExpired".equals(nextAction)){ path = "/jsf/delivery/timeExpired.faces"; } else { path = "/jsf/delivery/assessmentNotAvailable.faces"; } } else{ // notAuthorized if (!isAuthenticated){ if (AgentFacade.isStandaloneEnvironment()) { delivery.setActionString(null); path = "/jsf/delivery/login.faces"; } else{ relativePath = false; delivery.setActionString(null); path = "/authn/login?url=" + URLEncoder.encode(req.getRequestURL().toString()+"?id="+alias, "UTF-8"); } } else { //isAuthenticated but not authorized path = "/jsf/delivery/accessDenied.faces"; } } if ("true".equals(req.getParameter("fromDirect"))) { // send the user directly into taking the assessment... they already clicked start from the direct servlet if (delivery.getNavigation().trim() != null && "1".equals(delivery.getNavigation().trim())) { LinearAccessDeliveryActionListener linearDeliveryListener = new LinearAccessDeliveryActionListener(); linearDeliveryListener.processAction(null); } else { DeliveryActionListener deliveryListener = new DeliveryActionListener(); deliveryListener.processAction(null); } //TODO: Should be something a bit more robust as validate() can retun a lot of things... if ("takeAssessment".equals(delivery.validate())) { path = "/jsf/delivery/deliverAssessment.faces"; } } log.debug("***path"+path); if (relativePath){ dispatcher = req.getRequestDispatcher(path); dispatcher.forward(req, res); } else{ log.info("** servlet path="+req.getRequestURL().toString()); String url = req.getRequestURL().toString(); String context = req.getContextPath(); String finalUrl = url.substring(0,url.lastIndexOf(context))+path; log.info("**** finalUrl = "+finalUrl); res.sendRedirect(finalUrl); } } private boolean checkMembership(PublishedAssessmentFacade pub, HttpServletRequest req, HttpServletResponse res){ boolean isMember=false; // get list of site that this published assessment has been released to List l =PersistenceService.getInstance().getAuthzQueriesFacade(). getAuthorizationByFunctionAndQualifier("VIEW_PUBLISHED_ASSESSMENT", pub.getPublishedAssessmentId().toString()); for (int i=0;i<l.size();i++){ String siteId = ((AuthorizationData)l.get(i)).getAgentIdString(); isMember = PersistenceService.getInstance().getAuthzQueriesFacade(). checkMembership(siteId); if (isMember) break; } return isMember; } /** * added by gopalrc - Nov 2007 * * @param pub * @param req * @param res * @return */ private boolean checkMembershipForGroupRelease(PublishedAssessmentFacade pub, HttpServletRequest req, HttpServletResponse res){ boolean isMember=false; // get the site that owns the published assessment List l =PersistenceService.getInstance().getAuthzQueriesFacade(). getAuthorizationByFunctionAndQualifier("OWN_PUBLISHED_ASSESSMENT", pub.getPublishedAssessmentId().toString()); if (l == null || l.isEmpty()) { return false; } String siteId = ((AuthorizationData)l.get(0)).getAgentIdString(); Collection siteGroupsContainingUser = null; String currentUserId = UserDirectoryService.getCurrentUser().getId(); try { siteGroupsContainingUser = siteService.getSite(siteId).getGroupsWithMember(currentUserId); } catch (IdUnusedException ex) { // no site found } // get list of groups that this published assessment has been released to l =PersistenceService.getInstance().getAuthzQueriesFacade(). getAuthorizationByFunctionAndQualifier("TAKE_PUBLISHED_ASSESSMENT", pub.getPublishedAssessmentId().toString()); for (int i=0;i<l.size();i++){ String groupId = ((AuthorizationData)l.get(i)).getAgentIdString(); isMember = isUserInAuthorizedGroup(groupId, siteGroupsContainingUser); if (isMember) break; } return isMember; } /** * added by gopalrc - Nov 2007 * * @param authorizedGroupId * @param userGroups * @return */ private boolean isUserInAuthorizedGroup(String authorizedGroupId, Collection userGroups) { if (userGroups==null || userGroups.isEmpty() || authorizedGroupId==null || authorizedGroupId.equals("")) { return false; } Iterator userGroupsIter = userGroups.iterator(); while (userGroupsIter.hasNext()) { Group group = (Group) userGroupsIter.next(); if (group.getId().equals(authorizedGroupId)) { return true; } } return false; } }