Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -raf79204a6effce72a9c276513762d4d7f7d5ae1a -r00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b --- lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision af79204a6effce72a9c276513762d4d7f7d5ae1a) +++ lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b) @@ -49,6 +49,7 @@ msg.edit.tool.content.3 = Note that you cannot upload files to a tool's default content, only edit the default text. msg.roles.mandatory = You must assign at least one role. msg.roles.mandatory.users = You must assign at least one role for each user. +msg.password.generated = for user name "{0}" the following password was created: {1} organisation.state.ACTIVE = Active organisation.state.HIDDEN = Hidden organisation.state.ARCHIVED = Archived Index: lams_admin/src/java/org/lamsfoundation/lams/admin/service/IImportService.java =================================================================== diff -u -r80371e446858031dcb9d7fa4456a79e8ab71693c -r00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b --- lams_admin/src/java/org/lamsfoundation/lams/admin/service/IImportService.java (.../IImportService.java) (revision 80371e446858031dcb9d7fa4456a79e8ab71693c) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/service/IImportService.java (.../IImportService.java) (revision 00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b) @@ -42,6 +42,7 @@ public static final String IMPORT_GROUPS_HELP_PAGE = "Import+Groups"; public static final String STATUS_IMPORT_TOTAL = "importTotal"; public static final String STATUS_IMPORTED = "imported"; + public static final String STATUS_SUCCESSFUL = "successful"; public static final String IMPORT_FILE = "file"; public static final String IMPORT_RESULTS = "results"; public static final int THRESHOLD = 500; Index: lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java =================================================================== diff -u -r26a83b93c1ce8fa610895f50b57d44d6b7cc11db -r00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b --- lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java (.../ImportService.java) (revision 26a83b93c1ce8fa610895f50b57d44d6b7cc11db) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java (.../ImportService.java) (revision 00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b) @@ -39,6 +39,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.CellType; +import org.lamsfoundation.lams.integration.security.RandomPasswordGenerator; import org.lamsfoundation.lams.logevent.LogEvent; import org.lamsfoundation.lams.logevent.service.ILogEventService; import org.lamsfoundation.lams.themes.Theme; @@ -110,8 +111,7 @@ private static final short ADMIN_CHANGE_STATUS = 6; // class-wide variables - ArrayList results = new ArrayList<>(); - ArrayList rowResult = new ArrayList<>(); + List rowResult = new ArrayList<>(); private boolean emptyRow; private boolean hasError; private Organisation parentOrg; @@ -139,21 +139,21 @@ } @Override - public List parseSpreadsheet(File fileItem, String sessionId) throws IOException { + public List> parseSpreadsheet(File fileItem, String sessionId) throws IOException { if (isUserSpreadsheet(fileItem)) { return parseUserSpreadsheet(fileItem, sessionId); } else if (isRolesSpreadsheet(fileItem)) { return parseRolesSpreadsheet(fileItem, sessionId); } - return new ArrayList(); + return new ArrayList<>(); } // returns x size list where x is number of orgs. // each item in the list lists the id, name, and parent's id of that org; otherwise // the items in the list are error messages. @Override - public List parseGroupSpreadsheet(File fileItem, String sessionId) throws IOException { - results = new ArrayList<>(); + public List> parseGroupSpreadsheet(File fileItem, String sessionId) throws IOException { + List> results = new ArrayList<>(); parentOrg = service.getRootOrganisation(); HSSFSheet sheet = getSheet(fileItem); int startRow = sheet.getFirstRowNum(); @@ -272,8 +272,8 @@ } @Override - public List parseUserSpreadsheet(File fileItem, String sessionId) throws IOException { - results = new ArrayList<>(); + public List> parseUserSpreadsheet(File fileItem, String sessionId) throws IOException { + List> results = new ArrayList<>(); HSSFSheet sheet = getSheet(fileItem); int startRow = sheet.getFirstRowNum(); int endRow = sheet.getLastRowNum(); @@ -290,8 +290,9 @@ emptyRow = true; hasError = false; rowResult = new ArrayList<>(); + StringBuilder generatedPassword = new StringBuilder(); row = sheet.getRow(i); - user = parseUser(row, i); + user = parseUser(row, i, generatedPassword); if (emptyRow) { ImportService.log.debug("Row " + i + " is empty."); @@ -301,30 +302,37 @@ ImportService.log.debug("Row " + i + " has an error which has been sent to the browser."); results.add(rowResult); writeErrorsAuditLog(i + 1, rowResult, userDTO); - updateImportStatus(sessionId, results.size()); + updateImportStatus(sessionId, results.size(), successful); continue; } else { try { service.saveUser(user); successful++; writeAuditLog(user, userDTO); - ImportService.log.debug("Row " + i + " saved user: " + user.getLogin()); + ImportService.log.debug("Row " + i + " saved user: " + user.getLogin() + + (generatedPassword.length() > 0 ? " with a generated password" : "")); } catch (Exception e) { ImportService.log.debug(e); rowResult.add(messageService.getMessage("error.fail.add")); + generatedPassword = new StringBuilder(); } if (rowResult.size() > 0) { if (ImportService.log.isDebugEnabled()) { ImportService.log.debug("Row " + i + " has " + rowResult.size() + " messages."); } writeErrorsAuditLog(i + 1, rowResult, userDTO); } + if (generatedPassword.length() > 0) { + rowResult.add(messageService.getMessage("msg.password.generated", + new String[] { user.getLogin(), generatedPassword.toString() })); + } results.add(rowResult); - updateImportStatus(sessionId, results.size()); + updateImportStatus(sessionId, results.size(), successful); } } ImportService.log.debug("Found " + results.size() + " users in spreadsheet."); writeSuccessAuditLog(successful, userDTO, "audit.successful.user.import"); + return results; } @@ -336,15 +344,16 @@ ss.setAttribute(IImportService.STATUS_IMPORTED, 0); } - private void updateImportStatus(String sessionId, int imported) { + private void updateImportStatus(String sessionId, int imported, int successful) { HttpSession ss = SessionManager.getSession(sessionId); ss.removeAttribute(IImportService.STATUS_IMPORTED); ss.setAttribute(IImportService.STATUS_IMPORTED, imported); + ss.setAttribute(IImportService.STATUS_SUCCESSFUL, successful); } @Override - public List parseRolesSpreadsheet(File fileItem, String sessionId) throws IOException { - results = new ArrayList<>(); + public List> parseRolesSpreadsheet(File fileItem, String sessionId) throws IOException { + List> results = new ArrayList<>(); HSSFSheet sheet = getSheet(fileItem); int startRow = sheet.getFirstRowNum(); int endRow = sheet.getLastRowNum(); @@ -375,7 +384,7 @@ ImportService.log.debug("Row " + i + " has an error which has been sent to the browser."); results.add(rowResult); writeErrorsAuditLog(i + 1, rowResult, userDTO); - updateImportStatus(sessionId, results.size()); + updateImportStatus(sessionId, results.size(), successful); continue; } else { try { @@ -392,7 +401,7 @@ writeErrorsAuditLog(i + 1, rowResult, userDTO); } results.add(rowResult); - updateImportStatus(sessionId, results.size()); + updateImportStatus(sessionId, results.size(), successful); } } ImportService.log.debug("Found " + results.size() + " users in spreadsheet."); @@ -456,7 +465,7 @@ * gathers error messages for each cell as required, unless it's the login field in which case, flags whole row as * empty. */ - private User parseUser(HSSFRow row, int rowIndex) { + private User parseUser(HSSFRow row, int rowIndex, StringBuilder generatedPassword) { User user = new User(); String[] args = new String[1]; @@ -483,11 +492,9 @@ String password = parseStringCell(row.getCell(ImportService.PASSWORD)); // password validation if (StringUtils.isBlank(password)) { - rowResult.add(messageService.getMessage("error.password.required")); - hasError = true; - return null; - } - if (!ValidationUtil.isPasswordValueValid(password, password)) { + password = RandomPasswordGenerator.nextPassword(); + generatedPassword.append(password); + } else if (!ValidationUtil.isPasswordValueValid(password, password)) { rowResult.add(messageService.getMessage("label.password.restrictions")); hasError = true; return null; @@ -597,6 +604,12 @@ service.updatePassword(user, password); + if (generatedPassword.length() > 0) { + // if password was generated, make user change it on first log in + user.setChangePassword(true); + service.saveUser(user); + } + return user; } Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/ImportUserResultController.java =================================================================== diff -u -r80371e446858031dcb9d7fa4456a79e8ab71693c -r00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/ImportUserResultController.java (.../ImportUserResultController.java) (revision 80371e446858031dcb9d7fa4456a79e8ab71693c) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/controller/ImportUserResultController.java (.../ImportUserResultController.java) (revision 00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b) @@ -64,23 +64,25 @@ log.error("Couldn't check spreadsheet type!", e); } - int successful = 0; - for (int i = 0; i < results.size(); i++) { - ArrayList rowResult = (ArrayList) results.get(i); - if (rowResult.isEmpty()) { - successful++; + Integer successful = (Integer) ss.getAttribute(IImportService.STATUS_SUCCESSFUL); + if (successful == null) { + successful = 0; + for (int i = 0; i < results.size(); i++) { + ArrayList rowResult = (ArrayList) results.get(i); + if (rowResult.isEmpty()) { + successful++; + } } } - String[] args = new String[1]; - args[0] = String.valueOf(successful); request.setAttribute("results", results); - request.setAttribute("successful", messageService.getMessage(successMessageKey, args)); + request.setAttribute("successful", messageService.getMessage(successMessageKey, new Integer[] { successful })); // remove temporary session vars that allowed status to be displayed // to user during import ss.removeAttribute(IImportService.STATUS_IMPORT_TOTAL); ss.removeAttribute(IImportService.STATUS_IMPORTED); + ss.removeAttribute(IImportService.STATUS_SUCCESSFUL); ss.removeAttribute(IImportService.IMPORT_FILE); ss.removeAttribute(IImportService.IMPORT_RESULTS); Index: lams_common/src/java/org/lamsfoundation/lams/integration/security/RandomPasswordGenerator.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b --- lams_common/src/java/org/lamsfoundation/lams/integration/security/RandomPasswordGenerator.java (.../RandomPasswordGenerator.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_common/src/java/org/lamsfoundation/lams/integration/security/RandomPasswordGenerator.java (.../RandomPasswordGenerator.java) (revision 00f07d4e073c8b6fb447a5fbf2fa03782ba8cb4b) @@ -69,6 +69,17 @@ } /** + * Produce a password with + */ + public static String nextPassword() { + Integer passwordLength = Configuration.getAsInt(ConfigurationKeys.PASSWORD_POLICY_MINIMUM_CHARACTERS); + if (passwordLength == null || passwordLength < MINIMUM_PASSWORD_LENGTH) { + passwordLength = MINIMUM_PASSWORD_LENGTH; + } + return RandomPasswordGenerator.nextPassword(passwordLength); + } + + /** * Build a password that passes configured validation */ public static String nextPasswordValidated() {