/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/roster/trunk/roster-app/src/java/org/sakaiproject/tool/roster/RosterOverview.java $
* $Id: RosterOverview.java 125280 2013-05-31 03:23:54Z azeckoski@unicon.net $
***********************************************************************************
*
* Copyright (c) 2007, 2008, 2009 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.roster;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.apache.commons.lang.StringUtils;
import org.sakaiproject.api.app.roster.Participant;
import org.sakaiproject.api.app.roster.RosterFunctions;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterCsv;
import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterXls;
import org.sakaiproject.jsf.spreadsheet.SpreadsheetUtil;
import org.sakaiproject.jsf.util.LocaleUtil;
import org.sakaiproject.section.api.coursemanagement.CourseSection;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.user.api.User;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class RosterOverview extends BaseRosterPageBean {
private static final String DISPLAY_ROSTER_PRIVACY_MSG = "roster.privacy.display";
// UI method calls
public boolean isRenderModifyMembersInstructions() {
String siteRef = getSiteReference();
return filter.services.securityService.unlock(SiteService.SECURE_UPDATE_SITE, siteRef) ||
filter.services.securityService.unlock(SiteService.SECURE_UPDATE_SITE_MEMBERSHIP, siteRef);
}
/**
* Determine whether privacy message should be displayed. Will be shown if
* roster.privacy.display in sakai.properties is "true" and the user does
* not have roster.viewhidden permission
*
* @return
*/
public boolean isRenderPrivacyMessage() {
String msgEnabled = ServerConfigurationService.getString(DISPLAY_ROSTER_PRIVACY_MSG, Boolean.TRUE.toString());
if (Boolean.TRUE.toString().equalsIgnoreCase(msgEnabled)) {
return ! filter.services.securityService.unlock(RosterFunctions.ROSTER_FUNCTION_VIEWHIDDEN, getSiteReference());
} else {
return ! filter.services.securityService.unlock(RosterFunctions.ROSTER_FUNCTION_VIEWALL, getSiteReference());
}
}
public String getPageTitle() {
filter.services.eventTrackingService.post(filter.services.eventTrackingService.newEvent("roster.view",getSiteReference(),false));
return LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(),
ServicesBean.MESSAGE_BUNDLE, "title_overview");
}
public boolean isExportablePage() {
return filter.services.rosterManager.currentUserHasExportPerm();
}
public void export(ActionEvent event) {
List<List<Object>> spreadsheetData = new ArrayList<List<Object>>();
FacesContext facesContext = FacesContext.getCurrentInstance();
// Add the header row
List<Object> header = new ArrayList<Object>();
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_name"));
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_userId"));
if (isEmailColumnRendered()) {
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_email"));
}
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_role"));
spreadsheetData.add(header);
for(Iterator<Participant> participantIter = getParticipants().iterator(); participantIter.hasNext();) {
Participant participant = participantIter.next();
List<Object> row = new ArrayList<Object>();
row.add(participant.getUser().getSortName());
row.add(participant.getUser().getDisplayId());
if (isEmailColumnRendered()){
row.add(participant.getUser().getEmail());
}
row.add(participant.getRoleTitle());
spreadsheetData.add(row);
}
String spreadsheetNameRaw;
if(StringUtils.trimToNull(filter.sectionFilter) == null) {
spreadsheetNameRaw = filter.getCourseFilterTitle();
} else {
CourseSection section = filter.services.sectionAwareness.getSection(filter.getSectionFilter());
spreadsheetNameRaw = filter.getCourseFilterTitle() + "_" + section.getTitle();
}
String spreadsheetName = getDownloadFileName(spreadsheetNameRaw);
SpreadsheetUtil.downloadSpreadsheetData(spreadsheetData, spreadsheetName, new SpreadsheetDataFileWriterXls());
}
/**
* check to see if Early Alerts can be displayed
* @return true, if allowed
*/
public boolean isRenderAddAlert(){
return ServerConfigurationService.getBoolean("ssp.allowed.alerts", false) && isMaintainer();
}
/**
* check to see if current user is a site maintainer
* @return true, if user has a maintain role
*/
private boolean isMaintainer() {
boolean isMaintainer = false;
try {
String siteId = filter.services.toolManager.getCurrentPlacement().getContext();
Site site = filter.services.siteService.getSite(siteId);
Set<String> maintainers = site.getUsersHasRole(site.getMaintainRole());
String userId = filter.services.userDirectoryService.getCurrentUser().getId();
isMaintainer = maintainers.contains(userId);
} catch (Exception e) {
e.printStackTrace();
}
return isMaintainer;
}
/**
* Processes the event click when instructor wants to add an Early Alert in the SSP system
*/
public void addAlert(){
Map<String, String> attributes = new HashMap<String, String>();
String eaView = "ea.new";
// get participant external id
String participantEid = StringUtils.trimToNull((String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get("participantEid"));
attributes.put("participanteid", participantEid);
// get current date and time
Calendar c = Calendar.getInstance();
Date date = c.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String timeStamp = sdf.format(date);
attributes.put("timestamp", timeStamp);
try {
// get title of the site
String siteId = filter.services.toolManager.getCurrentPlacement().getContext();
Site site = filter.services.siteService.getSite(siteId);
String siteTitle = URLEncoder.encode(site.getTitle(), "UTF-8");
attributes.put("sitetitle", siteTitle);
// get the current user
User user = filter.services.userDirectoryService.getCurrentUser();
String instructorEid = user.getEid();
attributes.put("instructoreid", instructorEid);
} catch (Exception e) {
e.printStackTrace();
}
// set the view property
attributes.put("view", eaView);
String requestUrl = buildRequestUrl(attributes);
sendRequest(requestUrl);
}
/**
* gets the MD5 token for the URL to send to the SSP server
* @param instructorEid external ID of the instructor
* @param timeStamp the current timestamp
* @return the MD5 token
*/
private String getToken(String instructorEid, String timeStamp) {
String tokenHash = null;
String shared = ServerConfigurationService.getString("ssp.alerts.shared.password", "");
String tokenString = instructorEid + timeStamp + shared;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] token = tokenString.getBytes("UTF-8");
byte[] tokenMd5 = md.digest(token);
StringBuilder tokenEncoded = new StringBuilder(2*tokenMd5.length);
for(byte b : tokenMd5) {
tokenEncoded.append(String.format("%02x", b&0xff));
}
tokenHash = tokenEncoded.toString();
} catch (Exception e) {
e.printStackTrace();
}
return tokenHash;
}
/**
* builds the URL to send to the SSP server
* @param attributes HashMap of the attributes for the URL
* @return the full URL to send
*/
private String buildRequestUrl(Map<String, String> attributes) {
StringBuilder requestUrl = new StringBuilder();
String sspUrl = ServerConfigurationService.getString("ssp.server.url", "");
String token = getToken(attributes.get("instructoreid"), attributes.get("timestamp"));
// builds the URL with the necessary tokens
try {
requestUrl.append(sspUrl)
.append("?username=")
.append(attributes.get("instructoreid"))
.append("&formattedCourse=")
.append(attributes.get("sitetitle"))
.append("&studentSchoolId=")
.append(attributes.get("participanteid"))
.append("&timeStamp=")
.append(URLEncoder.encode(attributes.get("timestamp"), "UTF-8"))
.append("&token=")
.append(token)
.append("&view=")
.append(attributes.get("view"));
} catch (Exception e) {
e.printStackTrace();
}
return requestUrl.toString();
}
/**
* sends the URL to the SSP server
* @param requestUrl
*/
private void sendRequest(String requestUrl) {
String responseJson = "";
try {
// connect to SSP server
URL url = new URL(requestUrl);
URLConnection connection = url.openConnection();
// read response from SSP server
InputStreamReader inStream = new InputStreamReader(connection.getInputStream());
BufferedReader buff= new BufferedReader(inStream);
StringBuilder json = new StringBuilder();
String line = "";
while ((line = buff.readLine()) != null) {
json.append(line);
}
responseJson = json.toString();
// process JSON from response
Gson gson = new Gson();
Map<String, String> responseContent = gson.fromJson(responseJson, new TypeToken<Map<String, String>>(){}.getType());
// handle redirect
doRedirect(responseContent);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* handles the redirect to the Early Alert page for the instructor and student
* @param responseContent HashMap of the JSON response
*/
private void doRedirect(Map<String, String> responseContent) {
String redirectUrl = responseContent.get("URL");
// redirect browser to SSP Early Alert page
try {
FacesContext.getCurrentInstance().getExternalContext().redirect(redirectUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
}