Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/ImportedUser.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/ImportedUser.java (revision 0) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/ImportedUser.java (revision 0) @@ -0,0 +1,32 @@ +package org.sakaiproject.site.tool.helper.participant.impl; + +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; + +public class ImportedUser { + public String firstName = ""; + public String lastName = ""; + public String email = ""; + public boolean bad = true; + public String password = ""; + + public ImportedUser(String firstName,String lastName,String email) { + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + + try { + InternetAddress emailAddr = new InternetAddress(email); + + String[] tokens = email.split("@"); + + if(tokens.length == 2) + this.bad = false; + } + catch (AddressException ex) {} + } + + public void setPassword(String password) { + this.password = password; + } +} Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java (revision 90020) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java (working copy) @@ -1,18 +1,27 @@ package org.sakaiproject.site.tool.helper.participant.impl; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.Set; import java.util.Vector; +import org.apache.commons.fileupload.FileItem; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.validator.EmailValidator; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.sakaiproject.accountvalidator.logic.ValidationLogic; import org.sakaiproject.authz.api.AuthzGroup; import org.sakaiproject.authz.api.AuthzGroupService; @@ -37,11 +46,15 @@ import org.sakaiproject.user.api.UserIdInvalidException; import org.sakaiproject.user.api.UserNotDefinedException; import org.sakaiproject.user.api.UserPermissionException; +import org.sakaiproject.util.RequestFilter; import org.sakaiproject.util.StringUtil; import uk.org.ponder.messageutil.MessageLocator; import uk.org.ponder.messageutil.TargettedMessage; import uk.org.ponder.messageutil.TargettedMessageList; + +import javax.servlet.http.HttpServletRequest; + /** * * @author @@ -83,6 +96,43 @@ public MessageLocator messageLocator; private UserNotificationProvider notiProvider; + + /** + * We need this to get the uploaded file as snaffled by the request filter. + */ + private HttpServletRequest httpServletRequest; + public void setHttpServletRequest(HttpServletRequest req) { + this.httpServletRequest = req; + } + + /** + * As we import users we store their details here for use in further stages + * of the import sequence. + */ + private List importedUsers = new ArrayList(); + public List getImportedUsers() { + return importedUsers; + } + + /** + * As we add users to Sakai authn we add them to this list. It allows us to + * demonstrate a degree of transactionalism and remove the users if something + * goes wrong. Implemented as part of the import users from spreadsheet + * capability (SAK-20344). + */ + private List addedSakaiUsers = new ArrayList(); + public List getAddedSakaiUsers() { + return addedSakaiUsers; + } + + /** + * We store the import spreadsheet filename here so we can use it to build the + * filename for the download report later. + */ + private String userImportFilename; + public String getUserImportFilename() { + return userImportFilename; + } // Tool session attribute name used to schedule a whole page refresh. public static final String ATTR_TOP_REFRESH = "sakai.vppa.top.refresh"; @@ -1154,6 +1204,7 @@ sameRoleChoice = null; emailNotiChoice = Boolean.FALSE.toString(); userRoleEntries = new Vector(); + importedUsers = new ArrayList(); } public void setNotiProvider(UserNotificationProvider notiProvider) { @@ -1192,7 +1243,7 @@ int chooseArray = (int) (4 * Math.random()); switch (chooseArray) { case 0: - rndbuf.append(LOWER_ALPHA_ARRAY[(int) ( LOWER_ALPHA_ARRAY.length * Math.random())-1]); + rndbuf.append(LOWER_ALPHA_ARRAY[(int) ( LOWER_ALPHA_ARRAY.length * Math.random())/*-1*/]); break; case 1: rndbuf.append(UPPER_ALPHA_ARRAY[(int) ( UPPER_ALPHA_ARRAY.length * Math.random())]); @@ -1209,5 +1260,129 @@ } return rndbuf.toString(); } + + /** + * Grabs the uploaded file from the usersfile request attribute and extracts the user details + * from it, addding them to the importedUsers list as it goes. Expects at least three columns, + * the first three being first name, last name and email respectively. + */ + public String processUploadAndCheck() { + String uploadsDone = (String) httpServletRequest.getAttribute(RequestFilter.ATTR_UPLOADS_DONE); + + if (uploadsDone != null && uploadsDone.equals(RequestFilter.ATTR_UPLOADS_DONE)) { + + try { + FileItem usersFileItem = (FileItem) httpServletRequest.getAttribute("usersfile"); + if (usersFileItem != null && usersFileItem.getSize() > 0) { + byte[] data = usersFileItem.get(); + + userImportFilename = usersFileItem.getName(); + + importedUsers = new ArrayList(); + + try { + POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(data)); + HSSFWorkbook wb = new HSSFWorkbook(fs); + HSSFSheet sheet = wb.getSheetAt(0); + + for(Iterator rows = sheet.iterator();rows.hasNext();) { + HSSFRow row = (HSSFRow) rows.next(); + + if(row.getPhysicalNumberOfCells() < 3) continue; + + HSSFCell firstNameCell = row.getCell(0); + + if(HSSFCell.CELL_TYPE_STRING != firstNameCell.getCellType()) continue; + + String firstName = firstNameCell.getStringCellValue().trim(); + + HSSFCell lastNameCell = row.getCell(1); + + if(HSSFCell.CELL_TYPE_STRING != lastNameCell.getCellType()) continue; + + String lastName = lastNameCell.getStringCellValue().trim(); + + HSSFCell emailCell = row.getCell(2); + if(HSSFCell.CELL_TYPE_STRING != emailCell.getCellType()) continue; + String email = emailCell.getStringCellValue().trim().toLowerCase(); + + importedUsers.add(new ImportedUser(firstName,lastName,email)); + } + } + catch(IOException ioe) { + return "error"; + } + + return "uploaded"; + } + } + catch (Exception e){ + return "error"; + } + } + + + return "success"; + } + + private void removeAddedSakaiUsers() { + for(User su : addedSakaiUsers) { + + try { + userDirectoryService.removeUser(userDirectoryService.editUser(su.getId())); + } + catch (Exception e1) { + e1.printStackTrace(); + } + } + + addedSakaiUsers = new ArrayList(); + } + + /** + * Creates Sakai accounts for the users in importedUsers if not already present and then + * adds them to the userRoleEntries list. If there is an error adding any of the users then + * all of the users already added are rolled back, ie: removed. + */ + public String processCreateImportedUsers() { + + // We need this so we can rollback user creation on an error + addedSakaiUsers = new ArrayList(); + + for(ImportedUser user: importedUsers) { + + user.setPassword(generatePassword()); + + User sakaiUser = null; + + try { + sakaiUser = userDirectoryService.getUserByEid(user.email); + user.setPassword("EXISTING SAKAI USER"); + userRoleEntries.add(new UserRoleEntry(user.email, "")); + continue; + } + catch(UserNotDefinedException unde) { + } + + try { + boolean created = false; + + sakaiUser = userDirectoryService.addUser(null, user.email, user.firstName, user.lastName, user.email, user.password, "guest", null); + addedSakaiUsers.add(sakaiUser); + userRoleEntries.add(new UserRoleEntry(user.email, "")); + } + catch(Exception e) { + e.printStackTrace(); + removeAddedSakaiUsers(); + return "error"; + } + } + + return "addedtosakai"; + } + + public String processAddImportedUsersToSite() { + return roleChoice; + } } Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import1Producer.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import1Producer.java (revision 0) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import1Producer.java (revision 0) @@ -0,0 +1,73 @@ +package org.sakaiproject.site.tool.helper.participant.rsf; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.site.tool.helper.participant.impl.SiteAddParticipantHandler; +import org.sakaiproject.tool.api.SessionManager; +import org.sakaiproject.tool.api.Tool; +import org.sakaiproject.user.api.UserDirectoryService; + +import uk.ac.cam.caret.sakai.rsf.producers.FrameAdjustingProducer; +import uk.ac.cam.caret.sakai.rsf.util.SakaiURLUtil; +import uk.org.ponder.messageutil.MessageLocator; +import uk.org.ponder.rsf.components.UIBranchContainer; +import uk.org.ponder.rsf.components.UICommand; +import uk.org.ponder.rsf.components.UIContainer; +import uk.org.ponder.rsf.components.UIForm; +import uk.org.ponder.rsf.components.UIVerbatim; +import uk.org.ponder.rsf.flow.ARIResult; +import uk.org.ponder.rsf.flow.ActionResultInterceptor; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCase; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter; +import uk.org.ponder.rsf.view.ComponentChecker; +import uk.org.ponder.rsf.view.ViewComponentProducer; +import uk.org.ponder.rsf.viewstate.RawViewParameters; +import uk.org.ponder.rsf.viewstate.SimpleViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParamsReporter; +import uk.org.ponder.stringutil.StringList; + +/** + * @author Adrian Fish (a.fish@lancaster.ac.uk) + */ +public class Import1Producer implements ViewComponentProducer, NavigationCaseReporter, ActionResultInterceptor { + + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(Import1Producer.class); + + public SiteAddParticipantHandler handler; + public static final String VIEW_ID = "Import1"; + + public MessageLocator messageLocator; + public FrameAdjustingProducer frameAdjustingProducer; + public SessionManager sessionManager; + + public String getViewID() { + return VIEW_ID; + } + + public void fillComponents(UIContainer tofill, ViewParameters origviewparams, ComponentChecker checker) { + + UIBranchContainer content = UIBranchContainer.make(tofill, "content:"); + UIVerbatim.make(content, "import1.step1", messageLocator.getMessage("import1.step1")); + UIForm uploadForm = UIForm.make(content, "uploadform", ""); + UICommand.make(uploadForm, "continue", messageLocator.getMessage("import1.uploadandcheck"), "#{siteAddParticipantHandler.processUploadAndCheck}"); + UICommand.make(uploadForm, "cancel", messageLocator.getMessage("gen.cancel"), "#{siteAddParticipantHandler.processCancel}"); + } + + public List reportNavigationCases() { + List togo = new ArrayList(); + togo.add(new NavigationCase("uploaded", new SimpleViewParameters(Import2Producer.VIEW_ID))); + return togo; + } + + public void interceptActionResult(ARIResult result, ViewParameters incoming, Object actionReturn) { + if ("done".equals(actionReturn)) { + Tool tool = handler.getCurrentTool(); + result.resultingView = new RawViewParameters(SakaiURLUtil.getHelperDoneURL(tool, sessionManager)); + } + } +} Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import2Producer.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import2Producer.java (revision 0) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import2Producer.java (revision 0) @@ -0,0 +1,150 @@ +package org.sakaiproject.site.tool.helper.participant.rsf; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.site.tool.helper.participant.impl.SiteAddParticipantHandler; +import org.sakaiproject.site.tool.helper.participant.impl.ImportedUser; +import org.sakaiproject.tool.api.SessionManager; +import org.sakaiproject.tool.api.Tool; + +import uk.ac.cam.caret.sakai.rsf.producers.FrameAdjustingProducer; +import uk.ac.cam.caret.sakai.rsf.util.SakaiURLUtil; +import uk.org.ponder.messageutil.MessageLocator; +import uk.org.ponder.rsf.components.UIBranchContainer; +import uk.org.ponder.rsf.components.UICommand; +import uk.org.ponder.rsf.components.UIContainer; +import uk.org.ponder.rsf.components.UIForm; +import uk.org.ponder.rsf.components.UIInput; +import uk.org.ponder.rsf.components.UIInternalLink; +import uk.org.ponder.rsf.components.UIMessage; +import uk.org.ponder.rsf.components.UIOutput; +import uk.org.ponder.rsf.components.UIOutputMany; +import uk.org.ponder.rsf.components.UISelect; +import uk.org.ponder.rsf.components.UISelectChoice; +import uk.org.ponder.rsf.components.UISelectLabel; +import uk.org.ponder.rsf.components.decorators.UICSSDecorator; +import uk.org.ponder.rsf.components.decorators.UILabelTargetDecorator; +import uk.org.ponder.rsf.flow.ARIResult; +import uk.org.ponder.rsf.flow.ActionResultInterceptor; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCase; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter; +import uk.org.ponder.rsf.view.ComponentChecker; +import uk.org.ponder.rsf.view.ViewComponentProducer; +import uk.org.ponder.rsf.viewstate.RawViewParameters; +import uk.org.ponder.rsf.viewstate.SimpleViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParamsReporter; +import uk.org.ponder.stringutil.StringList; + +/** + * @author Adrian Fish (a.fish@lancaster.ac.uk) + */ +public class Import2Producer implements ViewComponentProducer, NavigationCaseReporter, ActionResultInterceptor { + + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(Import2Producer.class); + + public SiteAddParticipantHandler handler; + public static final String VIEW_ID = "Import2"; + + public MessageLocator messageLocator; + public FrameAdjustingProducer frameAdjustingProducer; + public SessionManager sessionManager; + + public String getViewID() { + return VIEW_ID; + } + + public void fillComponents(UIContainer tofill, ViewParameters origviewparams, ComponentChecker checker) { + + UIBranchContainer content = UIBranchContainer.make(tofill, "content:"); + + List users = handler.getImportedUsers(); + + boolean badData = false; + for(ImportedUser user: users) { + UIBranchContainer userBranch = UIBranchContainer.make(content,"userrow:",user.email); + UIOutput.make(userBranch,"fn",user.firstName); + UIOutput.make(userBranch,"ln",user.lastName); + UIOutput.make(userBranch,"email",user.email); + if(user.bad) { + badData = true; + Map cssMap = new HashMap(); + cssMap.put("background-color","red"); + userBranch.decorate(new UICSSDecorator(cssMap)); + } + } + + if(badData) { + UIMessage.make(content, "import2.error", "import2.error"); + } else { + UIMessage.make(content, "import2.okay", "import2.okay"); + + UIForm createForm = UIForm.make(content, "createForm", ""); + + // role choice + String[] roleValues = new String[] { "sameRole", "differentRole"}; + String[] roleLabels = new String[] { + messageLocator.getMessage("add.assign"), + messageLocator.getMessage("add.assign2") + }; + + StringList roleItems = new StringList(); + + UISelect roleSelect = UISelect.make(createForm, "select-roles", null, "#{siteAddParticipantHandler.roleChoice}", handler.roleChoice); + + roleSelect.optionnames = UIOutputMany.make(roleLabels); + String selectID = roleSelect.getFullID(); + for (int i = 0; i < roleValues.length; ++i) { + UIBranchContainer roleRow = UIBranchContainer.make(createForm,"role-row:", Integer.toString(i)); + UISelectLabel lb = UISelectLabel.make(roleRow, "role-label", selectID, i); + UISelectChoice choice =UISelectChoice.make(roleRow, "role-select", selectID, i); + UILabelTargetDecorator.targetLabel(lb, choice); + + roleItems.add(roleValues[i]); + } + roleSelect.optionlist.setValue(roleItems.toStringArray()); + + // status choice + String[] statusValues = new String[] { "active", "inactive"}; + String[] statusLabels = new String[] { + messageLocator.getMessage("sitegen.siteinfolist.active"), + messageLocator.getMessage("sitegen.siteinfolist.inactive") + }; + StringList statusItems = new StringList(); + UISelect statusSelect = UISelect.make(createForm, "select-status", null, "#{siteAddParticipantHandler.statusChoice}", handler.statusChoice); + statusSelect.optionnames = UIOutputMany.make(statusLabels); + String statusSelectID = statusSelect.getFullID(); + for (int i = 0; i < statusValues.length; ++i) { + UIBranchContainer statusRow = UIBranchContainer.make(createForm,"status-row:", Integer.toString(i)); + UISelectLabel lb = UISelectLabel.make(statusRow, "status-label", statusSelectID, i); + UISelectChoice choice =UISelectChoice.make(statusRow, "status-select", statusSelectID, i); + UILabelTargetDecorator.targetLabel(lb, choice); + statusItems.add(statusValues[i]); + } + statusSelect.optionlist.setValue(statusItems.toStringArray()); + + UICommand.make(createForm, "createButton", messageLocator.getMessage("import2.createusers"), "#{siteAddParticipantHandler.processCreateImportedUsers}"); + UICommand.make(createForm, "cancel", messageLocator.getMessage("gen.cancel"), "#{siteAddParticipantHandler.processCancel}"); + } + } + + public List reportNavigationCases() { + List togo = new ArrayList(); + togo.add(new NavigationCase("uploaded", new SimpleViewParameters(Import2Producer.VIEW_ID))); + togo.add(new NavigationCase("addedtosakai", new SimpleViewParameters(Import3Producer.VIEW_ID))); + return togo; + } + + public void interceptActionResult(ARIResult result, ViewParameters incoming, Object actionReturn) { + if ("done".equals(actionReturn)) { + Tool tool = handler.getCurrentTool(); + result.resultingView = new RawViewParameters(SakaiURLUtil.getHelperDoneURL(tool, sessionManager)); + } + } +} Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import3Producer.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import3Producer.java (revision 0) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/Import3Producer.java (revision 0) @@ -0,0 +1,94 @@ +package org.sakaiproject.site.tool.helper.participant.rsf; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.site.tool.helper.participant.impl.SiteAddParticipantHandler; +import org.sakaiproject.site.tool.helper.participant.impl.ImportedUser; +import org.sakaiproject.tool.api.SessionManager; +import org.sakaiproject.tool.api.Tool; + +import uk.ac.cam.caret.sakai.rsf.producers.FrameAdjustingProducer; +import uk.ac.cam.caret.sakai.rsf.util.SakaiURLUtil; +import uk.org.ponder.messageutil.MessageLocator; +import uk.org.ponder.messageutil.TargettedMessage; +import uk.org.ponder.messageutil.TargettedMessageList; +import uk.org.ponder.rsf.components.UIBranchContainer; +import uk.org.ponder.rsf.components.UICommand; +import uk.org.ponder.rsf.components.UIContainer; +import uk.org.ponder.rsf.components.UIForm; +import uk.org.ponder.rsf.components.UIInternalLink; +import uk.org.ponder.rsf.components.UIOutput; +import uk.org.ponder.rsf.flow.ARIResult; +import uk.org.ponder.rsf.flow.ActionResultInterceptor; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCase; +import uk.org.ponder.rsf.flow.jsfnav.NavigationCaseReporter; +import uk.org.ponder.rsf.view.ComponentChecker; +import uk.org.ponder.rsf.view.DefaultView; +import uk.org.ponder.rsf.view.ViewComponentProducer; +import uk.org.ponder.rsf.viewstate.RawViewParameters; +import uk.org.ponder.rsf.viewstate.SimpleViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParameters; +import uk.org.ponder.rsf.viewstate.ViewParamsReporter; +import uk.org.ponder.stringutil.StringList; + +/** + * @author Adrian Fish (a.fish@lancaster.ac.uk) + */ +public class Import3Producer implements ViewComponentProducer, NavigationCaseReporter, ActionResultInterceptor { + + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(Import3Producer.class); + + public SiteAddParticipantHandler handler; + public static final String VIEW_ID = "Import3"; + + public MessageLocator messageLocator; + public FrameAdjustingProducer frameAdjustingProducer; + public SessionManager sessionManager; + + public String getViewID() { + return VIEW_ID; + } + + public void fillComponents(UIContainer tofill, ViewParameters origviewparams, ComponentChecker checker) { + + UIBranchContainer content = UIBranchContainer.make(tofill, "content:"); + + List users = handler.getImportedUsers(); + + for(ImportedUser user: users) { + UIBranchContainer userBranch = UIBranchContainer.make(content,"userrow:",user.email); + UIOutput.make(userBranch,"login",user.email); + UIOutput.make(userBranch,"fn",user.firstName); + UIOutput.make(userBranch,"ln",user.lastName); + UIOutput.make(userBranch,"pw",user.password); + } + + UIInternalLink.make(content,"reportLink",new SimpleViewParameters(ImportReportProducer.VIEW_ID)); + + UIForm createForm = UIForm.make(content, "createForm", ""); + UICommand.make(createForm, "addToSiteButton", messageLocator.getMessage("import3.addtosite"), "#{siteAddParticipantHandler.processAddImportedUsersToSite}"); + UICommand.make(createForm, "cancel", messageLocator.getMessage("gen.cancel"), "#{siteAddParticipantHandler.processCancel}"); + } + + public List reportNavigationCases() { + List togo = new ArrayList(); + togo.add(new NavigationCase("uploaded", new SimpleViewParameters(Import2Producer.VIEW_ID))); + togo.add(new NavigationCase("addedtosakai", new SimpleViewParameters(Import3Producer.VIEW_ID))); + togo.add(new NavigationCase("sameRole", new SimpleViewParameters(SameRoleProducer.VIEW_ID))); + togo.add(new NavigationCase("differentRole", new SimpleViewParameters(DifferentRoleProducer.VIEW_ID))); + return togo; + } + + public void interceptActionResult(ARIResult result, ViewParameters incoming, Object actionReturn) { + if ("done".equals(actionReturn)) { + Tool tool = handler.getCurrentTool(); + result.resultingView = new RawViewParameters(SakaiURLUtil.getHelperDoneURL(tool, sessionManager)); + } + } +} Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/ImportReportProducer.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/ImportReportProducer.java (revision 0) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/ImportReportProducer.java (revision 0) @@ -0,0 +1,76 @@ +package org.sakaiproject.site.tool.helper.participant.rsf; + +import java.io.BufferedOutputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.sakaiproject.site.tool.helper.participant.impl.SiteAddParticipantHandler; +import org.sakaiproject.site.tool.helper.participant.impl.ImportedUser; + +import uk.org.ponder.rsf.components.UIContainer; +import uk.org.ponder.rsf.view.ComponentChecker; +import uk.org.ponder.rsf.view.ViewComponentProducer; +import uk.org.ponder.rsf.viewstate.ViewParameters; + +import javax.servlet.http.HttpServletResponse; + +/** + * @author Adrian Fish (a.fish@lancaster.ac.uk) + */ +public class ImportReportProducer implements ViewComponentProducer { + + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(ImportReportProducer.class); + + public SiteAddParticipantHandler handler; + public static final String VIEW_ID = "ImportReport"; + + private HttpServletResponse httpServletResponse; + public void setHttpServletResponse(HttpServletResponse res) { + this.httpServletResponse = res; + } + + public String getViewID() { + return VIEW_ID; + } + + public void fillComponents(UIContainer tofill, ViewParameters origviewparams, ComponentChecker checker) { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFRow headerRow = sheet.createRow(0); + headerRow.createCell(0).setCellValue("Login"); + headerRow.createCell(1).setCellValue("First Name"); + headerRow.createCell(2).setCellValue("Last Name"); + headerRow.createCell(3).setCellValue("Password"); + + int rowNum = 1; + for(ImportedUser user : handler.getImportedUsers()) { + HSSFRow row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue(user.email); + row.createCell(1).setCellValue(user.firstName); + row.createCell(2).setCellValue(user.lastName); + row.createCell(3).setCellValue(user.password); + } + + String fileName = handler.getUserImportFilename(); + fileName = fileName.replaceAll(" ", "_"); + int dotIndex = fileName.lastIndexOf("."); + fileName = fileName.substring(0,dotIndex) + "_report.xls"; + + try { + BufferedOutputStream bos = new BufferedOutputStream(httpServletResponse.getOutputStream()); + httpServletResponse.setStatus(HttpServletResponse.SC_OK); + httpServletResponse.setContentType("application/ms-excel"); + httpServletResponse.setHeader("Content-Disposition", "filename=" + fileName); + wb.write(bos); + bos.close(); + } + catch(Exception e) { + httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } +} Index: site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/AddProducer.java =================================================================== --- site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/AddProducer.java (revision 90020) +++ site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/rsf/AddProducer.java (working copy) @@ -22,6 +22,7 @@ import uk.org.ponder.rsf.components.UIContainer; import uk.org.ponder.rsf.components.UIForm; import uk.org.ponder.rsf.components.UIInput; +import uk.org.ponder.rsf.components.UIInternalLink; import uk.org.ponder.rsf.components.UIMessage; import uk.org.ponder.rsf.components.UIOutput; import uk.org.ponder.rsf.components.UIOutputMany; @@ -82,6 +83,8 @@ boolean isCourseSite = handler.isCourseSite(); UIBranchContainer content = UIBranchContainer.make(tofill, "content:"); + + UIInternalLink.make(content,"importLink",new SimpleViewParameters(Import1Producer.VIEW_ID)); org.sakaiproject.coursemanagement.api.CourseManagementService cms = (org.sakaiproject.coursemanagement.api.CourseManagementService) ComponentManager.get(org.sakaiproject.coursemanagement.api.CourseManagementService.class); Index: site-manage-participant-helper/src/bundle/org/sakaiproject/site/tool/participant/bundle/sitesetupgeneric.properties =================================================================== --- site-manage-participant-helper/src/bundle/org/sakaiproject/site/tool/participant/bundle/sitesetupgeneric.properties (revision 90020) +++ site-manage-participant-helper/src/bundle/org/sakaiproject/site/tool/participant/bundle/sitesetupgeneric.properties (working copy) @@ -1,5 +1,7 @@ java.theemail = The Email id must be made up of alpha numeric characters or any of !#$&'*+-=?^_`{|}~. (no spaces). java.addp = Add Participants +java.importfromfile = Import from File +java.importfromfileinstruction = Click here to import participants from a spreadsheet or csv file java.realm = The expected realm object was not found. java.isinval = ''{0}'' is invalid. ### (moot) java.nousers = No users available/selected for removal. @@ -103,3 +105,25 @@ nonOfficialAccountSectionTitle = Non-official Participants nonOfficialAccountName=Guest nonOfficialAccountLabel=Email Address of Non-official Participant + +#Import1 Vm +import1.title = Step 1: Upload a file containing the users you wish to add +import1.steps = Steps: +import1.step1 = 1. Select an Excel file (.xls NOT .xlsx please) containing your users details in three columns, first name, last name and then email. DO NOT INCLUDE A ROW OF COLUMN HEADERS! +import1.step2 = 2. Click 'Upload and Check'. The spreadsheet will be uploaded and the data checked for suitability. +import1.step3 = 3. View the results of the spreadsheet validation on the next screen. +import1.uploadandcheck = Upload and Check +import2.firstname = First Name +import2.lastname = Last Name +import2.email = Email +import2.back = Back +import2.check = Step 2: Check that your spreadsheet is ok +import2.error = The data you supplied contained errors (highlighted in red). The error is likely to be in the highlighted email address. You need to correct them in your spreadsheet and start again. +import2.okay = The data you supplied seems OK. Please check it over and, if you are happy with it, select the role you want the members to hold using the 'Role' drop down box and click the 'Create Users' button. +import2.createusers = Create Users +import3.report = Step 3: Report +import3.createdsuccessfully = These users have been given, or already had, Sakai accounts and their login details are contained in the table below. Click on 'Download Report' to download a spreadsheet version for your records. +import3.downloadreport = Download Report +import3.addtosite = Add to site +import3.login = Login +import3.password = Password Index: site-manage-participant-helper/src/webapp/WEB-INF/requestContext.xml =================================================================== --- site-manage-participant-helper/src/webapp/WEB-INF/requestContext.xml (revision 90020) +++ site-manage-participant-helper/src/webapp/WEB-INF/requestContext.xml (working copy) @@ -1,6 +1,10 @@ + + + + @@ -14,6 +18,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: site-manage-participant-helper/src/webapp/WEB-INF/web.xml =================================================================== --- site-manage-participant-helper/src/webapp/WEB-INF/web.xml (revision 90020) +++ site-manage-participant-helper/src/webapp/WEB-INF/web.xml (working copy) @@ -53,6 +53,10 @@ sakai.request org.sakaiproject.util.RequestFilter + sakai.request Index: site-manage-participant-helper/src/webapp/content/templates/Import2.html =================================================================== --- site-manage-participant-helper/src/webapp/content/templates/Import2.html (revision 0) +++ site-manage-participant-helper/src/webapp/content/templates/Import2.html (revision 0) @@ -0,0 +1,68 @@ + + + + Import from File - Confirm Users + + + + + + +
+
+

