Index: lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java =================================================================== RCS file: /usr/local/cvsroot/lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java,v diff -u -r1.20 -r1.20.2.1 --- lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java 9 Apr 2014 18:40:35 -0000 1.20 +++ lams_admin/src/java/org/lamsfoundation/lams/admin/service/ImportService.java 21 Oct 2015 11:44:57 -0000 1.20.2.1 @@ -74,411 +74,414 @@ */ public class ImportService implements IImportService { - private static Logger log = Logger.getLogger(ImportService.class); - public IUserManagementService service; - public MessageService messageService; - public IAuditService auditService; - - public IUserManagementService getService() { - return service; + private static Logger log = Logger.getLogger(ImportService.class); + public IUserManagementService service; + public MessageService messageService; + public IAuditService auditService; + + public IUserManagementService getService() { + return service; + } + + public void setService(IUserManagementService service) { + this.service = service; + } + + public MessageService getMessageService() { + return messageService; + } + + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } + + public IAuditService getAuditService() { + return auditService; + } + + public void setAuditService(IAuditService auditService) { + this.auditService = auditService; + } + + // spreadsheet column indexes for user spreadsheet + private static final short LOGIN = 0; + private static final short PASSWORD = 1; + private static final short TITLE = 2; + private static final short FIRST_NAME = 3; + private static final short LAST_NAME = 4; + private static final short AUTH_METHOD = 5; + private static final short EMAIL = 6; + private static final short FLASH_THEME = 7; + private static final short HTML_THEME = 8; + private static final short LOCALE = 9; + private static final short ADDRESS1 = 10; + private static final short ADDRESS2 = 11; + private static final short ADDRESS3 = 12; + private static final short CITY = 13; + private static final short STATE = 14; + private static final short POSTCODE = 15; + private static final short COUNTRY = 16; + private static final short DAY_PHONE = 17; + private static final short EVE_PHONE = 18; + private static final short MOB_PHONE = 19; + private static final short FAX = 20; + + // spreadsheet column indexes for userorgrole spreadsheet + private static final short ORGANISATION = 1; + private static final short ROLES = 2; + + // spreadsheet column indexes for groups spreadsheet + private static final short NAME = 0; + private static final short CODE = 1; + private static final short DESCRIPTION = 2; + private static final short LOCALE_ID = 3; + private static final short ORGANISATION_STATE = 4; + private static final short ADMIN_ADD_NEW_USERS = 5; + private static final short ADMIN_BROWSE_ALL_USERS = 6; + private static final short ADMIN_CHANGE_STATUS = 7; + + // class-wide variables + ArrayList results = new ArrayList(); + ArrayList rowResult = new ArrayList(); + private boolean emptyRow; + private boolean hasError; + private Organisation parentOrg; + + private HSSFSheet getSheet(FormFile fileItem) throws IOException { + POIFSFileSystem fs = new POIFSFileSystem(fileItem.getInputStream()); + HSSFWorkbook wb = new HSSFWorkbook(fs); + return wb.getSheetAt(0); + } + + public boolean isUserSpreadsheet(FormFile fileItem) throws IOException { + HSSFSheet sheet = getSheet(fileItem); + HSSFRow row = sheet.getRow(sheet.getFirstRowNum()); + String string = parseStringCell(row.getCell(PASSWORD)); + return (StringUtils.equals(string, "* password")) ? true : false; + } + + public boolean isRolesSpreadsheet(FormFile fileItem) throws IOException { + HSSFSheet sheet = getSheet(fileItem); + HSSFRow row = sheet.getRow(sheet.getFirstRowNum()); + String string = parseStringCell(row.getCell(ORGANISATION)); + return (StringUtils.equals(string, "* organisation")) ? true : false; + } + + public List parseSpreadsheet(FormFile fileItem, String sessionId) throws IOException { + if (isUserSpreadsheet(fileItem)) { + return parseUserSpreadsheet(fileItem, sessionId); + } else if (isRolesSpreadsheet(fileItem)) { + return parseRolesSpreadsheet(fileItem, sessionId); } + return new ArrayList(); + } - public void setService(IUserManagementService service) { - this.service = service; + // 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. + public List parseGroupSpreadsheet(FormFile fileItem) throws IOException { + results = new ArrayList(); + parentOrg = service.getRootOrganisation(); + HSSFSheet sheet = getSheet(fileItem); + int startRow = sheet.getFirstRowNum(); + int endRow = sheet.getLastRowNum(); + + log.debug("Parsing spreadsheet rows " + startRow + " through " + endRow); + + HSSFRow row; + Organisation org = null; + int successful = 0; + for (int i = startRow + 1; i < endRow + 1; i++) { + emptyRow = true; + hasError = false; + rowResult = new ArrayList(); + row = sheet.getRow(i); + if (row != null) { + org = parseGroup(row, i); + } + + // an empty row signifies a new group + if (emptyRow) { + log.debug("Row " + i + " is empty."); + parentOrg = service.getRootOrganisation(); + continue; + } + if (hasError) { + log.debug("Row " + i + " has an error which has been sent to the browser."); + results.add(rowResult); + continue; + } else { + org = service.saveOrganisation(org, getCurrentUserId()); + successful++; + rowResult.add(org.getOrganisationId().toString()); + rowResult.add(org.getName()); + rowResult.add(org.getParentOrganisation().getOrganisationId().toString()); + rowResult.add(org.getOrganisationType().getOrganisationTypeId().toString()); + writeOrgAuditLog(org); + // if we just added a group, then the rows under it become it's subgroups + if (parentOrg.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.ROOT_TYPE)) { + parentOrg = org; + } + results.add(rowResult); + } } - - public MessageService getMessageService() { - return messageService; + log.debug("Found " + results.size() + " orgs in spreadsheet."); + writeSuccessAuditLog(successful, null, "audit.successful.organisation.import"); + return results; + } + + private Integer getCurrentUserId() { + try { + UserDTO user = (UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER); + return user.getUserID(); + } catch (Exception e) { + log.error(e); } + return null; + } - public void setMessageService(MessageService messageService) { - this.messageService = messageService; + private Organisation parseGroup(HSSFRow row, int rowIndex) { + Organisation org = new Organisation(); + String[] args = new String[1]; + + String name = parseStringCell(row.getCell(NAME)); + + //validate organisation name + if (StringUtils.isBlank(name)) { + rowResult.add(messageService.getMessage("error.name.required")); + hasError = true; + return null; + + } else if (!ValidationUtil.isOrgNameValid(name)) { + rowResult.add(messageService.getMessage("error.name.invalid.characters")); + hasError = true; + return null; } - - public IAuditService getAuditService() { - return auditService; - } - public void setAuditService(IAuditService auditService) { - this.auditService = auditService; + org.setName(name); + org.setCode(parseStringCell(row.getCell(CODE))); + org.setDescription(parseStringCell(row.getCell(DESCRIPTION))); + + String localeId = parseStringCell(row.getCell(LOCALE_ID)); + SupportedLocale locale = getLocale(localeId); + if (locale == null) { + args[0] = "(" + localeId + ")"; + rowResult.add(messageService.getMessage("error.locale.invalid", args)); + hasError = true; + } else { + org.setLocale(locale); } - - // spreadsheet column indexes for user spreadsheet - private static final short LOGIN = 0; - private static final short PASSWORD = 1; - private static final short TITLE = 2; - private static final short FIRST_NAME = 3; - private static final short LAST_NAME = 4; - private static final short AUTH_METHOD = 5; - private static final short EMAIL = 6; - private static final short FLASH_THEME = 7; - private static final short HTML_THEME = 8; - private static final short LOCALE = 9; - private static final short ADDRESS1 = 10; - private static final short ADDRESS2 = 11; - private static final short ADDRESS3 = 12; - private static final short CITY = 13; - private static final short STATE = 14; - private static final short POSTCODE = 15; - private static final short COUNTRY = 16; - private static final short DAY_PHONE = 17; - private static final short EVE_PHONE = 18; - private static final short MOB_PHONE = 19; - private static final short FAX = 20; - - // spreadsheet column indexes for userorgrole spreadsheet - private static final short ORGANISATION = 1; - private static final short ROLES = 2; - - // spreadsheet column indexes for groups spreadsheet - private static final short NAME = 0; - private static final short CODE = 1; - private static final short DESCRIPTION = 2; - private static final short LOCALE_ID = 3; - private static final short ORGANISATION_STATE = 4; - private static final short ADMIN_ADD_NEW_USERS = 5; - private static final short ADMIN_BROWSE_ALL_USERS = 6; - private static final short ADMIN_CHANGE_STATUS = 7; - - // class-wide variables - ArrayList results = new ArrayList(); - ArrayList rowResult = new ArrayList(); - private boolean emptyRow; - private boolean hasError; - private Organisation parentOrg; - private HSSFSheet getSheet(FormFile fileItem) throws IOException { - POIFSFileSystem fs = new POIFSFileSystem(fileItem.getInputStream()); - HSSFWorkbook wb = new HSSFWorkbook(fs); - return wb.getSheetAt(0); + String orgStateText = parseStringCell(row.getCell(ORGANISATION_STATE)); + OrganisationState orgState = getOrganisationState(orgStateText); + org.setOrganisationState(orgState); + + org.setOrganisationType((OrganisationType) service.findById(OrganisationType.class, + parentOrg.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.ROOT_TYPE) + ? OrganisationType.COURSE_TYPE : OrganisationType.CLASS_TYPE)); + + org.setParentOrganisation(parentOrg); + org.setCourseAdminCanAddNewUsers(parseBooleanCell(row.getCell(ADMIN_ADD_NEW_USERS))); + org.setCourseAdminCanBrowseAllUsers(parseBooleanCell(row.getCell(ADMIN_BROWSE_ALL_USERS))); + org.setCourseAdminCanChangeStatusOfCourse(parseBooleanCell(row.getCell(ADMIN_CHANGE_STATUS))); + + return (hasError ? null : org); + } + + private boolean isIntegratedUser(List integPrefixes, String login) { + int underscore = login.indexOf('_'); + if (underscore >= 0) { + if (integPrefixes.contains(login.substring(0, underscore))) { + return true; + } } - - public boolean isUserSpreadsheet(FormFile fileItem) throws IOException { - HSSFSheet sheet = getSheet(fileItem); - HSSFRow row = sheet.getRow(sheet.getFirstRowNum()); - String string = parseStringCell(row.getCell(PASSWORD)); - return (StringUtils.equals(string, "* password")) ? true : false; - } - - public boolean isRolesSpreadsheet(FormFile fileItem) throws IOException { - HSSFSheet sheet = getSheet(fileItem); - HSSFRow row = sheet.getRow(sheet.getFirstRowNum()); - String string = parseStringCell(row.getCell(ORGANISATION)); - return (StringUtils.equals(string, "* organisation")) ? true : false; - } - - public List parseSpreadsheet(FormFile fileItem, String sessionId) throws IOException { - if (isUserSpreadsheet(fileItem)) { - return parseUserSpreadsheet(fileItem, sessionId); - } else if (isRolesSpreadsheet(fileItem)) { - return parseRolesSpreadsheet(fileItem, sessionId); - } - 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. - public List parseGroupSpreadsheet(FormFile fileItem) throws IOException { - results = new ArrayList(); - parentOrg = service.getRootOrganisation(); - HSSFSheet sheet = getSheet(fileItem); - int startRow = sheet.getFirstRowNum(); - int endRow = sheet.getLastRowNum(); - - log.debug("Parsing spreadsheet rows "+startRow+" through "+endRow); - - HSSFRow row; - Organisation org = null; - int successful = 0; - for (int i = startRow + 1; i < endRow + 1; i++) { - emptyRow = true; - hasError = false; - rowResult = new ArrayList(); - row = sheet.getRow(i); - if (row != null) { - org = parseGroup(row, i); - } - - // an empty row signifies a new group - if (emptyRow) { - log.debug("Row "+i+" is empty."); - parentOrg = service.getRootOrganisation(); - continue; - } - if (hasError) { - log.debug("Row "+i+" has an error which has been sent to the browser."); - results.add(rowResult); - continue; - } else { - org = service.saveOrganisation(org, getCurrentUserId()); - successful++; - rowResult.add(org.getOrganisationId().toString()); - rowResult.add(org.getName()); - rowResult.add(org.getParentOrganisation().getOrganisationId().toString()); - rowResult.add(org.getOrganisationType().getOrganisationTypeId().toString()); - writeOrgAuditLog(org); - // if we just added a group, then the rows under it become it's subgroups - if (parentOrg.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.ROOT_TYPE)) { - parentOrg = org; - } - results.add(rowResult); - } - } - log.debug("Found "+results.size()+" orgs in spreadsheet."); - writeSuccessAuditLog(successful, null, "audit.successful.organisation.import"); - return results; - } - - private Integer getCurrentUserId() { + return false; + } + + public int getNumRows(FormFile fileItem) throws IOException { + HSSFSheet sheet = getSheet(fileItem); + int startRow = sheet.getFirstRowNum(); + int endRow = sheet.getLastRowNum(); + return endRow - startRow; + } + + public List parseUserSpreadsheet(FormFile fileItem, String sessionId) throws IOException { + results = new ArrayList(); + HSSFSheet sheet = getSheet(fileItem); + int startRow = sheet.getFirstRowNum(); + int endRow = sheet.getLastRowNum(); + + setupImportStatus(sessionId, endRow - startRow); + UserDTO userDTO = (UserDTO) SessionManager.getSession(sessionId).getAttribute(AttributeNames.USER); + + log.debug("Parsing spreadsheet rows " + startRow + " through " + endRow); + + HSSFRow row; + User user = null; + int successful = 0; + for (int i = startRow + 1; i < endRow + 1; i++) { + emptyRow = true; + hasError = false; + rowResult = new ArrayList(); + row = sheet.getRow(i); + user = parseUser(row, i); + + if (emptyRow) { + log.debug("Row " + i + " is empty."); + break; + } + if (hasError) { + 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()); + continue; + } else { try { - UserDTO user = (UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER); - return user.getUserID(); + service.save(user); + successful++; + writeAuditLog(user, userDTO); + log.debug("Row " + i + " saved user: " + user.getLogin()); } catch (Exception e) { - log.error(e); + log.debug(e); + rowResult.add(messageService.getMessage("error.fail.add")); } - return null; - } - - private Organisation parseGroup(HSSFRow row, int rowIndex) { - Organisation org = new Organisation(); - String[] args = new String[1]; - - String name = parseStringCell(row.getCell(NAME)); - - //validate organisation name - if (StringUtils.isBlank(name)) { - rowResult.add(messageService.getMessage("error.name.required")); - hasError = true; - return null; - - } else if (!ValidationUtil.isOrgNameValid(name)) { - rowResult.add(messageService.getMessage("error.name.invalid.characters")); - hasError = true; - return null; + if (rowResult.size() > 0) { + if (log.isDebugEnabled()) + log.debug("Row " + i + " has " + rowResult.size() + " messages."); + writeErrorsAuditLog(i + 1, rowResult, userDTO); } - - org.setName(name); - org.setCode(parseStringCell(row.getCell(CODE))); - org.setDescription(parseStringCell(row.getCell(DESCRIPTION))); - - String localeId = parseStringCell(row.getCell(LOCALE_ID)); - SupportedLocale locale = getLocale(localeId); - if (locale==null) { - args[0] = "("+localeId+")"; - rowResult.add(messageService.getMessage("error.locale.invalid", args)); - hasError = true; - } else { - org.setLocale(locale); - } - - String orgStateText = parseStringCell(row.getCell(ORGANISATION_STATE)); - OrganisationState orgState = getOrganisationState(orgStateText); - org.setOrganisationState(orgState); + results.add(rowResult); + updateImportStatus(sessionId, results.size()); + } + } + log.debug("Found " + results.size() + " users in spreadsheet."); + writeSuccessAuditLog(successful, userDTO, "audit.successful.user.import"); + return results; + } - org.setOrganisationType((OrganisationType)service.findById(OrganisationType.class, - parentOrg.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.ROOT_TYPE) - ? OrganisationType.COURSE_TYPE : OrganisationType.CLASS_TYPE)); + // use session vars to update browser with import progress so page + // won't timeout + private void setupImportStatus(String sessionId, int importTotal) { + HttpSession ss = SessionManager.getSession(sessionId); + ss.setAttribute(STATUS_IMPORT_TOTAL, importTotal); + ss.setAttribute(STATUS_IMPORTED, 0); + } - org.setParentOrganisation(parentOrg); - org.setCourseAdminCanAddNewUsers(parseBooleanCell(row.getCell(ADMIN_ADD_NEW_USERS))); - org.setCourseAdminCanBrowseAllUsers(parseBooleanCell(row.getCell(ADMIN_BROWSE_ALL_USERS))); - org.setCourseAdminCanChangeStatusOfCourse(parseBooleanCell(row.getCell(ADMIN_CHANGE_STATUS))); - - return (hasError ? null : org); - } - - private boolean isIntegratedUser(List integPrefixes, String login) { - int underscore = login.indexOf('_'); - if (underscore >= 0) { - if (integPrefixes.contains(login.substring(0, underscore))) { - return true; - } + private void updateImportStatus(String sessionId, int imported) { + HttpSession ss = SessionManager.getSession(sessionId); + ss.removeAttribute(STATUS_IMPORTED); + ss.setAttribute(STATUS_IMPORTED, imported); + } + + public List parseRolesSpreadsheet(FormFile fileItem, String sessionId) throws IOException { + results = new ArrayList(); + HSSFSheet sheet = getSheet(fileItem); + int startRow = sheet.getFirstRowNum(); + int endRow = sheet.getLastRowNum(); + + log.debug("Parsing spreadsheet rows " + startRow + " through " + endRow); + + setupImportStatus(sessionId, endRow - startRow); + UserDTO userDTO = (UserDTO) SessionManager.getSession(sessionId).getAttribute(AttributeNames.USER); + + HSSFRow row; + List roles; + int successful = 0; + for (int i = startRow + 1; i < endRow + 1; i++) { + emptyRow = true; + hasError = false; + rowResult = new ArrayList(); + row = sheet.getRow(i); + + String login = parseStringCell(row.getCell(LOGIN)); + String orgId = parseStringCell(row.getCell(ORGANISATION)); + roles = parseRolesCell(row.getCell(ROLES)); + + if (emptyRow) { + log.debug("Row " + i + " is empty."); + break; + } + if (hasError) { + 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()); + continue; + } else { + try { + saveUserRoles(isSysadmin(sessionId), login, orgId, roles, row); + successful++; + } catch (Exception e) { + log.error("Unable to assign roles to user: " + login, e); + rowResult.add(messageService.getMessage("error.fail.add")); } - return false; - } - - public int getNumRows(FormFile fileItem) throws IOException { - HSSFSheet sheet = getSheet(fileItem); - int startRow = sheet.getFirstRowNum(); - int endRow = sheet.getLastRowNum(); - return endRow - startRow; - } - - public List parseUserSpreadsheet(FormFile fileItem, String sessionId) throws IOException { - results = new ArrayList(); - HSSFSheet sheet = getSheet(fileItem); - int startRow = sheet.getFirstRowNum(); - int endRow = sheet.getLastRowNum(); - - setupImportStatus(sessionId, endRow-startRow); - UserDTO userDTO = (UserDTO)SessionManager.getSession(sessionId).getAttribute(AttributeNames.USER); - - log.debug("Parsing spreadsheet rows "+startRow+" through "+endRow); - - HSSFRow row; - User user = null; - int successful = 0; - for (int i = startRow + 1; i < endRow + 1; i++) { - emptyRow = true; - hasError = false; - rowResult = new ArrayList(); - row = sheet.getRow(i); - user = parseUser(row, i); - - if (emptyRow) { - log.debug("Row "+i+" is empty."); - break; - } - if (hasError) { - 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()); - continue; - } else { - try { - service.save(user); - successful++; - writeAuditLog(user, userDTO); - log.debug("Row "+i+" saved user: "+user.getLogin()); - } catch (Exception e) { - log.debug(e); - rowResult.add(messageService.getMessage("error.fail.add")); - } - if (rowResult.size() > 0) { - if (log.isDebugEnabled()) log.debug("Row "+i+" has "+rowResult.size() + " messages."); - writeErrorsAuditLog(i+1, rowResult, userDTO); - } - results.add(rowResult); - updateImportStatus(sessionId, results.size()); - } + if (rowResult.size() > 0) { + if (log.isDebugEnabled()) + log.debug("Row " + i + " has " + rowResult.size() + " messages."); + writeErrorsAuditLog(i + 1, rowResult, userDTO); } - log.debug("Found "+results.size()+" users in spreadsheet."); - writeSuccessAuditLog(successful, userDTO, "audit.successful.user.import"); - return results; + results.add(rowResult); + updateImportStatus(sessionId, results.size()); + } } - - // use session vars to update browser with import progress so page - // won't timeout - private void setupImportStatus(String sessionId, int importTotal) { - HttpSession ss = SessionManager.getSession(sessionId); - ss.setAttribute(STATUS_IMPORT_TOTAL, importTotal); - ss.setAttribute(STATUS_IMPORTED, 0); + log.debug("Found " + results.size() + " users in spreadsheet."); + writeSuccessAuditLog(successful, userDTO, "audit.successful.role.import"); + return results; + } + + private void setError(String message, String arg) { + if (StringUtils.isBlank(arg)) { + rowResult.add(messageService.getMessage(message)); + } else { + String[] args = new String[1]; + args[0] = arg; + rowResult.add(messageService.getMessage(message, args)); } - - private void updateImportStatus(String sessionId, int imported) { - HttpSession ss = SessionManager.getSession(sessionId); - ss.removeAttribute(STATUS_IMPORTED); - ss.setAttribute(STATUS_IMPORTED, imported); + hasError = true; + } + + // used when importing in a separate thread that doesn't have the user's DTO in session + private boolean isSysadmin(String sessionId) { + UserDTO userDTO = (UserDTO) SessionManager.getSession(sessionId).getAttribute(AttributeNames.USER); + return service.isUserInRole(userDTO.getUserID(), service.getRootOrganisation().getOrganisationId(), + Role.SYSADMIN); + } + + /* + * user must already exist + */ + private void saveUserRoles(boolean isSysadmin, String login, String orgId, List roles, HSSFRow row) { + User user = null; + if (StringUtils.isNotBlank(login)) { + user = service.getUserByLogin(login); + } else if (StringUtils.isBlank(login)) { + setError("error.login.required", ""); } - - public List parseRolesSpreadsheet(FormFile fileItem, String sessionId) throws IOException { - results = new ArrayList(); - HSSFSheet sheet = getSheet(fileItem); - int startRow = sheet.getFirstRowNum(); - int endRow = sheet.getLastRowNum(); - - log.debug("Parsing spreadsheet rows "+startRow+" through "+endRow); - - setupImportStatus(sessionId, endRow-startRow); - UserDTO userDTO = (UserDTO)SessionManager.getSession(sessionId).getAttribute(AttributeNames.USER); - - HSSFRow row; - List roles; - int successful = 0; - for (int i = startRow + 1; i < endRow + 1; i++) { - emptyRow = true; - hasError = false; - rowResult = new ArrayList(); - row = sheet.getRow(i); - - String login = parseStringCell(row.getCell(LOGIN)); - String orgId = parseStringCell(row.getCell(ORGANISATION)); - roles = parseRolesCell(row.getCell(ROLES)); - - if (emptyRow) { - log.debug("Row "+i+" is empty."); - break; - } - if (hasError) { - 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()); - continue; - } else { - try { - saveUserRoles(isSysadmin(sessionId), login, orgId, roles, row); - successful++; - } catch (Exception e) { - log.error("Unable to assign roles to user: "+login, e); - rowResult.add(messageService.getMessage("error.fail.add")); - } - if (rowResult.size() > 0) { - if (log.isDebugEnabled()) log.debug("Row "+i+" has "+rowResult.size() + " messages."); - writeErrorsAuditLog(i+1, rowResult, userDTO); - } - results.add(rowResult); - updateImportStatus(sessionId, results.size()); - } - } - log.debug("Found "+results.size()+" users in spreadsheet."); - writeSuccessAuditLog(successful, userDTO, "audit.successful.role.import"); - return results; + if (user == null) { + setError("error.user.does.not.exist", "(" + login + ")"); } - - private void setError(String message, String arg) { - if (StringUtils.isBlank(arg)) { - rowResult.add(messageService.getMessage(message)); - } else { - String[] args = new String[1]; - args[0] = arg; - rowResult.add(messageService.getMessage(message, args)); - } - hasError = true; + + Organisation org = null; + if (StringUtils.isNotBlank(orgId)) { + org = (Organisation) service.findById(Organisation.class, new Integer(orgId)); } - - // used when importing in a separate thread that doesn't have the user's DTO in session - private boolean isSysadmin(String sessionId) { - UserDTO userDTO = (UserDTO)SessionManager.getSession(sessionId).getAttribute(AttributeNames.USER); - return service.isUserInRole(userDTO.getUserID(), service.getRootOrganisation().getOrganisationId(), Role.SYSADMIN); + if (StringUtils.isBlank(orgId) || org == null) { + setError("error.org.invalid", "(" + orgId + ")"); + } else { + if (roles == null || !checkValidRoles(roles, isSysadmin, org.getOrganisationType())) { + setError("error.roles.invalid", "(" + parseStringCell(row.getCell(ROLES)) + ")"); + } } - - /* - * user must already exist - */ - private void saveUserRoles(boolean isSysadmin, String login, String orgId, List roles, HSSFRow row) { - User user = null; - if (StringUtils.isNotBlank(login)) { - user = service.getUserByLogin(login); - } else if (StringUtils.isBlank(login)) { - setError("error.login.required", ""); - } - if (user==null) { - setError("error.user.does.not.exist", "("+login+")"); - } - - Organisation org = null; - if (StringUtils.isNotBlank(orgId)) { - org = (Organisation)service.findById(Organisation.class, new Integer(orgId)); - } - if (StringUtils.isBlank(orgId) || org==null){ - setError("error.org.invalid", "("+orgId+")"); - } else { - if (roles==null || !checkValidRoles(roles, isSysadmin, org.getOrganisationType())) { - setError("error.roles.invalid", "("+parseStringCell(row.getCell(ROLES))+")"); - } - } - - if (!hasError) { - service.setRolesForUserOrganisation(user, org.getOrganisationId(), roles); - if (log.isDebugEnabled()) { - log.debug("added: "+login+" to: "+org.getName()+" with roles: "+roles); - } - } + + if (!hasError) { + service.setRolesForUserOrganisation(user, org.getOrganisationId(), roles); + if (log.isDebugEnabled()) { + log.debug("added: " + login + " to: " + org.getName() + " with roles: " + roles); + } } - + } + /* * gathers error messages for each cell as required, unless it's the login field in which case, flags whole row as * empty. @@ -493,12 +496,12 @@ rowResult.add(messageService.getMessage("error.login.required")); hasError = true; return null; - + } else if (!ValidationUtil.isUserNameValid(login)) { rowResult.add(messageService.getMessage("error.username.invalid.characters")); hasError = true; return null; - + } else if (service.getUserByLogin(login) != null) { args[0] = "(" + login + ")"; rowResult.add(messageService.getMessage("error.login.unique", args)); @@ -507,13 +510,15 @@ } user.setLogin(login); - String password = HashUtil.sha1(parseStringCell(row.getCell(PASSWORD))); + String password = parseStringCell(row.getCell(PASSWORD)); // password validation if (StringUtils.isBlank(password)) { rowResult.add(messageService.getMessage("error.password.required")); hasError = true; return null; } + String salt = HashUtil.salt(); + password = HashUtil.sha256(password, salt); user.setPassword(password); user.setTitle(parseStringCell(row.getCell(TITLE))); @@ -523,11 +528,11 @@ if (StringUtils.isBlank(firstName)) { rowResult.add(messageService.getMessage("error.firstname.required")); hasError = true; - + } else if (!ValidationUtil.isFirstLastNameValid(firstName)) { rowResult.add(messageService.getMessage("error.firstname.invalid.characters")); - hasError = true; - + hasError = true; + } else { user.setFirstName(firstName); } @@ -537,11 +542,11 @@ if (StringUtils.isBlank(lastName)) { rowResult.add(messageService.getMessage("error.lastname.required")); hasError = true; - + } else if (!ValidationUtil.isFirstLastNameValid(lastName)) { rowResult.add(messageService.getMessage("error.lastname.invalid.characters")); hasError = true; - + } else { user.setLastName(lastName); } @@ -553,7 +558,7 @@ args[0] = "(" + authMethodName + ")"; rowResult.add(messageService.getMessage("error.authmethod.invalid", args)); hasError = true; - + } else { user.setAuthenticationMethod(authMethod); } @@ -563,11 +568,11 @@ if (StringUtils.isBlank(email)) { rowResult.add(messageService.getMessage("error.email.required")); hasError = true; - + } else if (!ValidationUtil.isEmailValid(email)) { rowResult.add(messageService.getMessage("error.valid.email.required")); hasError = true; - + } else { user.setEmail(email); } @@ -621,237 +626,236 @@ return (hasError ? null : user); } - - /* - * the methods below return legible data from individual cells - */ - private boolean parseBooleanCell(HSSFCell cell){ - if (cell!=null) { - String value; - try { - cell.setCellType(HSSFCell.CELL_TYPE_STRING); - if (cell.getStringCellValue()!= null) { - if (cell.getStringCellValue().trim().length()!= 0) { - emptyRow = false; - } - } else { - return false; - } - value = cell.getStringCellValue().trim(); - } catch(Exception e) { - cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); - double d = cell.getNumericCellValue(); - emptyRow = false; - value = new Long(new Double(d).longValue()).toString(); - } - if (StringUtils.equals(value, "1") || StringUtils.equalsIgnoreCase(value, "true")) { - return true; - } - } - return false; - } - - private String parseStringCell(HSSFCell cell){ - if (cell!=null) { - try { - cell.setCellType(HSSFCell.CELL_TYPE_STRING); - if (cell.getStringCellValue()!= null) { - if (cell.getStringCellValue().trim().length()!= 0) { - emptyRow = false; - } - } else { - return null; - } - // log.debug("string cell value: '"+cell.getStringCellValue().trim()+"'"); - return cell.getStringCellValue().trim(); - } catch(Exception e) { - cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); - double d = cell.getNumericCellValue(); - emptyRow = false; - // log.debug("numeric cell value: '"+d+"'"); - return (new Long(new Double(d).longValue()).toString()); - } - } - return null; - } - - private AuthenticationMethod getAuthMethod(String authMethodName){ - List list; - if (authMethodName==null || authMethodName=="") { - return (AuthenticationMethod)service.findById(AuthenticationMethod.class, AuthenticationMethod.DB); + + /* + * the methods below return legible data from individual cells + */ + private boolean parseBooleanCell(HSSFCell cell) { + if (cell != null) { + String value; + try { + cell.setCellType(HSSFCell.CELL_TYPE_STRING); + if (cell.getStringCellValue() != null) { + if (cell.getStringCellValue().trim().length() != 0) { + emptyRow = false; + } } else { - try { - Integer authMethodId = new Integer(authMethodName); - return (AuthenticationMethod)service.findById(AuthenticationMethod.class, authMethodId); - } catch (NumberFormatException e) { - list = service.findByProperty(AuthenticationMethod.class, "authenticationMethodName", authMethodName); - return ( list==null || list.isEmpty() ? null : (AuthenticationMethod)list.get(0)); - } + return false; } + value = cell.getStringCellValue().trim(); + } catch (Exception e) { + cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); + double d = cell.getNumericCellValue(); + emptyRow = false; + value = new Long(new Double(d).longValue()).toString(); + } + if (StringUtils.equals(value, "1") || StringUtils.equalsIgnoreCase(value, "true")) { + return true; + } } - - private List parseRolesCell(HSSFCell cell) - { - String roleDescription = ""; - if (cell!=null) { - try { - cell.setCellType(HSSFCell.CELL_TYPE_STRING); - if (cell.getStringCellValue()!= null || cell.getStringCellValue().trim().length()!= 0) { - emptyRow = false; - } else { - log.debug("Couldn't find any roles in spreadsheet column index " + ROLES); - return null; - } - roleDescription = cell.getStringCellValue().trim(); - } catch(Exception e) { - log.error("Caught exception when reading roles in spreadsheet: " + e.getMessage()); - return null; - } - List roles = new ArrayList(); - int fromIndex = 0; - int index = roleDescription.indexOf(SEPARATOR, fromIndex); - while (index != -1) { - String role = addRoleId(roleDescription, fromIndex, index); - log.debug("Found role: "+role); - if (role==null) { - return null; - } else { - roles.add(role); - } - fromIndex = index + 1; - index = roleDescription.indexOf(SEPARATOR, fromIndex); - } - String role = addRoleId(roleDescription, fromIndex, roleDescription.length()); - log.debug("Found last role: "+role); - if (role==null) { - return null; - } else { - roles.add(role); - } - return roles; - } - return null; - } - - // return id of role name in given role description - private String addRoleId(String roleDescription, int fromIndex, int index) { - List list = service.findByProperty(Role.class, "name", roleDescription.substring(fromIndex, index)); - Role role = (list==null || list.isEmpty() ? null : (Role)list.get(0)); - if (role!=null) { - return role.getRoleId().toString(); + return false; + } + + private String parseStringCell(HSSFCell cell) { + if (cell != null) { + try { + cell.setCellType(HSSFCell.CELL_TYPE_STRING); + if (cell.getStringCellValue() != null) { + if (cell.getStringCellValue().trim().length() != 0) { + emptyRow = false; + } } else { - return null; // if we can't translate the name to a role, return null + return null; } + // log.debug("string cell value: '"+cell.getStringCellValue().trim()+"'"); + return cell.getStringCellValue().trim(); + } catch (Exception e) { + cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); + double d = cell.getNumericCellValue(); + emptyRow = false; + // log.debug("numeric cell value: '"+d+"'"); + return (new Long(new Double(d).longValue()).toString()); + } } - - // return false if a role shouldn't be assigned in given org type - private boolean checkValidRoles(List idList, boolean isSysadmin, OrganisationType orgType) { - // convert list of id's into list of Roles - List roleList = new ArrayList(); - for (String id : idList) { - Role role = (Role)service.findById(Role.class, Integer.parseInt(id)); - if (role!=null) { - roleList.add(role); - } else { - return false; - } - } - - // check they are valid - List validRoles = service.filterRoles(roleList, isSysadmin, orgType); - for (Role r : roleList) { - if (!validRoles.contains(r)) { - return false; - } - } - return true; + return null; + } + + private AuthenticationMethod getAuthMethod(String authMethodName) { + List list; + if (authMethodName == null || authMethodName == "") { + return (AuthenticationMethod) service.findById(AuthenticationMethod.class, AuthenticationMethod.DB); + } else { + try { + Integer authMethodId = new Integer(authMethodName); + return (AuthenticationMethod) service.findById(AuthenticationMethod.class, authMethodId); + } catch (NumberFormatException e) { + list = service.findByProperty(AuthenticationMethod.class, "authenticationMethodName", authMethodName); + return (list == null || list.isEmpty() ? null : (AuthenticationMethod) list.get(0)); + } } + } - // set Theme to default flash theme if cell is empty - private Theme getFlashTheme(String flashId){ - if (flashId==null || flashId=="") { - return service.getDefaultFlashTheme(); + private List parseRolesCell(HSSFCell cell) { + String roleDescription = ""; + if (cell != null) { + try { + cell.setCellType(HSSFCell.CELL_TYPE_STRING); + if (cell.getStringCellValue() != null || cell.getStringCellValue().trim().length() != 0) { + emptyRow = false; } else { - try { - return (Theme)service.findById(Theme.class, new Long(flashId)); - } catch (Exception e) { - return null; - } + log.debug("Couldn't find any roles in spreadsheet column index " + ROLES); + return null; } - } - - // set Theme to default html theme if cell is empty - private Theme getHtmlTheme(String htmlId){ - if (htmlId==null || htmlId=="") { - return service.getDefaultHtmlTheme(); + roleDescription = cell.getStringCellValue().trim(); + } catch (Exception e) { + log.error("Caught exception when reading roles in spreadsheet: " + e.getMessage()); + return null; + } + List roles = new ArrayList(); + int fromIndex = 0; + int index = roleDescription.indexOf(SEPARATOR, fromIndex); + while (index != -1) { + String role = addRoleId(roleDescription, fromIndex, index); + log.debug("Found role: " + role); + if (role == null) { + return null; } else { - try { - return (Theme)service.findById(Theme.class, new Long(htmlId)); - } catch (Exception e) { - return null; - } + roles.add(role); } + fromIndex = index + 1; + index = roleDescription.indexOf(SEPARATOR, fromIndex); + } + String role = addRoleId(roleDescription, fromIndex, roleDescription.length()); + log.debug("Found last role: " + role); + if (role == null) { + return null; + } else { + roles.add(role); + } + return roles; } - - // set locale to default system locale if cell is empty - private SupportedLocale getLocale(String localeId){ - if (localeId==null || localeId=="") { - return LanguageUtil.getDefaultLocale(); - } else { - try { - return (SupportedLocale)service.findById(SupportedLocale.class, new Integer(localeId)); - } catch (Exception e) { - return null; - } - } + return null; + } + + // return id of role name in given role description + private String addRoleId(String roleDescription, int fromIndex, int index) { + List list = service.findByProperty(Role.class, "name", roleDescription.substring(fromIndex, index)); + Role role = (list == null || list.isEmpty() ? null : (Role) list.get(0)); + if (role != null) { + return role.getRoleId().toString(); + } else { + return null; // if we can't translate the name to a role, return null } - - // set organisation state to active if cell is empty - private OrganisationState getOrganisationState(String orgStateText) { - if (StringUtils.equals(orgStateText, "hidden")) { - return (OrganisationState)service.findById(OrganisationState.class, OrganisationState.HIDDEN); - } else if (StringUtils.equals(orgStateText, "archived")) { - return (OrganisationState)service.findById(OrganisationState.class, OrganisationState.ARCHIVED); - } else { - return (OrganisationState)service.findById(OrganisationState.class, OrganisationState.ACTIVE); - } + } + + // return false if a role shouldn't be assigned in given org type + private boolean checkValidRoles(List idList, boolean isSysadmin, OrganisationType orgType) { + // convert list of id's into list of Roles + List roleList = new ArrayList(); + for (String id : idList) { + Role role = (Role) service.findById(Role.class, Integer.parseInt(id)); + if (role != null) { + roleList.add(role); + } else { + return false; + } } - - private void writeAuditLog(User user, UserDTO userDTO) { - String[] args = new String[2]; - args[0] = user.getLogin()+"("+user.getUserId()+")"; - args[1] = user.getFullName(); - String message = messageService.getMessage("audit.user.create", args); - auditService.log(userDTO, AdminConstants.MODULE_NAME, message); + + // check they are valid + List validRoles = service.filterRoles(roleList, isSysadmin, orgType); + for (Role r : roleList) { + if (!validRoles.contains(r)) { + return false; + } } - - private void writeOrgAuditLog(Organisation org) { - String[] args = new String[2]; - args[0] = org.getName()+"("+org.getOrganisationId()+")"; - args[1] = org.getOrganisationType().getName(); - String message = messageService.getMessage("audit.organisation.create", args); - auditService.log(AdminConstants.MODULE_NAME, message); + return true; + } + + // set Theme to default flash theme if cell is empty + private Theme getFlashTheme(String flashId) { + if (flashId == null || flashId == "") { + return service.getDefaultFlashTheme(); + } else { + try { + return (Theme) service.findById(Theme.class, new Long(flashId)); + } catch (Exception e) { + return null; + } } - - private void writeErrorsAuditLog(int row, List list, UserDTO userDTO) { - for (String s : list) { - writeErrorAuditLog(row, s, userDTO); - } + } + + // set Theme to default html theme if cell is empty + private Theme getHtmlTheme(String htmlId) { + if (htmlId == null || htmlId == "") { + return service.getDefaultHtmlTheme(); + } else { + try { + return (Theme) service.findById(Theme.class, new Long(htmlId)); + } catch (Exception e) { + return null; + } } - - private void writeErrorAuditLog(int row, String error, UserDTO userDTO) { - String[] args = { Integer.toString(row), error }; - String message = messageService.getMessage("audit.spreadsheet.error", args); - auditService.log(userDTO, AdminConstants.MODULE_NAME, message); + } + + // set locale to default system locale if cell is empty + private SupportedLocale getLocale(String localeId) { + if (localeId == null || localeId == "") { + return LanguageUtil.getDefaultLocale(); + } else { + try { + return (SupportedLocale) service.findById(SupportedLocale.class, new Integer(localeId)); + } catch (Exception e) { + return null; + } } - - private void writeSuccessAuditLog(int successful, UserDTO userDTO, String key) { - String[] args = { Integer.toString(successful) }; - String message = messageService.getMessage(key, args); - if (userDTO == null) { - auditService.log(AdminConstants.MODULE_NAME, message); - } else { - auditService.log(userDTO, AdminConstants.MODULE_NAME, message); - } + } + + // set organisation state to active if cell is empty + private OrganisationState getOrganisationState(String orgStateText) { + if (StringUtils.equals(orgStateText, "hidden")) { + return (OrganisationState) service.findById(OrganisationState.class, OrganisationState.HIDDEN); + } else if (StringUtils.equals(orgStateText, "archived")) { + return (OrganisationState) service.findById(OrganisationState.class, OrganisationState.ARCHIVED); + } else { + return (OrganisationState) service.findById(OrganisationState.class, OrganisationState.ACTIVE); } + } + + private void writeAuditLog(User user, UserDTO userDTO) { + String[] args = new String[2]; + args[0] = user.getLogin() + "(" + user.getUserId() + ")"; + args[1] = user.getFullName(); + String message = messageService.getMessage("audit.user.create", args); + auditService.log(userDTO, AdminConstants.MODULE_NAME, message); + } + + private void writeOrgAuditLog(Organisation org) { + String[] args = new String[2]; + args[0] = org.getName() + "(" + org.getOrganisationId() + ")"; + args[1] = org.getOrganisationType().getName(); + String message = messageService.getMessage("audit.organisation.create", args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + + private void writeErrorsAuditLog(int row, List list, UserDTO userDTO) { + for (String s : list) { + writeErrorAuditLog(row, s, userDTO); + } + } + + private void writeErrorAuditLog(int row, String error, UserDTO userDTO) { + String[] args = { Integer.toString(row), error }; + String message = messageService.getMessage("audit.spreadsheet.error", args); + auditService.log(userDTO, AdminConstants.MODULE_NAME, message); + } + + private void writeSuccessAuditLog(int successful, UserDTO userDTO, String key) { + String[] args = { Integer.toString(successful) }; + String message = messageService.getMessage(key, args); + if (userDTO == null) { + auditService.log(AdminConstants.MODULE_NAME, message); + } else { + auditService.log(userDTO, AdminConstants.MODULE_NAME, message); + } + } } Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserSaveAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserSaveAction.java,v diff -u -r1.39 -r1.39.2.1 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserSaveAction.java 9 Apr 2014 18:40:36 -0000 1.39 +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserSaveAction.java 21 Oct 2015 11:44:57 -0000 1.39.2.1 @@ -25,8 +25,6 @@ package org.lamsfoundation.lams.admin.web; import java.util.Date; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -43,7 +41,6 @@ import org.apache.struts.action.DynaActionForm; import org.lamsfoundation.lams.admin.AdminConstants; import org.lamsfoundation.lams.admin.service.AdminServiceProxy; -import org.lamsfoundation.lams.integration.UserInfoValidationException; import org.lamsfoundation.lams.themes.Theme; import org.lamsfoundation.lams.usermanagement.AuthenticationMethod; import org.lamsfoundation.lams.usermanagement.SupportedLocale; @@ -90,8 +87,8 @@ Boolean passwordChanged = true; SupportedLocale locale = (SupportedLocale) UserSaveAction.service.findById(SupportedLocale.class, (Integer) userForm.get("localeId")); - AuthenticationMethod authenticationMethod = (AuthenticationMethod) UserSaveAction.service.findById( - AuthenticationMethod.class, (Integer) userForm.get("authenticationMethodId")); + AuthenticationMethod authenticationMethod = (AuthenticationMethod) UserSaveAction.service + .findById(AuthenticationMethod.class, (Integer) userForm.get("authenticationMethodId")); UserSaveAction.log.debug("locale: " + locale); UserSaveAction.log.debug("authenticationMethod:" + authenticationMethod); @@ -122,9 +119,8 @@ if ((user != null) && StringUtils.equals(user.getLogin(), login)) { // login exists - it's the user's current login } else { - errors.add("login", - new ActionMessage("error.login.unique", "(" + login + ", ID: " + existingUser.getUserId() - + ")")); + errors.add("login", new ActionMessage("error.login.unique", + "(" + login + ", ID: " + existingUser.getUserId() + ")")); } } } @@ -140,23 +136,23 @@ errors.add("password", new ActionMessage("error.password.required")); } } - + //first name validation String firstName = (userForm.get("firstName") == null) ? null : (String) userForm.get("firstName"); if (StringUtils.isBlank(firstName)) { errors.add("firstName", new ActionMessage("error.firstname.required")); } else if (!ValidationUtil.isFirstLastNameValid(firstName)) { errors.add("firstName", new ActionMessage("error.firstname.invalid.characters")); } - + //last name validation String lastName = (userForm.get("lastName") == null) ? null : (String) userForm.get("lastName"); if (StringUtils.isBlank(lastName)) { errors.add("lastName", new ActionMessage("error.lastname.required")); } else if (!ValidationUtil.isFirstLastNameValid(lastName)) { errors.add("lastName", new ActionMessage("error.lastname.invalid.characters")); } - + //user email validation String userEmail = (userForm.get("email") == null) ? null : (String) userForm.get("email"); if (StringUtils.isBlank(userEmail)) { @@ -171,7 +167,10 @@ // hash the new password if necessary, and audit the fact if (passwordChanged) { UserSaveAction.service.auditPasswordChanged(user, AdminConstants.MODULE_NAME); - userForm.set("password", HashUtil.sha1((String) userForm.get("password"))); + String salt = HashUtil.salt(); + String passwordHash = HashUtil.sha256((String) userForm.get("password"), salt); + userForm.set("salt", salt); + userForm.set("password", passwordHash); } else { userForm.set("password", user.getPassword()); } @@ -190,7 +189,10 @@ UserSaveAction.service.save(user); } else { // create user user = new User(); - userForm.set("password", HashUtil.sha1((String) userForm.get("password"))); + String salt = HashUtil.salt(); + String passwordHash = HashUtil.sha256((String) userForm.get("password"), salt); + userForm.set("salt", salt); + userForm.set("password", passwordHash); BeanUtils.copyProperties(user, userForm); UserSaveAction.log.debug("creating user... new login: " + user.getLogin()); if (errors.isEmpty()) { @@ -200,8 +202,9 @@ user.setHtmlTheme(UserSaveAction.service.getDefaultHtmlTheme()); user.setDisabledFlag(false); user.setCreateDate(new Date()); - user.setAuthenticationMethod((AuthenticationMethod) UserSaveAction.service.findByProperty( - AuthenticationMethod.class, "authenticationMethodName", "LAMS-Database").get(0)); + user.setAuthenticationMethod((AuthenticationMethod) UserSaveAction.service + .findByProperty(AuthenticationMethod.class, "authenticationMethodName", "LAMS-Database") + .get(0)); user.setUserId(null); user.setLocale(locale); Index: lams_build/lib/lams/lams-central.jar =================================================================== RCS file: /usr/local/cvsroot/lams_build/lib/lams/lams-central.jar,v diff -u -r1.81.2.9 -r1.81.2.10 Binary files differ Index: lams_build/lib/lams/lams.jar =================================================================== RCS file: /usr/local/cvsroot/lams_build/lib/lams/lams.jar,v diff -u -r1.420.2.35 -r1.420.2.36 Binary files differ Index: lams_central/src/java/org/lamsfoundation/lams/security/DatabaseAuthenticator.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/security/DatabaseAuthenticator.java,v diff -u -r1.6.14.1 -r1.6.14.2 --- lams_central/src/java/org/lamsfoundation/lams/security/DatabaseAuthenticator.java 19 Oct 2015 12:20:13 -0000 1.6.14.1 +++ lams_central/src/java/org/lamsfoundation/lams/security/DatabaseAuthenticator.java 21 Oct 2015 11:44:56 -0000 1.6.14.2 @@ -32,78 +32,130 @@ import javax.naming.NamingException; import javax.sql.DataSource; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.lamsfoundation.lams.util.HashUtil; /** * Validates user password against an entry in the LAMS database. */ public class DatabaseAuthenticator { private static Logger log = Logger.getLogger(DatabaseAuthenticator.class); - private String dsJndiName; - private static final String PRINCIPAL_QUERY = "SELECT password FROM lams_user WHERE login=?"; + private static DataSource dataSource; - public DatabaseAuthenticator(String dsJndiName) { - this.dsJndiName = dsJndiName; - } + private static final String GET_PASSWORD_QUERY = "SELECT password FROM lams_user WHERE login=?"; + private static final String GET_SALT_QUERY = "SELECT salt FROM lams_user WHERE login=?"; + private static final String UPDATE_PASSWORD_QUERY = "UPDATE lams_user SET password=?, salt=? WHERE login=?"; - public boolean authenticate(String username, String inputPassword) { - if ((inputPassword == null) || (inputPassword.trim().length() == 0)) { - return false; + public DatabaseAuthenticator(String dsJndiName) throws NamingException { + if (DatabaseAuthenticator.dataSource == null) { + InitialContext ctx = new InitialContext(); + DatabaseAuthenticator.dataSource = (DataSource) ctx.lookup(dsJndiName); } + } - boolean isValid = false; + public boolean authenticate(String userName, String inputPassword) { + try (Connection conn = DatabaseAuthenticator.dataSource.getConnection()) { + String databasePassword = DatabaseAuthenticator.getDatabasePassword(conn, userName); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - - String databasePassword = null; - try { - InitialContext ctx = new InitialContext(); - DataSource ds = (DataSource) ctx.lookup(dsJndiName); - conn = ds.getConnection(); - // Get the password - ps = conn.prepareStatement(PRINCIPAL_QUERY); - ps.setString(1, username); - rs = ps.executeQuery(); - if (rs.next() == false) { - isValid = false; + // password should never be blank in the DB (?) + if (StringUtils.isBlank(databasePassword)) { + DatabaseAuthenticator.log.warn("Password in database is blank for user: " + userName); + return false; } - - databasePassword = rs.getString(1); - if (inputPassword.equals(databasePassword.trim())) { - isValid = true; + // is it still SHA1 password? + if (databasePassword.length() == HashUtil.SHA1_HEX_LENGTH) { + String inputPasswordHash = HashUtil.sha1(inputPassword); + if (inputPasswordHash.equals(databasePassword)) { + // update the password with SHA256 + salt + return DatabaseAuthenticator.convertPasswordToSha256(conn, userName, inputPassword); + } + return false; } + // is it already SHA256 password + if (databasePassword.length() == HashUtil.SHA256_HEX_LENGTH) { + String salt = DatabaseAuthenticator.getDatabaseSalt(conn, userName); + if (StringUtils.isBlank(salt) || (salt.length() != HashUtil.SALT_HEX_LENGTH)) { + DatabaseAuthenticator.log.error("Salt does not have correct format for user: " + userName); + return false; + } + String inputPasswordHash = HashUtil.sha256(inputPassword, salt); + + return inputPasswordHash.equals(databasePassword); + } - } catch (NamingException e) { - DatabaseAuthenticator.log.error(e); + DatabaseAuthenticator.log.error("Password in database does not have correct format for user: " + userName); } catch (SQLException e) { DatabaseAuthenticator.log.error(e); + } + + return false; + } + + /** + * Fetches user password from the database. + */ + private static String getDatabasePassword(Connection conn, String userName) throws SQLException { + ResultSet resultSet = null; + + try (PreparedStatement preparedStatement = conn.prepareStatement(DatabaseAuthenticator.GET_PASSWORD_QUERY)) { + preparedStatement.setString(1, userName); + resultSet = preparedStatement.executeQuery(); + return resultSet.next() ? resultSet.getString(1).trim() : null; } finally { - if (rs != null) { + if (resultSet != null) { try { - rs.close(); + resultSet.close(); } catch (SQLException e) { DatabaseAuthenticator.log.error(e); } } - if (ps != null) { + } + } + + private static String getDatabaseSalt(Connection conn, String userName) throws SQLException { + ResultSet resultSet = null; + + try (PreparedStatement preparedStatement = conn.prepareStatement(DatabaseAuthenticator.GET_SALT_QUERY)) { + preparedStatement.setString(1, userName); + resultSet = preparedStatement.executeQuery(); + return resultSet.next() ? resultSet.getString(1).trim() : null; + } finally { + if (resultSet != null) { try { - ps.close(); + resultSet.close(); } catch (SQLException e) { DatabaseAuthenticator.log.error(e); } } - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - DatabaseAuthenticator.log.error(e); - } + } + } + + /** + * Updates the user password with sha256 hash with salt. + */ + private static boolean convertPasswordToSha256(Connection conn, String userName, String inputPassword) + throws SQLException { + if (DatabaseAuthenticator.log.isDebugEnabled()) { + DatabaseAuthenticator.log.debug("Converting password to SHA256 for user: " + userName); + } + String salt = HashUtil.salt(); + String inputPasswordHash = HashUtil.sha256(inputPassword, salt); + + try (PreparedStatement preparedStatement = conn.prepareStatement(DatabaseAuthenticator.UPDATE_PASSWORD_QUERY)) { + preparedStatement.setString(1, inputPasswordHash); + preparedStatement.setString(2, salt); + preparedStatement.setString(3, userName); + int result = preparedStatement.executeUpdate(); + if (result == 1) { + return true; + } else { + DatabaseAuthenticator.log.error("Error while converting password to SHA256 for user: " + userName + + ". The update query returned result: " + result); } } - return isValid; + return false; } } \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java,v diff -u -r1.29.2.9 -r1.29.2.10 --- lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java 19 Oct 2015 12:20:12 -0000 1.29.2.9 +++ lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java 21 Oct 2015 11:44:56 -0000 1.29.2.10 @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import javax.naming.InitialContext; import javax.naming.NamingException; @@ -48,6 +49,7 @@ import javax.security.auth.spi.LoginModule; import javax.sql.DataSource; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.themes.Theme; import org.lamsfoundation.lams.themes.dto.CSSThemeBriefDTO; @@ -60,7 +62,6 @@ import org.lamsfoundation.lams.usermanagement.service.LdapService; import org.lamsfoundation.lams.util.Configuration; import org.lamsfoundation.lams.util.ConfigurationKeys; -import org.lamsfoundation.lams.util.HashUtil; import org.lamsfoundation.lams.web.session.SessionManager; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; @@ -82,11 +83,15 @@ private boolean loginOK; private Principal identity; private char[] credential; - private String dsJndiName; + private static String dsJndiName; + private static final Map internalAuthenticationTokens = new TreeMap(); + + private static DatabaseAuthenticator databaseAuthenticator; private static IThemeService themeService; private static IUserManagementService userManagementService; + private static final long INTERNAL_AUTHENTICATION_TIMEOUT = 10 * 1000; private static final String ROLES_QUERY = "SELECT DISTINCT r.name,'Roles' FROM lams_user u " + "LEFT OUTER JOIN lams_user_organisation uo USING(user_id) " + "LEFT OUTER JOIN lams_user_organisation_role urr USING(user_organisation_id) " @@ -195,7 +200,7 @@ if (!validatePassword(password)) { if (UniversalLoginModule.log.isDebugEnabled()) { - UniversalLoginModule.log.debug("Bad password for user " + userName); + UniversalLoginModule.log.debug("Bad password for user: " + userName); } throw new FailedLoginException("Incorrect password"); } @@ -254,7 +259,9 @@ this.subject = subject; this.callbackHandler = callbackHandler; - dsJndiName = (String) options.get("dsJndiName"); + if (UniversalLoginModule.dsJndiName == null) { + UniversalLoginModule.dsJndiName = (String) options.get("dsJndiName"); + } } private boolean validatePassword(String inputPassword) { @@ -271,18 +278,21 @@ return true; } + String userName = getUserName(); + // empty password not allowed - if ((inputPassword == null) || (inputPassword.length() == 0)) { - return false; + if (StringUtils.isBlank(inputPassword)) { + // check for internal authentication made by LoginRequestServlet or LoginAsAction + Long internalAuthenticationTime = UniversalLoginModule.internalAuthenticationTokens.get(userName); + UniversalLoginModule.internalAuthenticationTokens.remove(userName); + // internal authentication is valid for 10 seconds + return (internalAuthenticationTime != null) && ((System.currentTimeMillis() + - internalAuthenticationTime) < UniversalLoginModule.INTERNAL_AUTHENTICATION_TIMEOUT); } boolean isValid = false; try { - String userName = getUserName(); - if (UniversalLoginModule.log.isDebugEnabled()) { - UniversalLoginModule.log.debug("Authenticating user " + userName + "."); - } User user = UniversalLoginModule.userManagementService.getUserByLogin(userName); @@ -331,25 +341,18 @@ // perform password checking according to user's authentication method if (!isValid) { String type = user.getAuthenticationMethod().getAuthenticationMethodType().getDescription(); - UniversalLoginModule.log.debug("Authentication type: " + type); if (AuthenticationMethodType.LDAP.equals(type)) { LDAPAuthenticator authenticator = new LDAPAuthenticator(UniversalLoginModule.userManagementService); isValid = authenticator.authenticate(userName, inputPassword); // if LDAP user profile has updated, udpate user object for dto below user = UniversalLoginModule.userManagementService.getUserByLogin(userName); - } else if (AuthenticationMethodType.LAMS.equals(type)) { - DatabaseAuthenticator authenticator = new DatabaseAuthenticator(dsJndiName); - isValid = authenticator.authenticate(userName, inputPassword); - // if the password is not encrypted when sent from the - // jsp (e.g. when it is passed - // unencrypted to say, ldap) then encrypt it here when - // authenticating against local db - if (!isValid && !Configuration.getAsBoolean(ConfigurationKeys.LDAP_ENCRYPT_PASSWORD_FROM_BROWSER)) { - inputPassword = HashUtil.sha1(inputPassword); - isValid = authenticator.authenticate(userName, inputPassword); + // check password in LAMS DB + if (UniversalLoginModule.databaseAuthenticator == null) { + UniversalLoginModule.databaseAuthenticator = new DatabaseAuthenticator( + UniversalLoginModule.dsJndiName); } - + isValid = UniversalLoginModule.databaseAuthenticator.authenticate(userName, inputPassword); } else { UniversalLoginModule.log.error("Unexpected authentication type: " + type); return false; @@ -426,7 +429,7 @@ try { InitialContext ctx = new InitialContext(); - DataSource ds = (DataSource) ctx.lookup(this.dsJndiName); + DataSource ds = (DataSource) ctx.lookup(UniversalLoginModule.dsJndiName); conn = ds.getConnection(); // Get the user role names @@ -508,4 +511,11 @@ setsMap.values().toArray(roleSets); return roleSets; } + + /** + * Allows other LAMS modules to confirm user authentication before WildFly proper authentication commences. + */ + public static void setAuthenticationToken(String userName) { + UniversalLoginModule.internalAuthenticationTokens.put(userName, System.currentTimeMillis()); + } } \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/web/LoginAsAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/LoginAsAction.java,v diff -u -r1.3.14.3 -r1.3.14.4 --- lams_central/src/java/org/lamsfoundation/lams/web/LoginAsAction.java 25 Nov 2014 08:43:56 -0000 1.3.14.3 +++ lams_central/src/java/org/lamsfoundation/lams/web/LoginAsAction.java 21 Oct 2015 11:44:56 -0000 1.3.14.4 @@ -30,6 +30,7 @@ import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.security.UniversalLoginModule; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; @@ -73,7 +74,8 @@ // login.jsp knows what to do with these request.setAttribute("login", login); - request.setAttribute("password", user.getPassword()); + // notify the login module that the user has been authenticated correctly + UniversalLoginModule.setAuthenticationToken(login); // redirect to login page return (new ActionForward("/login.jsp?redirectURL=/lams/index.jsp")); } Index: lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java,v diff -u -r1.21.2.9 -r1.21.2.10 --- lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java 5 Aug 2015 17:46:47 -0000 1.21.2.9 +++ lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java 21 Oct 2015 11:44:56 -0000 1.21.2.10 @@ -38,6 +38,7 @@ import org.lamsfoundation.lams.integration.security.Authenticator; import org.lamsfoundation.lams.integration.service.IntegrationService; import org.lamsfoundation.lams.integration.util.LoginRequestDispatcher; +import org.lamsfoundation.lams.security.UniversalLoginModule; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.CentralConstants; @@ -101,8 +102,8 @@ // LDEV-2196 preserve character encoding if necessary if (request.getCharacterEncoding() == null) { - LoginRequestServlet.log - .debug("request.getCharacterEncoding is empty, parsing username and courseName as 8859_1 to UTF-8..."); + LoginRequestServlet.log.debug( + "request.getCharacterEncoding is empty, parsing username and courseName as 8859_1 to UTF-8..."); extUsername = new String(extUsername.getBytes("8859_1"), "UTF-8"); if (courseName != null) { courseName = new String(courseName.getBytes("8859_1"), "UTF-8"); @@ -123,15 +124,15 @@ //in case of request for learner with strict authentication check cache should also contain lsid String lsId = null; if (LoginRequestDispatcher.METHOD_LEARNER_STRICT_AUTHENTICATION.equals(method)) { - + lsId = request.getParameter(LoginRequestDispatcher.PARAM_LESSON_ID); if (lsId == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Login Failed - lsId parameter missing"); return; } } Authenticator.authenticateLoginRequest(serverMap, timestamp, extUsername, method, lsId, hash); - + if (extCourseId != null) { // check if organisation, ExtCourseClassMap and user roles exist and up-to-date, and if not update them getService().getExtCourseClassMap(serverMap, userMap, extCourseId, countryIsoCode, langIsoCode, @@ -157,12 +158,14 @@ // login.jsp knows what to do with these hses.setAttribute("login", login); - hses.setAttribute("password", user.getPassword()); + // notify the login module that the user has been authenticated correctly + UniversalLoginModule.setAuthenticationToken(login); response.sendRedirect("login.jsp?redirectURL=" + redirectURL); } catch (AuthenticationException e) { LoginRequestServlet.log.error("Authentication error: ", e); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Login Failed - authentication error. " + e.getMessage()); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, + "Login Failed - authentication error. " + e.getMessage()); } catch (UserInfoFetchException e) { LoginRequestServlet.log.error("User fetch info error: ", e); response.sendError(HttpServletResponse.SC_BAD_GATEWAY, Index: lams_central/src/java/org/lamsfoundation/lams/web/PasswordChangeAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/PasswordChangeAction.java,v diff -u -r1.14 -r1.14.2.1 --- lams_central/src/java/org/lamsfoundation/lams/web/PasswordChangeAction.java 30 Oct 2009 00:41:17 -0000 1.14 +++ lams_central/src/java/org/lamsfoundation/lams/web/PasswordChangeAction.java 21 Oct 2015 11:44:56 -0000 1.14.2.1 @@ -67,6 +67,7 @@ * The HTTP response we are creating * */ + @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // -- isCancelled? @@ -88,31 +89,35 @@ String password = passwordChangeForm.getPassword(); String passwordConfirm = passwordChangeForm.getPasswordConfirm(); - if (loggedInUser == null || !loggedInUser.equals(login)) { + if ((loggedInUser == null) || !loggedInUser.equals(login)) { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.authorisation")); } else { // WebApplicationContext ctx = // WebApplicationContextUtils.getWebApplicationContext(request.getSession(true).getServletContext()); - WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServlet() - .getServletContext()); + WebApplicationContext ctx = WebApplicationContextUtils + .getWebApplicationContext(getServlet().getServletContext()); UserManagementService service = (UserManagementService) ctx.getBean("userManagementService"); User user = service.getUserByLogin(login); - if (!user.getPassword().equals(HashUtil.sha1(oldPassword))) { + String passwordHash = user.getPassword().length() == HashUtil.SHA1_HEX_LENGTH + ? HashUtil.sha1(oldPassword) : HashUtil.sha256(oldPassword, user.getSalt()); + + if (!user.getPassword().equals(passwordHash)) { errors.add("oldPassword", new ActionMessage("error.oldpassword.mismatch")); - log.debug("old pass wrong"); + PasswordChangeAction.log.debug("old pass wrong"); } if (!password.equals(passwordConfirm)) { errors.add("password", new ActionMessage("error.newpassword.mismatch")); - log.debug("new pass wrong"); + PasswordChangeAction.log.debug("new pass wrong"); } - if (password == null || password.length() == 0) { + if ((password == null) || (password.length() == 0)) { errors.add("password", new ActionMessage("error.password.empty")); - log.debug("new password cannot be empty"); + PasswordChangeAction.log.debug("new password cannot be empty"); } if (errors.isEmpty()) { - // service.updatePassword(login, HashUtil.sha1(password)); - user.setPassword(HashUtil.sha1(password)); + String salt = HashUtil.salt(); + user.setSalt(salt); + user.setPassword(HashUtil.sha256(password, salt)); user.setChangePassword(false); service.save(user); @@ -127,7 +132,7 @@ } } catch (Exception e) { - log.error("Exception occured ", e); + PasswordChangeAction.log.error("Exception occured ", e); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(e.getMessage())); } Index: lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java,v diff -u -r1.6.2.1 -r1.6.2.2 --- lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java 8 Dec 2014 13:37:56 -0000 1.6.2.1 +++ lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java 21 Oct 2015 11:44:56 -0000 1.6.2.2 @@ -28,8 +28,7 @@ import org.springframework.web.context.support.WebApplicationContextUtils; /** - * @struts:action path="/signup/signup" name="SignupForm" scope="request" - * validate="false" parameter="method" + * @struts:action path="/signup/signup" name="SignupForm" scope="request" validate="false" parameter="method" * * @struts:action-forward name="signup" path=".signup" * @struts:action-forward name="index" path="/" @@ -41,32 +40,33 @@ private static Logger log = Logger.getLogger(SignupAction.class); private static ISignupService signupService = null; - + + @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { - if (signupService == null) { - WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() - .getServletContext()); - signupService = (ISignupService) wac.getBean("signupService"); + if (SignupAction.signupService == null) { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + SignupAction.signupService = (ISignupService) wac.getBean("signupService"); } DynaActionForm signupForm = (DynaActionForm) form; String method = WebUtil.readStrParam(request, "method", true); - if (signupForm.get("submitted") == null || !((Boolean) signupForm.get("submitted"))) { + if ((signupForm.get("submitted") == null) || !((Boolean) signupForm.get("submitted"))) { String context = WebUtil.readStrParam(request, "context", true); SignupOrganisation signupOrganisation = null; if (StringUtils.isNotBlank(context)) { - signupOrganisation = signupService.getSignupOrganisation(context); + signupOrganisation = SignupAction.signupService.getSignupOrganisation(context); request.setAttribute("signupOrganisation", signupOrganisation); } if (signupOrganisation == null) { request.setAttribute("messageKey", "No such signup page exists"); return mapping.findForward("message"); } - + // no context and unsubmitted form means it's the initial request return mapping.findForward("signup"); } else if (StringUtils.equals(method, "register")) { @@ -75,7 +75,7 @@ return signIn(mapping, form, request, response); } } - + private ActionForward signUp(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { @@ -95,8 +95,10 @@ user.setFirstName(signupForm.getString("firstName")); user.setLastName(signupForm.getString("lastName")); user.setEmail(signupForm.getString("email")); - user.setPassword(HashUtil.sha1(signupForm.getString("password"))); - signupService.signupUser(user, signupForm.getString("context")); + String salt = HashUtil.salt(); + user.setSalt(salt); + user.setPassword(HashUtil.sha256(signupForm.getString("password"), salt)); + SignupAction.signupService.signupUser(user, signupForm.getString("context")); // send email try { @@ -113,20 +115,20 @@ Emailer.sendFromSupportEmail(subject, user.getEmail(), body, isHtmlFormat); } catch (Exception e) { - log.error(e.getMessage(), e); + SignupAction.log.error(e.getMessage(), e); request.setAttribute("error", e.getMessage()); } return mapping.findForward("success"); } } catch (Exception e) { - log.error(e.getMessage(), e); + SignupAction.log.error(e.getMessage(), e); request.setAttribute("error", e.getMessage()); } return mapping.findForward("index"); } - + private ActionForward signIn(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { @@ -140,23 +142,24 @@ return mapping.findForward("signup"); } else { String login = signupForm.getString("usernameTab2"); - String password = HashUtil.sha1(signupForm.getString("passwordTab2")); + String password = signupForm.getString("passwordTab2"); String context = signupForm.getString("context"); - signupService.signinUser(login, context); + SignupAction.signupService.signinUser(login, context); String redirectUrl = Configuration.get(ConfigurationKeys.SERVER_URL); - + //check if user is logged in already - if (SessionManager.getSession() == null || SessionManager.getSession().getAttribute(AttributeNames.USER) == null) { + if ((SessionManager.getSession() == null) + || (SessionManager.getSession().getAttribute(AttributeNames.USER) == null)) { redirectUrl += "/j_security_check?" + Constants.FORM_USERNAME + "=" + login + "&" - + Constants.FORM_PASSWORD + "=" + password; + + Constants.FORM_PASSWORD + "=" + password; } - + response.sendRedirect(redirectUrl); return null; } } catch (Exception e) { - log.error(e.getMessage(), e); + SignupAction.log.error(e.getMessage(), e); request.setAttribute("error", e.getMessage()); } @@ -165,15 +168,15 @@ private ActionMessages validateSignup(DynaActionForm signupForm) { ActionMessages errors = new ActionMessages(); - + // user name validation String userName = (signupForm.get("username") == null) ? null : (String) signupForm.get("username"); if (StringUtils.isBlank(userName)) { errors.add("username", new ActionMessage("error.username.blank")); } else if (!ValidationUtil.isUserNameValid(userName)) { errors.add("username", new ActionMessage("error.username.invalid.characters")); - log.info("username has invalid characters: "+ userName); - } else if (signupService.usernameExists(userName)) { + SignupAction.log.info("username has invalid characters: " + userName); + } else if (SignupAction.signupService.usernameExists(userName)) { errors.add("username", new ActionMessage("error.username.exists")); } @@ -183,16 +186,16 @@ errors.add("firstName", new ActionMessage("error.first.name.blank")); } else if (!ValidationUtil.isFirstLastNameValid(firstName)) { errors.add("firstName", new ActionMessage("error.firstname.invalid.characters")); - log.info("firstname has invalid characters: "+ firstName); + SignupAction.log.info("firstname has invalid characters: " + firstName); } - + //last name validation String lastName = (signupForm.get("lastName") == null) ? null : (String) signupForm.get("lastName"); if (StringUtils.isBlank(lastName)) { errors.add("lastName", new ActionMessage("error.last.name.blank")); } else if (!ValidationUtil.isFirstLastNameValid(lastName)) { errors.add("lastName", new ActionMessage("error.lastname.invalid.characters")); - log.info("lastName has invalid characters: "+ lastName); + SignupAction.log.info("lastName has invalid characters: " + lastName); } //password validation @@ -201,7 +204,7 @@ } else if (!StringUtils.equals(signupForm.getString("password"), signupForm.getString("confirmPassword"))) { errors.add("password", new ActionMessage("error.passwords.unequal")); } - + //user email validation String userEmail = (signupForm.get("email") == null) ? null : (String) signupForm.get("email"); if (StringUtils.isBlank(userEmail)) { @@ -211,15 +214,15 @@ } else if (!StringUtils.equals(userEmail, signupForm.getString("confirmEmail"))) { errors.add("email", new ActionMessage("error.emails.unequal")); } - + // courseKey validation - if (!signupService.courseKeyIsValid(signupForm.getString("context"), + if (!SignupAction.signupService.courseKeyIsValid(signupForm.getString("context"), signupForm.getString("courseKey"))) { errors.add("courseKey", new ActionMessage("error.course.key.invalid")); } return errors; } - + private ActionMessages validateSignin(DynaActionForm signupForm) { ActionMessages errors = new ActionMessages(); if (StringUtils.isBlank(signupForm.getString("usernameTab2"))) { @@ -228,21 +231,24 @@ if (StringUtils.isBlank(signupForm.getString("passwordTab2"))) { errors.add("passwordTab2", new ActionMessage("error.password.blank")); } - if (!signupService.courseKeyIsValid(signupForm.getString("context"), + if (!SignupAction.signupService.courseKeyIsValid(signupForm.getString("context"), signupForm.getString("courseKeyTab2"))) { errors.add("courseKeyTab2", new ActionMessage("error.course.key.invalid")); } - + if (errors.isEmpty()) { String login = signupForm.getString("usernameTab2"); - String password = HashUtil.sha1(signupForm.getString("passwordTab2")); - User user = signupService.getUserByLogin(login); - - if ((user == null) || !user.getPassword().equals(password)) { - errors.add("usernameTab2", new ActionMessage("error.login.or.password.incorrect", "", "")); + String password = signupForm.getString("passwordTab2"); + User user = SignupAction.signupService.getUserByLogin(login); + String passwordHash = user.getPassword().length() == HashUtil.SHA1_HEX_LENGTH ? HashUtil.sha1(password) + : HashUtil.sha256(password, user.getSalt()); + + if ((user == null) || !user.getPassword().equals(passwordHash)) { + errors.add("usernameTab2", new ActionMessage("error.login.or.password.incorrect", + "", "")); } } - + return errors; } } Index: lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterAction.java,v diff -u -r1.9 -r1.9.2.1 --- lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterAction.java 4 Jul 2013 11:35:28 -0000 1.9 +++ lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterAction.java 21 Oct 2015 11:44:56 -0000 1.9.2.1 @@ -103,8 +103,8 @@ private static MessageService messageService = null; - public synchronized void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, - IOException { + public synchronized void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { String method = request.getParameter(CentralConstants.PARAM_METHOD); if (method.equals("addUserToGroupLessons")) { @@ -126,37 +126,37 @@ * if an error occured */ public void init() throws ServletException { - learnerProgressDAO = (ILearnerProgressDAO) WebApplicationContextUtils.getRequiredWebApplicationContext( - getServletContext()).getBean("learnerProgressDAO"); + learnerProgressDAO = (ILearnerProgressDAO) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServletContext()).getBean("learnerProgressDAO"); - integrationService = (IntegrationService) WebApplicationContextUtils.getRequiredWebApplicationContext( - getServletContext()).getBean("integrationService"); + integrationService = (IntegrationService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServletContext()).getBean("integrationService"); - lessonService = (ILessonService) WebApplicationContextUtils.getRequiredWebApplicationContext( - getServletContext()).getBean("lessonService"); + lessonService = (ILessonService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServletContext()).getBean("lessonService"); - learnerService = (ICoreLearnerService) WebApplicationContextUtils.getRequiredWebApplicationContext( - getServletContext()).getBean("learnerService"); + learnerService = (ICoreLearnerService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServletContext()).getBean("learnerService"); groupUserDAO = (IGroupUserDAO) WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()) .getBean("groupUserDAO"); - userManagementService = (IUserManagementService) WebApplicationContextUtils.getRequiredWebApplicationContext( - getServletContext()).getBean("userManagementService"); + userManagementService = (IUserManagementService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServletContext()).getBean("userManagementService"); eventNotificationService = (IEventNotificationService) WebApplicationContextUtils .getRequiredWebApplicationContext(getServletContext()).getBean("eventNotificationService"); - messageService = (MessageService) WebApplicationContextUtils.getRequiredWebApplicationContext( - getServletContext()).getBean(CentralConstants.CENTRAL_MESSAGE_SERVICE_BEAN_NAME); + messageService = (MessageService) WebApplicationContextUtils + .getRequiredWebApplicationContext(getServletContext()) + .getBean(CentralConstants.CENTRAL_MESSAGE_SERVICE_BEAN_NAME); } /** * Add user to group lessons. * - * External server call must follow the next format: - * http://<>/lams/central/Register.do?method=addUserToGroupLessons - * &serverId=%serverId%&datetime=%datetime% + * External server call must follow the next format: http://< + * >/lams/central/Register.do?method=addUserToGroupLessons &serverId=%serverId%&datetime=%datetime% * &hashValue=%hashValue%&courseId=%courseId%&username=%username%&firstName= * %firstName%&lastName=%lastName%&email=%email&isJoinLesson=%isJoinLesson% * &isEmailParticipant=%isEmailParticipant%&isEmailCoordinator=%isEmailCoordinator% @@ -231,7 +231,8 @@ // create new password String password = RandomPasswordGenerator.nextPassword(8); - String hashedPassword = HashUtil.sha1(password); + String salt = HashUtil.salt(); + String passwordHash = HashUtil.sha256(password, salt); // check whether we need to use a prefix for users if ("1".equals(usePrefix)) { @@ -241,7 +242,7 @@ // get user from the DB if exists, create it otherwise ExtUserUseridMap userMap = integrationService.getImplicitExtUserUseridMap(extServer, username, - hashedPassword, firstName, lastName, email); + passwordHash, salt, firstName, lastName, email); User user = userMap.getUser(); HashSet lessonsToJoin = new HashSet(); @@ -273,8 +274,8 @@ for (Lesson lesson : lessonsToJoin) { boolean isAdded = lessonService.addLearner(lesson.getLessonId(), user.getUserId()); if (isAdded) { - logger.debug("Added user:" + user.getLogin() + " to lesson:" + lesson.getLessonName() - + " as a learner"); + logger.debug( + "Added user:" + user.getLogin() + " to lesson:" + lesson.getLessonName() + " as a learner"); } } @@ -285,8 +286,8 @@ LearnerProgress learnerProgress = learnerProgressDAO.getLearnerProgressByLearner(user.getUserId(), lesson.getLessonId()); if (learnerProgress == null) { - logger.debug("The learner:" + user.getLogin() + " is joining the lesson:" - + lesson.getLessonId()); + logger.debug( + "The learner:" + user.getLogin() + " is joining the lesson:" + lesson.getLessonId()); learnerService.joinLesson(user.getUserId(), lesson.getLessonId()); } else {// don't join to lessons which user is a part of already but make sure time limit is reset resetUserTimeLimit(lesson, user); @@ -317,10 +318,11 @@ String registeredUserName = firstName + " " + lastName + " (" + username + ")"; eventNotificationService.sendMessage(null, coordinator.getUserId(), - IEventNotificationService.DELIVERY_METHOD_MAIL, messageService - .getMessage("notify.coordinator.register.user.email.subject"), messageService - .getMessage("notify.coordinator.register.user.email.body", - new Object[] { registeredUserName }), isHtmlFormat); + IEventNotificationService.DELIVERY_METHOD_MAIL, + messageService.getMessage("notify.coordinator.register.user.email.subject"), + messageService.getMessage("notify.coordinator.register.user.email.body", + new Object[] { registeredUserName }), + isHtmlFormat); } writeAJAXOKResponse(response); @@ -334,9 +336,8 @@ /** * Remove user from group lessons. * - * External server call must follow the next format: - * http://<>/lams/central/Register.do?method=removeUserFromGroup - * &serverId=%serverId%&datetime=%datetime% + * External server call must follow the next format: http://< + * >/lams/central/Register.do?method=removeUserFromGroup &serverId=%serverId%&datetime=%datetime% * &hashValue=%hashValue%&courseId=%courseId%&username=%username%&isRemoveFromAllCourses=%isRemoveFromAllCourses% * * Here are the parameters explanation: @@ -436,9 +437,9 @@ * Resets user's time limit for all lessons in a group with scheduledToCloseForIndividuals setting on. In case * lesson's time limit is not individual it does nothing. * - * External server call must follow the next format: - * http://<>/lams/central/Register.do?method=resetUserTimeLimit - * &serverId=%serverId%&datetime=%datetime% &hashValue=%hashValue%&courseId=%courseId%&username=%username% + * External server call must follow the next format: http://< + * >/lams/central/Register.do?method=resetUserTimeLimit &serverId=%serverId%&datetime=%datetime% + * &hashValue=%hashValue%&courseId=%courseId%&username=%username% * * Here are the parameters explanation: * Index: lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterServiceSoapBindingImpl.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterServiceSoapBindingImpl.java,v diff -u -r1.18 -r1.18.2.1 --- lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterServiceSoapBindingImpl.java 9 Apr 2014 15:54:14 -0000 1.18 +++ lams_central/src/java/org/lamsfoundation/lams/webservice/RegisterServiceSoapBindingImpl.java 21 Oct 2015 11:44:56 -0000 1.18.2.1 @@ -76,31 +76,36 @@ private static IUserManagementService service = (IUserManagementService) WebApplicationContextUtils .getRequiredWebApplicationContext( - ((HttpServlet) context.getProperty(HTTPConstants.MC_HTTP_SERVLET)).getServletContext()).getBean( - "userManagementService"); + ((HttpServlet) RegisterServiceSoapBindingImpl.context.getProperty(HTTPConstants.MC_HTTP_SERVLET)) + .getServletContext()) + .getBean("userManagementService"); private static ILessonService lessonService = (ILessonService) WebApplicationContextUtils .getRequiredWebApplicationContext( - ((HttpServlet) context.getProperty(HTTPConstants.MC_HTTP_SERVLET)).getServletContext()).getBean( - "lessonService"); + ((HttpServlet) RegisterServiceSoapBindingImpl.context.getProperty(HTTPConstants.MC_HTTP_SERVLET)) + .getServletContext()) + .getBean("lessonService"); private static IIntegrationService integrationService = (IIntegrationService) WebApplicationContextUtils .getRequiredWebApplicationContext( - ((HttpServlet) context.getProperty(HTTPConstants.MC_HTTP_SERVLET)).getServletContext()).getBean( - "integrationService"); + ((HttpServlet) RegisterServiceSoapBindingImpl.context.getProperty(HTTPConstants.MC_HTTP_SERVLET)) + .getServletContext()) + .getBean("integrationService"); /** * Creates a user account in LAMS with the given username. */ + @Override public boolean createUser(String username, String password, String firstName, String lastName, String email, String serverId, String datetime, String hash) throws java.rmi.RemoteException { try { - ExtServerOrgMap extServer = integrationService.getExtServerOrgMap(serverId); + ExtServerOrgMap extServer = RegisterServiceSoapBindingImpl.integrationService.getExtServerOrgMap(serverId); Authenticator.authenticate(extServer, datetime, hash); - if (service.getUserByLogin(username) != null) + if (RegisterServiceSoapBindingImpl.service.getUserByLogin(username) != null) { return false; - ExtUserUseridMap userMap = integrationService.getImplicitExtUserUseridMap(extServer, username, password, - firstName, lastName, email); + } + ExtUserUseridMap userMap = RegisterServiceSoapBindingImpl.integrationService + .getImplicitExtUserUseridMap(extServer, username, password, null, firstName, lastName, email); return true; } catch (Exception e) { log.debug(e.getMessage(), e); @@ -111,6 +116,7 @@ /** * Create a new group with the given name. */ + @Override public int createOrganisation(String name, String code, String description, String owner, String serverId, String datetime, String hash) throws java.rmi.RemoteException { try { @@ -120,20 +126,20 @@ + "organisation name cannot contain any of these characters < > ^ * @ % $. External serverId:" + serverId + ", orgName:" + name); } - + Organisation org = new Organisation(); org.setName(name); org.setCode(code); org.setDescription(description); - org.setParentOrganisation(service.getRootOrganisation()); - org.setOrganisationType((OrganisationType) service.findById(OrganisationType.class, - OrganisationType.COURSE_TYPE)); - org.setOrganisationState((OrganisationState) service.findById(OrganisationState.class, - OrganisationState.ACTIVE)); + org.setParentOrganisation(RegisterServiceSoapBindingImpl.service.getRootOrganisation()); + org.setOrganisationType((OrganisationType) RegisterServiceSoapBindingImpl.service + .findById(OrganisationType.class, OrganisationType.COURSE_TYPE)); + org.setOrganisationState((OrganisationState) RegisterServiceSoapBindingImpl.service + .findById(OrganisationState.class, OrganisationState.ACTIVE)); SupportedLocale locale = LanguageUtil.getDefaultLocale(); org.setLocale(locale); - User user = service.getUserByLogin(owner); - service.saveOrganisation(org, user.getUserId()); + User user = RegisterServiceSoapBindingImpl.service.getUserByLogin(owner); + RegisterServiceSoapBindingImpl.service.saveOrganisation(org, user.getUserId()); return org.getOrganisationId(); } catch (Exception e) { log.debug(e.getMessage(), e); @@ -145,42 +151,46 @@ * Add the given username to the given group or subgroup. User and group/subgroup must exist. If asStaff is true, * user is given Learner, Author, and Monitor roles; otherwise only Learner. */ + @Override public boolean addUserToOrganisation(String login, Integer organisationId, Boolean asStaff, String serverId, String datetime, String hash) throws java.rmi.RemoteException { try { // authenticate external server - ExtServerOrgMap serverMap = integrationService.getExtServerOrgMap(serverId); + ExtServerOrgMap serverMap = RegisterServiceSoapBindingImpl.integrationService.getExtServerOrgMap(serverId); Authenticator.authenticate(serverMap, datetime, hash); // get user and organisation - User user = service.getUserByLogin(login); - Organisation org = (Organisation) service.findById(Organisation.class, organisationId); + User user = RegisterServiceSoapBindingImpl.service.getUserByLogin(login); + Organisation org = (Organisation) RegisterServiceSoapBindingImpl.service.findById(Organisation.class, + organisationId); - if (user == null || org == null) { + if ((user == null) || (org == null)) { return false; } // check user is not already in org - UserOrganisation uo = service.getUserOrganisation(user.getUserId(), org.getOrganisationId()); + UserOrganisation uo = RegisterServiceSoapBindingImpl.service.getUserOrganisation(user.getUserId(), + org.getOrganisationId()); if (uo == null) { // create UserOrganisation uo = new UserOrganisation(user, org); - service.save(uo); + RegisterServiceSoapBindingImpl.service.save(uo); Integer[] roles; if (asStaff) { roles = new Integer[] { Role.ROLE_AUTHOR, Role.ROLE_MONITOR, Role.ROLE_LEARNER }; } else { roles = new Integer[] { Role.ROLE_LEARNER }; } for (Integer roleId : roles) { - UserOrganisationRole uor = new UserOrganisationRole(uo, (Role) service.findById(Role.class, roleId)); - service.save(uor); + UserOrganisationRole uor = new UserOrganisationRole(uo, + (Role) RegisterServiceSoapBindingImpl.service.findById(Role.class, roleId)); + RegisterServiceSoapBindingImpl.service.save(uor); uo.addUserOrganisationRole(uor); } user.addUserOrganisation(uo); - service.save(user); + RegisterServiceSoapBindingImpl.service.save(user); return true; @@ -209,21 +219,24 @@ * createUser method. *

*/ + @Override public boolean addUserToGroup(String username, String serverId, String datetime, String hash, String courseId, String courseName, String countryIsoCode, String langIsoCode, Boolean isTeacher) - throws java.rmi.RemoteException { + throws java.rmi.RemoteException { try { // authenticate external server - ExtServerOrgMap serverMap = integrationService.getExtServerOrgMap(serverId); + ExtServerOrgMap serverMap = RegisterServiceSoapBindingImpl.integrationService.getExtServerOrgMap(serverId); Authenticator.authenticate(serverMap, datetime, hash); // get user map, creating if necessary - ExtUserUseridMap userMap = integrationService.getExtUserUseridMap(serverMap, username); + ExtUserUseridMap userMap = RegisterServiceSoapBindingImpl.integrationService.getExtUserUseridMap(serverMap, + username); // add user to org, creating org if necessary - ExtCourseClassMap orgMap = integrationService.getExtCourseClassMap(serverMap, userMap, courseId, - courseName, countryIsoCode, langIsoCode, service.getRootOrganisation().getOrganisationId() - .toString(), isTeacher, false); + ExtCourseClassMap orgMap = RegisterServiceSoapBindingImpl.integrationService.getExtCourseClassMap(serverMap, + userMap, courseId, courseName, countryIsoCode, langIsoCode, + RegisterServiceSoapBindingImpl.service.getRootOrganisation().getOrganisationId().toString(), + isTeacher, false); return true; } catch (Exception e) { log.debug(e.getMessage(), e); @@ -234,24 +247,28 @@ /** * Same as addUserToGroup, except adds user to the given aubgroup (and creates it if it doesn't exist). */ + @Override public boolean addUserToSubgroup(String username, String serverId, String datetime, String hash, String courseId, String courseName, String countryIsoCode, String langIsoCode, String subgroupId, String subgroupName, Boolean isTeacher) throws java.rmi.RemoteException { try { // authenticate external server - ExtServerOrgMap serverMap = integrationService.getExtServerOrgMap(serverId); + ExtServerOrgMap serverMap = RegisterServiceSoapBindingImpl.integrationService.getExtServerOrgMap(serverId); Authenticator.authenticate(serverMap, datetime, hash); // get group to use for this request - ExtUserUseridMap userMap = integrationService.getExtUserUseridMap(serverMap, username); - ExtCourseClassMap orgMap = integrationService.getExtCourseClassMap(serverMap, userMap, courseId, - courseName, countryIsoCode, langIsoCode, service.getRootOrganisation().getOrganisationId() - .toString(), isTeacher, false); + ExtUserUseridMap userMap = RegisterServiceSoapBindingImpl.integrationService.getExtUserUseridMap(serverMap, + username); + ExtCourseClassMap orgMap = RegisterServiceSoapBindingImpl.integrationService.getExtCourseClassMap(serverMap, + userMap, courseId, courseName, countryIsoCode, langIsoCode, + RegisterServiceSoapBindingImpl.service.getRootOrganisation().getOrganisationId().toString(), + isTeacher, false); Organisation group = orgMap.getOrganisation(); // add user to subgroup, creating subgroup if necessary - ExtCourseClassMap subOrgMap = integrationService.getExtCourseClassMap(serverMap, userMap, subgroupId, - subgroupName, countryIsoCode, langIsoCode, group.getOrganisationId().toString(), isTeacher, false); + ExtCourseClassMap subOrgMap = RegisterServiceSoapBindingImpl.integrationService.getExtCourseClassMap( + serverMap, userMap, subgroupId, subgroupName, countryIsoCode, langIsoCode, + group.getOrganisationId().toString(), isTeacher, false); return true; } catch (Exception e) { log.debug(e.getMessage(), e); @@ -261,33 +278,34 @@ /** *

- * Adds given username as learner or monitor (as specified by asStaff parameter) to all lessons in - * given LAMS group. + * Adds given username as learner or monitor (as specified by asStaff parameter) to all lessons in given LAMS group. *

* *

- * The LAMS group is identified by the external courseId parameter. If the courseId doesn't exist in the - * lams_ext_course_class_map table, then a new LAMS group is created. If it does exist, the group name is - * updated. + * The LAMS group is identified by the external courseId parameter. If the courseId doesn't exist in the + * lams_ext_course_class_map table, then a new LAMS group is created. If it does exist, the group name is updated. *

*/ + @Override public boolean addUserToGroupLessons(String username, String serverId, String datetime, String hash, String courseId, String courseName, String countryIsoCode, String langIsoCode, Boolean asStaff) - throws java.rmi.RemoteException { + throws java.rmi.RemoteException { try { // authenticate external server - ExtServerOrgMap serverMap = integrationService.getExtServerOrgMap(serverId); + ExtServerOrgMap serverMap = RegisterServiceSoapBindingImpl.integrationService.getExtServerOrgMap(serverId); Authenticator.authenticate(serverMap, datetime, hash); // get group to use for this request - ExtUserUseridMap userMap = integrationService.getExtUserUseridMap(serverMap, username); - ExtCourseClassMap orgMap = integrationService.getExtCourseClassMap(serverMap, userMap, courseId, - courseName, countryIsoCode, langIsoCode, service.getRootOrganisation().getOrganisationId() - .toString(), asStaff, false); + ExtUserUseridMap userMap = RegisterServiceSoapBindingImpl.integrationService.getExtUserUseridMap(serverMap, + username); + ExtCourseClassMap orgMap = RegisterServiceSoapBindingImpl.integrationService.getExtCourseClassMap(serverMap, + userMap, courseId, courseName, countryIsoCode, langIsoCode, + RegisterServiceSoapBindingImpl.service.getRootOrganisation().getOrganisationId().toString(), + asStaff, false); Organisation org = orgMap.getOrganisation(); // add user to lessons - User user = service.getUserByLogin(username); + User user = RegisterServiceSoapBindingImpl.service.getUserByLogin(username); addUserToLessons(user, org, asStaff); return true; } catch (Exception e) { @@ -299,29 +317,33 @@ /** * Same as addUserToLessons, except adds user to lessons in given subgroup. */ + @Override public boolean addUserToSubgroupLessons(String username, String serverId, String datetime, String hash, String courseId, String courseName, String countryIsoCode, String langIsoCode, String subgroupId, String subgroupName, Boolean asStaff) throws java.rmi.RemoteException { try { // authenticate external server - ExtServerOrgMap serverMap = integrationService.getExtServerOrgMap(serverId); + ExtServerOrgMap serverMap = RegisterServiceSoapBindingImpl.integrationService.getExtServerOrgMap(serverId); Authenticator.authenticate(serverMap, datetime, hash); // get group to use for this request - ExtUserUseridMap userMap = integrationService.getExtUserUseridMap(serverMap, username); - ExtCourseClassMap orgMap = integrationService.getExtCourseClassMap(serverMap, userMap, courseId, - courseName, countryIsoCode, langIsoCode, service.getRootOrganisation().getOrganisationId() - .toString(), asStaff, false); + ExtUserUseridMap userMap = RegisterServiceSoapBindingImpl.integrationService.getExtUserUseridMap(serverMap, + username); + ExtCourseClassMap orgMap = RegisterServiceSoapBindingImpl.integrationService.getExtCourseClassMap(serverMap, + userMap, courseId, courseName, countryIsoCode, langIsoCode, + RegisterServiceSoapBindingImpl.service.getRootOrganisation().getOrganisationId().toString(), + asStaff, false); Organisation group = orgMap.getOrganisation(); // get subgroup to add user to - ExtCourseClassMap subOrgMap = integrationService.getExtCourseClassMap(serverMap, userMap, subgroupId, - subgroupName, countryIsoCode, langIsoCode, group.getOrganisationId().toString(), asStaff, false); + ExtCourseClassMap subOrgMap = RegisterServiceSoapBindingImpl.integrationService.getExtCourseClassMap( + serverMap, userMap, subgroupId, subgroupName, countryIsoCode, langIsoCode, + group.getOrganisationId().toString(), asStaff, false); Organisation subgroup = subOrgMap.getOrganisation(); // add user to subgroup lessons if (subgroup != null) { - User user = service.getUserByLogin(username); + User user = RegisterServiceSoapBindingImpl.service.getUserByLogin(username); addUserToLessons(user, subgroup, asStaff); return true; } @@ -337,9 +359,10 @@ Iterator iter2 = org.getLessons().iterator(); while (iter2.hasNext()) { Lesson lesson = (Lesson) iter2.next(); - lessonService.addLearner(lesson.getLessonId(), user.getUserId()); - if (asStaff) - lessonService.addStaffMember(lesson.getLessonId(), user.getUserId()); + RegisterServiceSoapBindingImpl.lessonService.addLearner(lesson.getLessonId(), user.getUserId()); + if (asStaff) { + RegisterServiceSoapBindingImpl.lessonService.addStaffMember(lesson.getLessonId(), user.getUserId()); + } if (log.isDebugEnabled()) { log.debug("Added " + user.getLogin() + " to " + lesson.getLessonName() + (asStaff ? " as staff, and" : " as learner")); Index: lams_central/web/login.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_central/web/login.jsp,v diff -u -r1.51.2.7 -r1.51.2.8 --- lams_central/web/login.jsp 20 Oct 2015 10:41:38 -0000 1.51.2.7 +++ lams_central/web/login.jsp 21 Oct 2015 11:44:56 -0000 1.51.2.8 @@ -11,7 +11,6 @@ --%> - @@ -26,23 +25,15 @@ --%> - <%-- If credentials came from attributes, no need for encrypting --%> - <%= Configuration.getAsBoolean(ConfigurationKeys.LDAP_ENCRYPT_PASSWORD_FROM_BROWSER) %> <fmt:message key="title.login.window" /> - Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml =================================================================== RCS file: /usr/local/cvsroot/lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml,v diff -u -r1.35.2.3 -r1.35.2.4 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml 15 Oct 2014 07:48:47 -0000 1.35.2.3 +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml 21 Oct 2015 11:44:55 -0000 1.35.2.4 @@ -62,16 +62,30 @@ type="java.lang.String" column="password" not-null="true" - length="50" + length="64" > @hibernate.property column="password" - length="50" + length="64" not-null="true" + + @hibernate.property + column="salt" + length="64" + not-null="false" + + + getExtUserUseridMapByServerMap(ExtServerOrgMap serverMap); /** @@ -94,9 +96,10 @@ ExtServerOrgMap getExtServerOrgMap(Integer sid); ExtServerOrgMap getExtServerOrgMap(String serverId); - + /** - * Returns ExtCourseClassMap. If ExtCourseClassMap doesn't existent - returns null and does not create a new ExtCourseClassMap. + * Returns ExtCourseClassMap. If ExtCourseClassMap doesn't existent - returns null and does not create a new + * ExtCourseClassMap. * * @param extServerOrgMapId * @param extCourseId @@ -113,16 +116,17 @@ * @param country * @param email * @param prefix - * @param isUpdateUserDetails whether user details should be updated with provided parameters + * @param isUpdateUserDetails + * whether user details should be updated with provided parameters * @return * @throws UserInfoValidationException */ ExtUserUseridMap getImplicitExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, String firstName, String lastName, String language, String country, String email, boolean prefix, boolean isUpdateUserDetails) - throws UserInfoValidationException; + throws UserInfoValidationException; ExtUserUseridMap getImplicitExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, String password, - String firstName, String lastName, String email) throws UserInfoValidationException; + String salt, String firstName, String lastName, String email) throws UserInfoValidationException; List getAllExtServerOrgMaps(); Index: lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java,v diff -u -r1.33.2.2 -r1.33.2.3 --- lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java 13 Feb 2015 23:34:26 -0000 1.33.2.2 +++ lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java 21 Oct 2015 11:44:55 -0000 1.33.2.3 @@ -41,7 +41,6 @@ import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; -import org.apache.struts.action.ActionMessage; import org.lamsfoundation.lams.integration.ExtCourseClassMap; import org.lamsfoundation.lams.integration.ExtServerLessonMap; import org.lamsfoundation.lams.integration.ExtServerOrgMap; @@ -62,8 +61,6 @@ import org.lamsfoundation.lams.usermanagement.UserOrganisationRole; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.CSVUtil; -import org.lamsfoundation.lams.util.Configuration; -import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.HashUtil; import org.lamsfoundation.lams.util.LanguageUtil; import org.lamsfoundation.lams.util.ValidationUtil; @@ -92,28 +89,29 @@ @Override public ExtServerOrgMap getExtServerOrgMap(String serverId) { List list = service.findByProperty(ExtServerOrgMap.class, "serverid", serverId); - if (list == null || list.size() == 0) { + if ((list == null) || (list.size() == 0)) { return null; } else { return (ExtServerOrgMap) list.get(0); } } - + @Override public ExtCourseClassMap getExtCourseClassMap(Integer extServerOrgMapId, String extCourseId) { Map properties = new HashMap(); properties.put("courseid", extCourseId); properties.put("extServerOrgMap.sid", extServerOrgMapId); List list = service.findByProperties(ExtCourseClassMap.class, properties); - if (list == null || list.size() == 0) { + if ((list == null) || (list.size() == 0)) { return null; } else { - return (ExtCourseClassMap) list.get(0); + return list.get(0); } } // wrapper method for compatibility with original integration modules + @Override public ExtCourseClassMap getExtCourseClassMap(ExtServerOrgMap serverMap, ExtUserUseridMap userMap, String extCourseId, String countryIsoCode, String langIsoCode, String prettyCourseName, String method, Boolean prefix) throws UserInfoValidationException { @@ -136,60 +134,61 @@ } // wrapper method for compatibility with original integration modules + @Override public ExtCourseClassMap getExtCourseClassMap(ExtServerOrgMap serverMap, ExtUserUseridMap userMap, - String extCourseId, String countryIsoCode, String langIsoCode, String prettyCourseName, String method) throws UserInfoValidationException { + String extCourseId, String countryIsoCode, String langIsoCode, String prettyCourseName, String method) + throws UserInfoValidationException { return getExtCourseClassMap(serverMap, userMap, extCourseId, countryIsoCode, langIsoCode, prettyCourseName, method, true); } // newer method which accepts course name, a parent org id, a flag for whether user should get // 'teacher' roles, and a flag for whether to use a prefix in the org's name + @Override public ExtCourseClassMap getExtCourseClassMap(ExtServerOrgMap serverMap, ExtUserUseridMap userMap, String extCourseId, String extCourseName, String countryIsoCode, String langIsoCode, String parentOrgId, Boolean isTeacher, Boolean prefix) throws UserInfoValidationException { Organisation org; User user = userMap.getUser(); - + ExtCourseClassMap extCourseClassMap = getExtCourseClassMap(serverMap.getSid(), extCourseId); if (extCourseClassMap == null) { //create new ExtCourseClassMap - - org = createOrganisation(serverMap, user, extCourseId, extCourseName, countryIsoCode, - langIsoCode, parentOrgId, prefix); + + org = createOrganisation(serverMap, user, extCourseId, extCourseName, countryIsoCode, langIsoCode, + parentOrgId, prefix); extCourseClassMap = new ExtCourseClassMap(); extCourseClassMap.setCourseid(extCourseId); extCourseClassMap.setExtServerOrgMap(serverMap); extCourseClassMap.setOrganisation(org); service.save(extCourseClassMap); - + } else { org = extCourseClassMap.getOrganisation(); // update external course name if if has changed String requestedCourseName = prefix ? buildName(serverMap.getPrefix(), extCourseName) : extCourseName; - if (extCourseName != null && !org.getName().equals(requestedCourseName)) { + if ((extCourseName != null) && !org.getName().equals(requestedCourseName)) { // validate org name if (!ValidationUtil.isOrgNameValid(requestedCourseName)) { - throw new UserInfoValidationException( - "Can't create organisation due to validation error: " - + "organisation name cannot contain any of these characters < > ^ * @ % $. External server:" - + serverMap.getServerid() + ", orgId:" + extCourseId + ", orgName:" - + requestedCourseName); + throw new UserInfoValidationException("Can't create organisation due to validation error: " + + "organisation name cannot contain any of these characters < > ^ * @ % $. External server:" + + serverMap.getServerid() + ", orgId:" + extCourseId + ", orgName:" + requestedCourseName); } org.setName(requestedCourseName); service.updateOrganisationandWorkspaceNames(org); } } - + updateUserRoles(user, org, isTeacher); - + return extCourseClassMap; } private void updateUserRoles(User user, Organisation org, Boolean isTeacher) { - + //create UserOrganisation if it doesn't exist UserOrganisation uo = service.getUserOrganisation(user.getUserId(), org.getOrganisationId()); if (uo == null) { @@ -198,7 +197,7 @@ user.addUserOrganisation(uo); service.save(user); } - + Integer[] roles; if (isTeacher) { roles = new Integer[] { Role.ROLE_AUTHOR, Role.ROLE_MONITOR, Role.ROLE_LEARNER }; @@ -214,7 +213,8 @@ } } } - + + @Override public List getExtUserUseridMapByServerMap(ExtServerOrgMap serverMap) { Map properties = new HashMap(); properties.put("extServerOrgMap.sid", serverMap.getSid()); @@ -226,11 +226,12 @@ public ExtUserUseridMap getExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, boolean prefix) throws UserInfoFetchException, UserInfoValidationException { ExtUserUseridMap extUserUseridMap = getExistingExtUserUseridMap(serverMap, extUsername); - + if (extUserUseridMap == null) { String[] userData = getUserDataFromExtServer(serverMap, extUsername); - String password = HashUtil.sha1(RandomPasswordGenerator.nextPassword(10)); - return createExtUserUseridMap(serverMap, extUsername, password, userData, prefix); + String salt = HashUtil.salt(); + String password = HashUtil.sha256(RandomPasswordGenerator.nextPassword(10), salt); + return createExtUserUseridMap(serverMap, extUsername, password, salt, userData, prefix); } else { return extUserUseridMap; } @@ -248,43 +249,44 @@ properties.put("extServerOrgMap.sid", serverMap.getSid()); properties.put("extUsername", extUsername); List list = service.findByProperties(ExtUserUseridMap.class, properties); - - if (list == null || list.size() == 0) { + + if ((list == null) || (list.size() == 0)) { return null; } else { - return (ExtUserUseridMap) list.get(0); + return list.get(0); } } @Override public ExtUserUseridMap getImplicitExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, String password, - String firstName, String lastName, String email) throws UserInfoValidationException { + String salt, String firstName, String lastName, String email) throws UserInfoValidationException { ExtUserUseridMap extUserUseridMap = getExistingExtUserUseridMap(serverMap, extUsername); - + if (extUserUseridMap == null) { String[] defaultLangCountry = LanguageUtil.getDefaultLangCountry(); - String[] userData = { "", firstName, lastName, "", "", "", "", "", "", "", "", email, - defaultLangCountry[1], defaultLangCountry[0] }; - return createExtUserUseridMap(serverMap, extUsername, password, userData, false); + String[] userData = { "", firstName, lastName, "", "", "", "", "", "", "", "", email, defaultLangCountry[1], + defaultLangCountry[0] }; + return createExtUserUseridMap(serverMap, extUsername, password, salt, userData, false); } else { return extUserUseridMap; } } @Override - public ExtUserUseridMap getImplicitExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, - String firstName, String lastName, String language, String country, String email, boolean prefix, - boolean isUpdateUserDetails) throws UserInfoValidationException { - + public ExtUserUseridMap getImplicitExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, String firstName, + String lastName, String language, String country, String email, boolean prefix, boolean isUpdateUserDetails) + throws UserInfoValidationException { + ExtUserUseridMap extUserUseridMap = getExistingExtUserUseridMap(serverMap, extUsername); - + //create new one if it doesn't exist yet if (extUserUseridMap == null) { String[] userData = { "", firstName, lastName, "", "", "", "", "", "", "", "", email, country, language }; - String password = HashUtil.sha1(RandomPasswordGenerator.nextPassword(10)); - return createExtUserUseridMap(serverMap, extUsername, password, userData, prefix); - - //update user details if it's required + String salt = HashUtil.salt(); + String password = HashUtil.sha256(RandomPasswordGenerator.nextPassword(10), salt); + return createExtUserUseridMap(serverMap, extUsername, password, salt, userData, prefix); + + //update user details if it's required } else if (isUpdateUserDetails) { User user = extUserUseridMap.getUser(); @@ -307,27 +309,28 @@ + "Email format is invalid. External server:" + serverMap.getServerid() + ", Username:" + user.getLogin() + ", firstName:" + firstName + ", lastName:" + lastName); } - + user.setFirstName(firstName); user.setLastName(lastName); user.setEmail(email); user.setModifiedDate(new Date()); user.setLocale(LanguageUtil.getSupportedLocale(language, country)); service.save(user); - + return extUserUseridMap; - - //simply return existing one + + //simply return existing one } else { return extUserUseridMap; } } private Organisation createOrganisation(ExtServerOrgMap serverMap, User user, String extCourseId, - String extCourseName, String countryIsoCode, String langIsoCode, String parentOrgId, Boolean prefix) throws UserInfoValidationException { - + String extCourseName, String countryIsoCode, String langIsoCode, String parentOrgId, Boolean prefix) + throws UserInfoValidationException { + Organisation org = new Organisation(); - + // org name validation String orgName = prefix ? buildName(serverMap.getPrefix(), extCourseName) : extCourseName; if (StringUtils.isNotBlank(orgName) && !ValidationUtil.isOrgNameValid(orgName)) { @@ -336,46 +339,46 @@ + serverMap.getServerid() + ", orgId:" + extCourseId + ", orgName:" + orgName); } org.setName(orgName); - + org.setDescription(extCourseId); - org.setOrganisationState((OrganisationState) service - .findById(OrganisationState.class, OrganisationState.ACTIVE)); + org.setOrganisationState( + (OrganisationState) service.findById(OrganisationState.class, OrganisationState.ACTIVE)); org.setLocale(LanguageUtil.getSupportedLocale(langIsoCode, countryIsoCode)); // determine whether org will be a group or subgroup Organisation parent = (Organisation) service.findById(Organisation.class, Integer.valueOf(parentOrgId)); if (parent != null) { org.setParentOrganisation(parent); if (!parent.getOrganisationId().equals(service.getRootOrganisation().getOrganisationId())) { - org.setOrganisationType((OrganisationType) service.findById(OrganisationType.class, - OrganisationType.CLASS_TYPE)); + org.setOrganisationType( + (OrganisationType) service.findById(OrganisationType.class, OrganisationType.CLASS_TYPE)); } else { - org.setOrganisationType((OrganisationType) service.findById(OrganisationType.class, - OrganisationType.COURSE_TYPE)); + org.setOrganisationType( + (OrganisationType) service.findById(OrganisationType.class, OrganisationType.COURSE_TYPE)); } } else { // default org.setParentOrganisation(service.getRootOrganisation()); - org.setOrganisationType((OrganisationType) service.findById(OrganisationType.class, - OrganisationType.COURSE_TYPE)); + org.setOrganisationType( + (OrganisationType) service.findById(OrganisationType.class, OrganisationType.COURSE_TYPE)); } return service.saveOrganisation(org, user.getUserId()); } // flexible method to specify username and password private ExtUserUseridMap createExtUserUseridMap(ExtServerOrgMap serverMap, String extUsername, String password, - String[] userData, boolean prefix) throws UserInfoValidationException { - + String salt, String[] userData, boolean prefix) throws UserInfoValidationException { + String login = prefix ? buildName(serverMap.getPrefix(), extUsername) : extUsername; String firstName = userData[1]; String lastName = userData[2]; String email = userData[11]; - + // login validation if (StringUtils.isBlank(login)) { - throw new UserInfoValidationException("Can't create user due to validation error: " - + "Username cannot be blank. External server:" + serverMap.getServerid() + ", firstName:" - + firstName + ", lastName:" + lastName); + throw new UserInfoValidationException( + "Can't create user due to validation error: " + "Username cannot be blank. External server:" + + serverMap.getServerid() + ", firstName:" + firstName + ", lastName:" + lastName); } else if (!ValidationUtil.isUserNameValid(login)) { throw new UserInfoValidationException("Can't create user due to validation error: " + "Username can only contain alphanumeric characters and no spaces. External server:" @@ -402,10 +405,11 @@ + "Email format is invalid. External server:" + serverMap.getServerid() + ", Username:" + login + ", firstName:" + firstName + ", lastName:" + lastName); } - + User user = new User(); user.setLogin(login); user.setPassword(password); + user.setSalt(salt); user.setTitle(userData[0]); user.setFirstName(userData[1]); user.setLastName(userData[2]); @@ -418,8 +422,8 @@ user.setMobilePhone(userData[9]); user.setFax(userData[10]); user.setEmail(userData[11]); - user.setAuthenticationMethod((AuthenticationMethod) service.findById(AuthenticationMethod.class, - AuthenticationMethod.DB)); + user.setAuthenticationMethod( + (AuthenticationMethod) service.findById(AuthenticationMethod.class, AuthenticationMethod.DB)); user.setCreateDate(new Date()); user.setDisabledFlag(false); user.setLocale(LanguageUtil.getSupportedLocale(userData[13], userData[12])); @@ -450,17 +454,19 @@ // set the values for the parameters userDataCallbackUrl = userDataCallbackUrl.replaceAll("%username%", encodedExtUsername) .replaceAll("%timestamp%", timestamp).replaceAll("%hash%", hash); - log.debug(userDataCallbackUrl); + IntegrationService.log.debug(userDataCallbackUrl); URL url = new URL(userDataCallbackUrl); URLConnection conn = url.openConnection(); - if (!(conn instanceof HttpURLConnection)) + if (!(conn instanceof HttpURLConnection)) { throw new UserInfoFetchException("Fail to fetch user data from external server:" + serverMap.getServerid() + "- Invalid connection type"); + } HttpURLConnection httpConn = (HttpURLConnection) conn; - if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) + if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new UserInfoFetchException("Fail to fetch user data from external server:" + serverMap.getServerid() + " - Unexpected return HTTP Status:" + httpConn.getResponseCode()); + } InputStream is = url.openConnection().getInputStream(); BufferedReader isReader = new BufferedReader(new InputStreamReader(is, "UTF-8")); @@ -473,17 +479,18 @@ return CSVUtil.parse(str); } catch (MalformedURLException e) { - log.error(e); + IntegrationService.log.error(e); throw new UserInfoFetchException(e); } catch (IOException e) { - log.error(e); + IntegrationService.log.error(e); throw new UserInfoFetchException(e); } catch (ParseException e) { - log.error(e); + IntegrationService.log.error(e); throw new UserInfoFetchException(e); } } + @Override public String hash(ExtServerOrgMap serverMap, String extUsername, String timestamp) { String serverId = serverMap.getServerid(); String serverKey = serverMap.getServerkey(); @@ -496,43 +503,50 @@ return prefix + '_' + name; } + @Override public List getAllExtServerOrgMaps() { return service.findAll(ExtServerOrgMap.class); } + @Override @SuppressWarnings("unchecked") public List getMappedServers(String toolSig) { Map properties = new HashMap(); properties.put("tool.toolSignature", toolSig); - return (List) service.findByProperties(ExtServerToolAdapterMap.class, properties); + return service.findByProperties(ExtServerToolAdapterMap.class, properties); } + @Override @SuppressWarnings("unchecked") public ExtServerToolAdapterMap getMappedServer(String serverId, String toolSig) { Map properties = new HashMap(); properties.put("tool.toolSignature", toolSig); properties.put("extServer.serverid", serverId); List ret = service.findByProperties(ExtServerToolAdapterMap.class, properties); - if (ret != null && ret.size() > 0) { + if ((ret != null) && (ret.size() > 0)) { return (ExtServerToolAdapterMap) ret.get(0); } else { return null; } } + @Override public void saveExtServerToolAdapterMap(ExtServerToolAdapterMap map) { service.save(map); } + @Override public void deleteExtServerToolAdapterMap(ExtServerToolAdapterMap map) { service.delete(map); } + @Override public void saveExtServerOrgMap(ExtServerOrgMap map) { service.save(map); } + @Override public ExtServerOrgMap getExtServerOrgMap(Integer sid) { return (ExtServerOrgMap) service.findById(ExtServerOrgMap.class, sid); } @@ -544,6 +558,7 @@ service.save(map); } + @Override public String getLessonFinishCallbackUrl(User user, Lesson lesson) throws UnsupportedEncodingException { // the callback url must contain %username%, %lessonid%, %timestamp% and %hash% eg: // "http://test100.ics.mq.edu.au/webapps/lams-plglamscontent-bb_bb60/UserData?uid=%username%&lessonid=%lessonid%&ts=%timestamp%&hash=%hash%"; @@ -554,7 +569,8 @@ Long lessonId = lesson.getLessonId(); ExtServerLessonMap extServerLesson = getExtServerLessonMap(lessonId); // checks whether the lesson was created from extServer and whether it has lessonFinishCallbackUrl setting - if (extServerLesson != null && StringUtils.isNotBlank(extServerLesson.getExtServer().getLessonFinishUrl())) { + if ((extServerLesson != null) + && StringUtils.isNotBlank(extServerLesson.getExtServer().getLessonFinishUrl())) { ExtServerOrgMap serverMap = extServerLesson.getExtServer(); ExtUserUseridMap extUserUseridMap = getExtUserUseridMapByUserId(serverMap, user.getUserId()); @@ -571,7 +587,7 @@ lessonFinishCallbackUrl = lessonFinishCallbackUrl.replaceAll("%username%", encodedExtUsername) .replaceAll("%lessonid%", lessonId.toString()).replaceAll("%timestamp%", timestamp) .replaceAll("%hash%", hash); - log.debug(lessonFinishCallbackUrl); + IntegrationService.log.debug(lessonFinishCallbackUrl); } } } @@ -581,7 +597,7 @@ private ExtServerLessonMap getExtServerLessonMap(Long lessonId) { List list = service.findByProperty(ExtServerLessonMap.class, "lessonId", lessonId); - if (list == null || list.size() == 0) { + if ((list == null) || (list.size() == 0)) { return null; } else { return (ExtServerLessonMap) list.get(0); @@ -593,7 +609,7 @@ properties.put("extServerOrgMap.sid", serverMap.getSid()); properties.put("user.userId", userId); List list = service.findByProperties(ExtUserUseridMap.class, properties); - if (list == null || list.size() == 0) { + if ((list == null) || (list.size() == 0)) { return null; } else { return (ExtUserUseridMap) list.get(0); Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java,v diff -u -r1.50 -r1.50.2.1 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java 3 Sep 2013 10:55:36 -0000 1.50 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java 21 Oct 2015 11:44:55 -0000 1.50.2.1 @@ -50,10 +50,15 @@ private String login; /** - * persistent field ] TODO needs to be removed for security reason + * persistent field */ private String password; + /** + * persistent field + */ + private String salt; + /** nullable persistent field */ private String title; @@ -198,10 +203,18 @@ return password; } + public String getSalt() { + return salt; + } + public void setPassword(String password) { this.password = password; } + public void setSalt(String salt) { + this.salt = salt; + } + public String getTitle() { return title; } @@ -485,7 +498,7 @@ // TimeZone.getTimeZone("Australia/Sydney"), timeZone, authenticationMethod.getAuthenticationMethodId(), fckLanguageMapping, lamsCommunityToken, lamsCommunityUsername, (tutorialsDisabled == null ? false : true), // assume tutorials enabled if not - // set + // set tutorialPages, (firstLogin == null ? true : false) // assume no firstLogin value means they haven't // logged in ); Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java,v diff -u -r1.22 -r1.22.2.1 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java 3 Sep 2013 10:55:36 -0000 1.22 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java 21 Oct 2015 11:44:54 -0000 1.22.2.1 @@ -82,6 +82,7 @@ this.service = service; } + @Override public void updateLDAPUser(User user, Attributes attrs) { HashMap map = getLDAPUserAttributes(attrs); user.setLogin(map.get("login")); @@ -107,7 +108,7 @@ // tries to match ldap attribute to a locale, otherwise returns server // default private SupportedLocale getLocale(String attribute) { - if (attribute != null && attribute.trim().length() > 0) { + if ((attribute != null) && (attribute.trim().length() > 0)) { int index = attribute.indexOf("_"); if (index > 0) { String language = attribute.substring(0, index); @@ -120,11 +121,12 @@ return LanguageUtil.getDefaultLocale(); } + @Override public boolean createLDAPUser(Attributes attrs) { User user = new User(); try { HashMap map = getLDAPUserAttributes(attrs); - if (map.get("login") != null && map.get("login").trim().length() > 0) { + if ((map.get("login") != null) && (map.get("login").trim().length() > 0)) { if (log.isDebugEnabled()) { log.debug("===> using LDAP attributes: " + map.get("login") + "," + map.get("fname") + "," + map.get("lname") + "," + map.get("email") + "," + map.get("address1") + "," @@ -134,7 +136,9 @@ + map.get("mobile") + "," + map.get("locale")); } user.setLogin(map.get("login")); - user.setPassword(HashUtil.sha1(RandomPasswordGenerator.nextPassword(10))); + String salt = HashUtil.salt(); + user.setSalt(salt); + user.setPassword(HashUtil.sha256(RandomPasswordGenerator.nextPassword(10), salt)); user.setFirstName(map.get("fname")); user.setLastName(map.get("lname")); user.setEmail(map.get("email")); @@ -149,8 +153,8 @@ user.setEveningPhone(map.get("eveningphone")); user.setFax(map.get("fax")); user.setMobilePhone(map.get("mobile")); - user.setAuthenticationMethod((AuthenticationMethod) service.findById(AuthenticationMethod.class, - AuthenticationMethod.LDAP)); + user.setAuthenticationMethod( + (AuthenticationMethod) service.findById(AuthenticationMethod.class, AuthenticationMethod.LDAP)); user.setFlashTheme(service.getDefaultFlashTheme()); user.setHtmlTheme(service.getDefaultHtmlTheme()); user.setDisabledFlag(getDisabledBoolean(attrs)); @@ -175,88 +179,89 @@ HashMap map = new HashMap(); try { map.put("login", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR)))); - map.put("fname", getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_FIRST_NAME_ATTR)))); - map.put("lname", getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_LAST_NAME_ATTR)))); + map.put("fname", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_FIRST_NAME_ATTR)))); + map.put("lname", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_LAST_NAME_ATTR)))); map.put("email", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_EMAIL_ATTR)))); - map.put("address1", getSingleAttributeString(attrs - .get(Configuration.get(ConfigurationKeys.LDAP_ADDR1_ATTR)))); - map.put("address2", getSingleAttributeString(attrs - .get(Configuration.get(ConfigurationKeys.LDAP_ADDR2_ATTR)))); - map.put("address3", getSingleAttributeString(attrs - .get(Configuration.get(ConfigurationKeys.LDAP_ADDR3_ATTR)))); + map.put("address1", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_ADDR1_ATTR)))); + map.put("address2", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_ADDR2_ATTR)))); + map.put("address3", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_ADDR3_ATTR)))); map.put("city", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_CITY_ATTR)))); map.put("state", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_STATE_ATTR)))); - map.put("postcode", getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_POSTCODE_ATTR)))); - map.put("country", getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_COUNTRY_ATTR)))); - map.put("dayphone", getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_DAY_PHONE_ATTR)))); - map.put("eveningphone", getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_EVENING_PHONE_ATTR)))); + map.put("postcode", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_POSTCODE_ATTR)))); + map.put("country", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_COUNTRY_ATTR)))); + map.put("dayphone", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_DAY_PHONE_ATTR)))); + map.put("eveningphone", + getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_EVENING_PHONE_ATTR)))); map.put("fax", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_FAX_ATTR)))); map.put("mobile", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_MOBILE_ATTR)))); map.put("locale", getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_LOCALE_ATTR)))); - map.put("disabled", getSingleAttributeString(attrs.get(getLdapAttr(Configuration - .get(ConfigurationKeys.LDAP_DISABLED_ATTR))))); + map.put("disabled", getSingleAttributeString( + attrs.get(getLdapAttr(Configuration.get(ConfigurationKeys.LDAP_DISABLED_ATTR))))); } catch (Exception e) { log.error("===> Exception occurred while getting LDAP user attributes: ", e); } // field validation; trim values before they get to database - if (map.get("login") != null && map.get("login").trim().length() > 255) { + if ((map.get("login") != null) && (map.get("login").trim().length() > 255)) { map.put("login", map.get("login").substring(0, 255)); } - if (map.get("fname") != null && map.get("fname").trim().length() > 128) { + if ((map.get("fname") != null) && (map.get("fname").trim().length() > 128)) { map.put("fname", map.get("fname").substring(0, 128)); } - if (map.get("lname") != null && map.get("lname").trim().length() > 128) { + if ((map.get("lname") != null) && (map.get("lname").trim().length() > 128)) { map.put("lname", map.get("lname").substring(0, 128)); } - if (map.get("email") != null && map.get("email").trim().length() > 128) { + if ((map.get("email") != null) && (map.get("email").trim().length() > 128)) { map.put("email", map.get("email").substring(0, 128)); } - if (map.get("address1") != null && map.get("address1").trim().length() > 64) { + if ((map.get("address1") != null) && (map.get("address1").trim().length() > 64)) { map.put("address1", map.get("address1").substring(0, 64)); } - if (map.get("address2") != null && map.get("address2").trim().length() > 64) { + if ((map.get("address2") != null) && (map.get("address2").trim().length() > 64)) { map.put("address2", map.get("address2").substring(0, 64)); } - if (map.get("address3") != null && map.get("address3").trim().length() > 64) { + if ((map.get("address3") != null) && (map.get("address3").trim().length() > 64)) { map.put("address3", map.get("address3").substring(0, 64)); } - if (map.get("city") != null && map.get("city").trim().length() > 64) { + if ((map.get("city") != null) && (map.get("city").trim().length() > 64)) { map.put("city", map.get("city").substring(0, 64)); } - if (map.get("state") != null && map.get("state").trim().length() > 64) { + if ((map.get("state") != null) && (map.get("state").trim().length() > 64)) { map.put("state", map.get("state").substring(0, 64)); } - if (map.get("postcode") != null && map.get("postcode").trim().length() > 10) { + if ((map.get("postcode") != null) && (map.get("postcode").trim().length() > 10)) { map.put("postcode", map.get("postcode").substring(0, 10)); } - if (map.get("country") != null && map.get("country").trim().length() > 64) { + if ((map.get("country") != null) && (map.get("country").trim().length() > 64)) { map.put("country", map.get("country").substring(0, 64)); } - if (map.get("dayphone") != null && map.get("dayphone").trim().length() > 64) { + if ((map.get("dayphone") != null) && (map.get("dayphone").trim().length() > 64)) { map.put("dayphone", map.get("dayphone").substring(0, 64)); } - if (map.get("eveningphone") != null && map.get("eveningphone").trim().length() > 64) { + if ((map.get("eveningphone") != null) && (map.get("eveningphone").trim().length() > 64)) { map.put("eveningphone", map.get("eveningphone").substring(0, 64)); } - if (map.get("fax") != null && map.get("fax").trim().length() > 64) { + if ((map.get("fax") != null) && (map.get("fax").trim().length() > 64)) { map.put("fax", map.get("fax").substring(0, 64)); } - if (map.get("mobile") != null && map.get("mobile").trim().length() > 64) { + if ((map.get("mobile") != null) && (map.get("mobile").trim().length() > 64)) { map.put("mobile", map.get("mobile").substring(0, 64)); } return map; } + @Override public String getLdapAttr(String ldapAttr) { if (ldapAttr != null) { return (ldapAttr.startsWith("!") ? ldapAttr.substring(1) : ldapAttr); @@ -277,6 +282,7 @@ return null; } + @Override public boolean getDisabledBoolean(Attributes attrs) { String ldapDisabledAttrStr = Configuration.get(ConfigurationKeys.LDAP_DISABLED_ATTR); if (ldapDisabledAttrStr.startsWith("!")) { @@ -295,6 +301,7 @@ } + @Override public boolean addLDAPUser(Attributes attrs, Integer userId) { User user = (User) service.findById(User.class, userId); // get ldap attributes for lams org and roles @@ -305,51 +312,51 @@ String orgField = Configuration.get(ConfigurationKeys.LDAP_ORG_FIELD); boolean isAddingUserSuccessful = true; - if (ldapOrgs != null && ldapRoles != null && orgField != null) { + if ((ldapOrgs != null) && (ldapRoles != null) && (orgField != null)) { // get list of possible matching organisations - for (String ldapOrg : ldapOrgs) { - log.debug("Looking for organisation to add ldap user to..."); - List orgList = (List) service.findByProperty(Organisation.class, orgField, ldapOrg); - if (orgList != null && !orgList.isEmpty()) { - Organisation org = null; + for (String ldapOrg : ldapOrgs) { + log.debug("Looking for organisation to add ldap user to..."); + List orgList = service.findByProperty(Organisation.class, orgField, ldapOrg); + if ((orgList != null) && !orgList.isEmpty()) { + Organisation org = null; + if (orgList.size() == 1) { + org = (Organisation) orgList.get(0); + } else if (orgList.size() > 1) { + // if there are multiple orgs, select the one that is + // active, if there is one + HashMap properties = new HashMap(); + properties.put(orgField, ldapOrg); + properties.put("organisationState.organisationStateId", OrganisationState.ACTIVE); + orgList = service.findByProperties(Organisation.class, properties); if (orgList.size() == 1) { org = (Organisation) orgList.get(0); - } else if (orgList.size() > 1) { - // if there are multiple orgs, select the one that is - // active, if there is one - HashMap properties = new HashMap(); - properties.put(orgField, ldapOrg); - properties.put("organisationState.organisationStateId", OrganisationState.ACTIVE); - orgList = (List) service.findByProperties(Organisation.class, properties); - if (orgList.size() == 1) { - org = (Organisation) orgList.get(0); - } else { - log.warn("More than one LAMS organisation found with the " + orgField + ": " + ldapOrg); - isAddingUserSuccessful = false; - break; - } - } - - // now convert the roles to lams roles and add the user to the org - List roleIds = getRoleIds(ldapRoles); - if (roleIds != null && !roleIds.isEmpty()) { - service.setRolesForUserOrganisation(user, org.getOrganisationId(), roleIds); } else { - log.warn("Couldn't map any roles from attribute: " - + Configuration.get(ConfigurationKeys.LDAP_ROLES_ATTR)); + log.warn("More than one LAMS organisation found with the " + orgField + ": " + ldapOrg); isAddingUserSuccessful = false; - } - - // if the user is a member of any other groups, remove them - if (Configuration.getAsBoolean(ConfigurationKeys.LDAP_ONLY_ONE_ORG)) { - service.removeUserFromOtherGroups(userId, org.getOrganisationId()); break; - } + } + } + + // now convert the roles to lams roles and add the user to the org + List roleIds = getRoleIds(ldapRoles); + if ((roleIds != null) && !roleIds.isEmpty()) { + service.setRolesForUserOrganisation(user, org.getOrganisationId(), roleIds); } else { - log.warn("No LAMS organisations found with the " + orgField + ": " + ldapOrg); + log.warn("Couldn't map any roles from attribute: " + + Configuration.get(ConfigurationKeys.LDAP_ROLES_ATTR)); isAddingUserSuccessful = false; } + + // if the user is a member of any other groups, remove them + if (Configuration.getAsBoolean(ConfigurationKeys.LDAP_ONLY_ONE_ORG)) { + service.removeUserFromOtherGroups(userId, org.getOrganisationId()); + break; + } + } else { + log.warn("No LAMS organisations found with the " + orgField + ": " + ldapOrg); + isAddingUserSuccessful = false; } + } } return isAddingUserSuccessful; } @@ -386,7 +393,7 @@ } private boolean isRoleInList(String list, String role) { - if (list != null && role != null) { + if ((list != null) && (role != null)) { String[] array = list.split(";"); for (String s : array) { if (role.contains(s)) { @@ -418,6 +425,7 @@ } // get the single (string) value of an ldap attribute + @Override public String getSingleAttributeString(Attribute attr) { try { if (attr != null) { @@ -432,12 +440,13 @@ return null; } + @Override public BulkUpdateResultDTO bulkUpdate() { // setup ldap context Properties env = new Properties(); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - env.setProperty(Context.SECURITY_AUTHENTICATION, Configuration - .get(ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION)); + env.setProperty(Context.SECURITY_AUTHENTICATION, + Configuration.get(ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION)); // make java ldap provider return 10 results at a time instead of // default 1 env.setProperty(Context.BATCHSIZE, "10"); @@ -446,7 +455,7 @@ if (StringUtils.equals("ssl", securityProtocol)) { env.setProperty(Context.SECURITY_PROTOCOL, securityProtocol); } - + // setup initial bind user credentials if configured if (StringUtils.isNotBlank(Configuration.get(ConfigurationKeys.LDAP_BIND_USER_DN))) { env.setProperty(Context.SECURITY_PRINCIPAL, Configuration.get(ConfigurationKeys.LDAP_BIND_USER_DN)); @@ -504,48 +513,49 @@ NamingEnumeration results = ctx.search(baseDN, filter, ctrl); while (results.hasMore()) { try { - SearchResult result = results.next(); - Attributes attrs = result.getAttributes(); + SearchResult result = results.next(); + Attributes attrs = result.getAttributes(); - // add or update this user to LAMS - boolean disabled = getDisabledBoolean(attrs); - String login = getSingleAttributeString(attrs.get(Configuration - .get(ConfigurationKeys.LDAP_LOGIN_ATTR))); - if (login != null && login.trim().length() > 0) { - int code = bulkUpdateLDAPUser(login, attrs, disabled); - switch (code) { - case BULK_UPDATE_CREATED: - createdUsers++; - break; - case BULK_UPDATE_UPDATED: - updatedUsers++; - break; - case BULK_UPDATE_DISABLED: - disabledUsers++; - break; - } - } else { - log.error("Couldn't find login attribute for user using attribute name: " - + Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR) - + ". Dumping attributes..."); - NamingEnumeration enumAttrs = attrs.getAll(); - while (enumAttrs.hasMoreElements()) { - log.error(enumAttrs.next()); - } - } - } catch (Exception e) { - // continue processing - messages.add("Error processing context result number " + contextResults + ": " + e.getMessage()); - } + // add or update this user to LAMS + boolean disabled = getDisabledBoolean(attrs); + String login = getSingleAttributeString( + attrs.get(Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR))); + if ((login != null) && (login.trim().length() > 0)) { + int code = bulkUpdateLDAPUser(login, attrs, disabled); + switch (code) { + case BULK_UPDATE_CREATED: + createdUsers++; + break; + case BULK_UPDATE_UPDATED: + updatedUsers++; + break; + case BULK_UPDATE_DISABLED: + disabledUsers++; + break; + } + } else { + log.error("Couldn't find login attribute for user using attribute name: " + + Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR) + + ". Dumping attributes..."); + NamingEnumeration enumAttrs = attrs.getAll(); + while (enumAttrs.hasMoreElements()) { + log.error(enumAttrs.next()); + } + } + } catch (Exception e) { + // continue processing + messages.add( + "Error processing context result number " + contextResults + ": " + e.getMessage()); + } contextResults++; } cookie = getPagedResponseCookie(ctx.getResponseControls()); // set response cookie to continue paged result - ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, cookie, - Control.NONCRITICAL) }); + ctx.setRequestControls( + new Control[] { new PagedResultsControl(pageSize, cookie, Control.NONCRITICAL) }); } while (cookie != null); log.info("Ldap context " + baseDN + " returned " + contextResults + " users."); ctx.close(); @@ -580,13 +590,13 @@ log.info("Creating new user for LDAP username: " + login); if (createLDAPUser(attrs)) { user = getService().getUserByLogin(login); - returnCode = BULK_UPDATE_CREATED; + returnCode = LdapService.BULK_UPDATE_CREATED; } else { log.error("Couldn't create new user for LDAP username: " + login); } } else { updateLDAPUser(user, attrs); - returnCode = BULK_UPDATE_UPDATED; + returnCode = LdapService.BULK_UPDATE_UPDATED; } if (!addLDAPUser(attrs, user.getUserId())) { log.error("Couldn't add LDAP user: " + login + " to organisation."); @@ -595,7 +605,7 @@ // remove user from groups and set disabled flag if (user != null) { getService().disableUser(user.getUserId()); - returnCode = BULK_UPDATE_DISABLED; + returnCode = LdapService.BULK_UPDATE_DISABLED; } } return returnCode; Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java,v diff -u -r1.115.2.5 -r1.115.2.6 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java 5 Oct 2015 18:03:00 -0000 1.115.2.5 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java 21 Oct 2015 11:44:54 -0000 1.115.2.6 @@ -109,8 +109,8 @@ private IAuditService getAuditService() { if (UserManagementService.auditService == null) { - WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(SessionManager - .getServletContext()); + WebApplicationContext ctx = WebApplicationContextUtils + .getWebApplicationContext(SessionManager.getServletContext()); UserManagementService.auditService = (IAuditService) ctx.getBean("auditService"); } return UserManagementService.auditService; @@ -356,7 +356,8 @@ // now, process any children of this org Organisation childOrganisation = userOrganisation.getOrganisation(); if (org.getChildOrganisations().size() > 0) { - getChildOrganisations(user, childOrganisation, restrictToRoleNames, restrictToClassIds, dtolist); + getChildOrganisations(user, childOrganisation, restrictToRoleNames, restrictToClassIds, + dtolist); } } } @@ -395,8 +396,8 @@ Map map = new HashMap(); map.put("user.userId", user.getUserId()); map.put("organisation.organisationId", organisationId); - UserOrganisation userOrganisation = (UserOrganisation) baseDAO - .findByProperties(UserOrganisation.class, map).get(0); + UserOrganisation userOrganisation = (UserOrganisation) baseDAO.findByProperties(UserOrganisation.class, map) + .get(0); OrganisationDTO dto = userOrganisation.getOrganisation().getOrganisationDTO(); addRolesToDTO(null, userOrganisation, dto); return dto; @@ -445,8 +446,8 @@ // it's ugly to put query string here, but it is a convention of this class so let's stick to it for now String query = "SELECT uo.user FROM UserOrganisation uo INNER JOIN uo.userOrganisationRoles r WHERE uo.organisation.organisationId=" + organisationID + " AND r.role.name= '" + roleName + "'"; - List queryResult = (List) baseDAO.find(query); - + List queryResult = baseDAO.find(query); + for (User user : queryResult) { if (isFlashCall && !getUser) { users.add(user.getUserFlashDTO()); @@ -456,14 +457,15 @@ users.add(user.getUserDTO()); } } - + return users; } @Override public Organisation getRootOrganisation() { - return (Organisation) baseDAO.findByProperty(Organisation.class, "organisationType.organisationTypeId", - OrganisationType.ROOT_TYPE).get(0); + return (Organisation) baseDAO + .findByProperty(Organisation.class, "organisationType.organisationTypeId", OrganisationType.ROOT_TYPE) + .get(0); } @Override @@ -537,7 +539,9 @@ public void updatePassword(String login, String password) { try { User user = getUserByLogin(login); - user.setPassword(HashUtil.sha1(password)); + String salt = HashUtil.salt(); + user.setSalt(salt); + user.setPassword(HashUtil.sha256(password, salt)); baseDAO.update(user); } catch (Exception e) { log.debug(e); @@ -628,8 +632,8 @@ User user = (User) findById(User.class, m.getUserID()); UserOrganisation uo = new UserOrganisation(user, organisation); log.debug("adding course manager: " + user.getUserId() + " as staff"); - UserOrganisationRole uor = new UserOrganisationRole(uo, (Role) findById(Role.class, - Role.ROLE_MONITOR)); + UserOrganisationRole uor = new UserOrganisationRole(uo, + (Role) findById(Role.class, Role.ROLE_MONITOR)); HashSet uors = new HashSet(); uors.add(uor); uo.setUserOrganisationRoles(uors); Index: lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java,v diff -u -r1.53.2.2 -r1.53.2.3 --- lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java 4 May 2015 09:19:10 -0000 1.53.2.2 +++ lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java 21 Oct 2015 11:44:54 -0000 1.53.2.3 @@ -47,7 +47,7 @@ public static String LAMS_EAR_DIR = "EARDir"; public static String SMTP_SERVER = "SMTPServer"; - + public static String USE_INTERNAL_SMTP_SERVER = "InternalSMTPServer"; public static String LAMS_ADMIN_EMAIL = "LamsSupportEmail"; @@ -128,7 +128,7 @@ public static String LAMS_COMMUNITY_ENABLE = "LAMS_Community_enable"; public static String ALLOW_EDIT_ON_FLY = "AllowLiveEdit"; - + public static String SHOW_ALL_MY_LESSON_LINK = "ShowAllMyLessonLink"; public static String LDAP_PROVISIONING_ENABLED = "LDAPProvisioningEnabled"; @@ -140,9 +140,9 @@ public static String LDAP_SEARCH_FILTER = "LDAPSearchFilter"; public static String LDAP_BASE_DN = "LDAPBaseDN"; - + public static String LDAP_BIND_USER_DN = "LDAPBindUserDN"; - + public static String LDAP_BIND_USER_PASSWORD = "LDAPBindUserPassword"; public static String LDAP_SECURITY_PROTOCOL = "LDAPSecurityProtocol"; @@ -205,8 +205,6 @@ public static String LDAP_ONLY_ONE_ORG = "LDAPOnlyOneOrg"; - public static String LDAP_ENCRYPT_PASSWORD_FROM_BROWSER = "LDAPEncryptPasswordFromBrowser"; - public static String LDAP_SEARCH_RESULTS_PAGE_SIZE = "LDAPSearchResultsPageSize"; /** @@ -231,17 +229,17 @@ public static String ADMIN_SCREEN_SIZE = "AdminScreenSize"; public static String GMAP_KEY = "GmapKey"; - + public static String RED5_SERVER_URL = "Red5ServerUrl"; - + public static String RED5_RECORDINGS_URL = "Red5RecordingsUrl"; - + public static String SMTP_AUTH_USER = "SMTPUser"; - + public static String SMTP_AUTH_PASSWORD = "SMTPPassword"; - + public static String PROFILE_EDIT_ENABLE = "ProfileEditEnable"; - + public static String PROFILE_PARTIAL_EDIT_ENABLE = "ProfilePartialEditEnable"; public static String KALTURA_SERVER = "KalturaServer"; @@ -253,25 +251,25 @@ public static String KALTURA_USER_SECRET = "KalturaUserSecret"; public static String KALTURA_KCW_UI_CONF_ID = "KalturaKCWUiConfId"; - + public static String KALTURA_KDP_UI_CONF_ID = "KalturaKDPUiConfId"; - + public static String USER_VALIDATION_REQUIRED_USERNAME = "UserValidationUsername"; - + public static String USER_VALIDATION_REQUIRED_FIRST_LAST_NAME = "UserValidationFirstLastName"; - + public static String USER_VALIDATION_REQUIRED_EMAIL = "UserValidationEmail"; // LDEV-2747 public static String ENABLE_SERVER_REGISTRATION = "EnableServerRegistration"; - + // LDEV-2889 public static String LEARNER_COLLAPSIBLE_PROGRESS_PANEL = "LearnerCollapsProgressPanel"; - + // CNG-26 Add to lams_configuration and set to false // if you don't want imported LD to have __ appended public static String SUFFIX_IMPORTED_LD = "SuffixImportedLD"; - + // LDEV-3254 public static String CONFIGURATION_CACHE_REFRESH_INTERVAL = "ConfigCacheRefresInterval"; } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/util/HashUtil.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/HashUtil.java,v diff -u -r1.3 -r1.3.24.1 --- lams_common/src/java/org/lamsfoundation/lams/util/HashUtil.java 20 Sep 2006 02:41:57 -0000 1.3 +++ lams_common/src/java/org/lamsfoundation/lams/util/HashUtil.java 21 Oct 2015 11:44:54 -0000 1.3.24.1 @@ -24,38 +24,68 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import org.apache.commons.codec.binary.Hex; /** - * @version - * - *

- * View Source - *

- * - * @author Fei Yang - * - * Created at 16:25:56 on 20/06/2006 + * Utilities for hashing passwords. + * + * @author Fei Yang, Marcin Cieslak */ public class HashUtil { - public static String sha1(String plaintext){ - try { - MessageDigest md = MessageDigest.getInstance("SHA1"); - return new String(Hex.encodeHex(md.digest(plaintext.getBytes()))); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } + private static final SecureRandom secureRandom = new SecureRandom(); + + public static final int SALT_BYTE_LENGTH = 32; + public static final int SALT_HEX_LENGTH = HashUtil.SALT_BYTE_LENGTH * 2; + public static final int SHA1_HEX_LENGTH = 40; + public static final int SHA256_HEX_LENGTH = 64; + + public static String sha1(String plaintext) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + return new String(Hex.encodeHex(md.digest(plaintext.getBytes()))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } } - public static String md5(String plaintext){ - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - return new String(Hex.encodeHex(md.digest(plaintext.getBytes()))); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } + public static String sha256(String plaintext) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + return new String(Hex.encodeHex(md.digest(plaintext.getBytes()))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } } - -} + + public static String sha256(String password, String salt) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + String plaintext = salt + password; + return new String(Hex.encodeHex(md.digest(plaintext.getBytes()))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static String md5(String plaintext) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + return new String(Hex.encodeHex(md.digest(plaintext.getBytes()))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static String salt() { + return HashUtil.salt(HashUtil.SALT_BYTE_LENGTH); + } + + public static String salt(int length) { + byte[] salt = new byte[length]; + HashUtil.secureRandom.nextBytes(salt); + return Hex.encodeHexString(salt); + } +} \ No newline at end of file Index: lams_gradebook/web/template.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_gradebook/web/template.jsp,v diff -u -r1.1 -r1.1.8.1 --- lams_gradebook/web/template.jsp 9 Apr 2009 04:55:52 -0000 1.1 +++ lams_gradebook/web/template.jsp 21 Oct 2015 11:44:53 -0000 1.1.8.1 @@ -11,7 +11,6 @@ <fmt:message><tiles:getAsString name="titleKey"/></fmt:message> -