import2.check

+
import2.error
+
import2.okay
+ +
+ + + + + + + + + + + + +
First NameLast Nameemail
JoeBloggsjoe.bloggs@blogg.com
+ +
+ +

+ + + + + +
+ + +
+ + +

+ + + + + +
+ + +
+ +

+ + +

+
+
+
+ + Index: site-manage-participant-helper/src/webapp/content/templates/Import3.html =================================================================== --- site-manage-participant-helper/src/webapp/content/templates/Import3.html (revision 0) +++ site-manage-participant-helper/src/webapp/content/templates/Import3.html (revision 0) @@ -0,0 +1,45 @@ + + + + Import from File - Sakai Users Created + + + + + + +
+
+

import3.report

+ +
import3.createdsuccessfully
+ +
+ + + + + + + + + + + + + +
LoginFirst NameLast NamePassword
joe.bloggs@blogg.comJoeBloggspassword
+

import3.downloadreport

+ +
+

+ + +

+
+ +
+
+ + Index: site-manage-participant-helper/src/webapp/content/templates/ImportReport.html =================================================================== --- site-manage-participant-helper/src/webapp/content/templates/ImportReport.html (revision 0) +++ site-manage-participant-helper/src/webapp/content/templates/ImportReport.html (revision 0) @@ -0,0 +1,45 @@ + + + + Import from File - Sakai Users Created + + + + + + +
+
+

import3.report

+ +
import3.createdsuccessfully
+ +
+ + + + + + + + + + + + + +
LoginFirst NameLast NamePassword
joe.bloggs@blogg.comJoeBloggspassword
+

import3.downloadreport

+ +
+

+ + +

+
+ +
+
+ + Index: site-manage-participant-helper/src/webapp/content/templates/Add.html =================================================================== --- site-manage-participant-helper/src/webapp/content/templates/Add.html (revision 90020) +++ site-manage-participant-helper/src/webapp/content/templates/Add.html (working copy) @@ -14,6 +14,9 @@

Add Participant

+

msg=java.importfromfile

+

msg=java.importfromfileinstruction

+

@@ -84,4 +87,4 @@

- \ No newline at end of file + Index: site-manage-participant-helper/src/webapp/content/templates/Import1.html =================================================================== --- site-manage-participant-helper/src/webapp/content/templates/Import1.html (revision 0) +++ site-manage-participant-helper/src/webapp/content/templates/Import1.html (revision 0) @@ -0,0 +1,36 @@ + + + + Import from File - Select a file + + + + + + + +
+
+

import1.title

+

import1.steps

+ import1.step1 +
+ import1.step2 +
+ import1.step3 +
+
+
+ +
+
+

+ + +

+
+
+
+ + Index: site-manage-participant-helper/pom.xml =================================================================== --- site-manage-participant-helper/pom.xml (revision 90020) +++ site-manage-participant-helper/pom.xml (working copy) @@ -75,6 +75,32 @@ ${sakai.resetpass.version} provided + + org.springframework + spring + + + org.springframework + spring-webmvc + + + javax.servlet + servlet-api + + + commons-fileupload + commons-fileupload + + + org.apache.poi + poi + 3.6 + + + javax.mail + mail + 1.4.3 + commons-lang