Index: lams_central/src/java/org/lamsfoundation/lams/webservice/SPEnrolmentServlet.java =================================================================== diff -u -r189a7bfea07961794f4044042ba26ba2b0ffc24a -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_central/src/java/org/lamsfoundation/lams/webservice/SPEnrolmentServlet.java (.../SPEnrolmentServlet.java) (revision 189a7bfea07961794f4044042ba26ba2b0ffc24a) +++ lams_central/src/java/org/lamsfoundation/lams/webservice/SPEnrolmentServlet.java (.../SPEnrolmentServlet.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -36,8 +36,11 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -60,6 +63,7 @@ import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.Role; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.UserOrganisation; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.Configuration; import org.lamsfoundation.lams.util.ConfigurationKeys; @@ -105,6 +109,11 @@ // start interacting with DB HibernateSessionManager.openSession(); + ExtServer extServer = integrationService.getExtServer(INTEGRATED_SERVER_NAME); + if (extServer == null) { + throw new ServletException("Integrated server not found: " + INTEGRATED_SERVER_NAME); + } + // split each line into list of trimmed pieces List> lines = Files.readAllLines(fileInput).parallelStream().unordered() .map(line -> Arrays.stream(line.split(DELIMITER)).map(elem -> elem.trim()) @@ -134,36 +143,93 @@ elem -> elem.get(6).equals(ROLE_STAFF) ? elem.get(3) : elem.get(5), Collectors.toList())))); - // map of user login -> course ID -> role IDs - Map>> existingRoles = new HashMap<>(); // map of user login -> user ID Map userIDs = new HashMap<>(); // find sysadmin as he/she will be the creator of organisations Organisation rootOrganisation = userManagementService.getRootOrganisation(); Integer creatorId = rootOrganisation.getCreatedBy().getUserId(); - ExtServer extServer = integrationService.getExtServer(INTEGRATED_SERVER_NAME); - if (extServer == null) { - throw new ServletException("Integrated server not found: " + INTEGRATED_SERVER_NAME); - } + Integer extServerSid = extServer.getSid(); + // load all users from DB which are present in the output file + // map of user login -> user + Map allExistingUsers = userManagementService + .findByPropertyValues(User.class, "login", users.keySet()).parallelStream() + .collect(Collectors.toConcurrentMap(User::getLogin, u -> u)); + // load all ext users from DB which are present in the output file + // map of user login -> extUser + Map allExistingExtUsers = userManagementService + .findByPropertyValues(ExtUserUseridMap.class, "extUsername", allExistingUsers.keySet()) + .parallelStream().filter(e -> e.getExtServer().getSid().equals(extServerSid)) + .collect(Collectors.toConcurrentMap(ExtUserUseridMap::getExtUsername, e -> e)); + // create users and ext users + Set allUsersParsed = createUsers(extServer, creatorId, users, userIDs, allExistingUsers, + allExistingExtUsers); - // create users - Set allUsersParsed = createUsers(extServer, creatorId, users, userIDs, existingRoles); + // load all organisations from DB which are present in the output file, by code + // map of code -> organisation + Map allExistingOrganisations = userManagementService + .findByPropertyValues(Organisation.class, "code", courses.keySet()).parallelStream() + .collect(Collectors.toConcurrentMap(Organisation::getCode, o -> o)); + + // prepare codes of all suborganisations disregarding which organisation is their parent + Set allExistingSubOrganisationCodes = mappings.values().stream() + .flatMap(e -> e.keySet().stream()).collect(Collectors.toSet()); + + // load all suborganisations from DB which are present in the output file + List allExistingSubcourseObjects = userManagementService + .findByPropertyValues(Organisation.class, "code", allExistingSubOrganisationCodes); + + // map of course code -> subcourse code -> subcourse + Map> allExistingSubcourses = allExistingSubcourseObjects + .parallelStream() + .collect(Collectors.groupingByConcurrent(o -> o.getParentOrganisation().getCode(), + Collectors.toConcurrentMap(Organisation::getCode, o -> o))); + + // load all ext courses and subcourses from DB which are present in the output file + Map allExistingExtCourses = userManagementService + .findByPropertyValues(ExtCourseClassMap.class, "classid", Stream + // merge IDs of organisations and suborganisations + .concat(allExistingOrganisations.values().stream().map(Organisation::getOrganisationId), + allExistingSubcourseObjects.stream().map(Organisation::getOrganisationId)) + .collect(Collectors.toSet())) + .parallelStream().filter(e -> e.getExtServer().getSid().equals(extServerSid)) + .collect(Collectors.toConcurrentMap(e -> e.getOrganisation().getOrganisationId(), e -> e)); + + // map of user login -> course ID -> role IDs + // for all users which are present in the output file + Map>> allExistingRoles = userManagementService + .findByPropertyValues(UserOrganisation.class, "user.userId", + allExistingUsers.values().parallelStream() + .collect(Collectors.mapping(User::getUserId, Collectors.toSet()))) + .stream() + .collect(Collectors.groupingBy(uo -> uo.getUser().getLogin(), + Collectors.toMap( + userOrganisation -> userOrganisation.getOrganisation().getOrganisationId(), + userOrganisation -> userOrganisation.getUserOrganisationRoles().stream() + .map(userOrganisationRole -> userOrganisationRole.getRole().getRoleId()) + .collect(Collectors.toSet())))); + Set allUsersinCourses = new HashSet<>(); // go through each course + AtomicInteger mappingsProcessed = new AtomicInteger(); + logger.info("Processing courses and assigments"); for (Entry courseEntry : courses.entrySet()) { String courseCode = courseEntry.getKey(); // create or get existing course Organisation course = getCourse(courseCode, courseEntry.getValue(), extServer, creatorId, - rootOrganisation); + rootOrganisation, allExistingOrganisations, allExistingExtCourses); // collect learners from all subcourses of this course Set allUsersInSubcourses = assignUsers(course, mappings, extServer, creatorId, allUsersParsed, - userIDs, existingRoles, isStaffMode); + userIDs, allExistingRoles, allExistingSubcourses, allExistingExtCourses, allExistingUsers, + isStaffMode, mappingsProcessed); allUsersinCourses.addAll(allUsersInSubcourses); + + logger.info("Processed " + mappingsProcessed.get() + " entries"); } + logger.info("Disabling users"); // users who are part of courses but are not in the file anymore are eligible for disabling allUsersinCourses.removeAll(allUsersParsed); for (User user : allUsersinCourses) { @@ -201,13 +267,15 @@ } private Set createUsers(ExtServer extServer, Integer creatorId, Map users, - Map userIDs, Map>> existingRoles) + Map userIDs, Map allExistingUsers, + Map allExistingExtUsers) throws UserInfoValidationException, UserInfoFetchException { Set allUsersParsed = new HashSet<>(); + logger.info("Creating users"); for (Entry userEntry : users.entrySet()) { // email servers as login String login = userEntry.getKey(); - User user = userManagementService.getUserByLogin(login); + User user = allExistingUsers.get(login); if (user == null) { String salt = HashUtil.salt(); String password = HashUtil.sha256(RandomPasswordGenerator.nextPassword(10), salt); @@ -218,19 +286,24 @@ salt, firstName, ".", email); user = userMap.getUser(); + allExistingUsers.put(login, user); + allExistingExtUsers.put(login, userMap); + String message = "User created with login \"" + login + "\" and ID " + user.getUserId(); logger.info(message); logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, "SPEnrolment: " + message); } else { - ExtUserUseridMap userMap = integrationService.getExistingExtUserUseridMap(extServer, login); + ExtUserUseridMap userMap = allExistingExtUsers.get(login); if (userMap == null) { userMap = new ExtUserUseridMap(); userMap.setExtServer(extServer); userMap.setUser(user); userMap.setExtUsername(login); userManagementService.save(userMap); + allExistingExtUsers.put(login, userMap); + String message = "External user created for existing user with login \"" + login + "\" and ID " + user.getUserId(); logger.info(message); @@ -245,7 +318,6 @@ } // fill data for later usage - existingRoles.put(login, userManagementService.getRolesForUser(user.getUserId())); userIDs.put(login, user.getUserId()); // add user to a collection of all users in the parsed file allUsersParsed.add(user); @@ -254,37 +326,40 @@ return allUsersParsed; } - @SuppressWarnings("unchecked") private Organisation getCourse(String courseCode, String courseName, ExtServer extServer, Integer creatorId, - Organisation rootOrganisation) throws UserInfoValidationException { - Organisation course = null; - List organisations = userManagementService.findByProperty(Organisation.class, "code", courseCode); + Organisation rootOrganisation, Map allExistingOrganisations, + Map allExistingExtCourses) throws UserInfoValidationException { + Organisation course = allExistingOrganisations.get(courseCode); // create course - if (organisations.isEmpty()) { + if (course == null) { String name = courseName; ExtCourseClassMap extOrgMap = integrationService.createExtCourseClassMap(extServer, creatorId, name, name, rootOrganisation.getOrganisationId().toString(), false); course = extOrgMap.getOrganisation(); course.setCode(courseCode); userManagementService.save(course); + allExistingOrganisations.put(courseCode, course); + allExistingExtCourses.put(extOrgMap.getOrganisation().getOrganisationId(), extOrgMap); + String message = "Course created with code \"" + courseCode + "\" and name \"" + name + "\" and ID " + course.getOrganisationId(); logger.info(message); logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, "SPEnrolment: " + message); } else { - course = organisations.get(0); String name = course.getName(); - ExtCourseClassMap extOrgMap = integrationService.getExtCourseClassMap(extServer.getSid(), name); + ExtCourseClassMap extOrgMap = allExistingExtCourses.get(course.getOrganisationId()); if (extOrgMap == null) { extOrgMap = new ExtCourseClassMap(); extOrgMap.setCourseid(name); extOrgMap.setExtServer(extServer); extOrgMap.setOrganisation(course); userManagementService.save(extOrgMap); + allExistingExtCourses.put(course.getOrganisationId(), extOrgMap); + String message = "External course created for existing course with code \"" + courseCode + "\" and name \"" + name + "\" and ID " + course.getOrganisationId(); logger.info(message); @@ -298,48 +373,51 @@ @SuppressWarnings("unchecked") private Set assignUsers(Organisation course, Map>> mappings, ExtServer extServer, Integer creatorId, Set allUsersParsed, Map userIDs, - Map>> existingRoles, boolean isStaffMode) - throws UserInfoValidationException { + Map>> allExistingRoles, + Map> allExistingSubcourses, + Map allExistingExtCourses, Map allExistingUsers, + boolean isStaffMode, AtomicInteger mappingsProcessed) throws UserInfoValidationException { Set allUsersInSubcourses = new HashSet<>(); String courseCode = course.getCode(); // go through each subcourse for (Entry> subcourseEntry : mappings.get(courseCode).entrySet()) { - Organisation subcourse = null; String subcourseCode = subcourseEntry.getKey(); + ConcurrentMap existingSubcourses = allExistingSubcourses.get(courseCode); + Organisation subcourse = existingSubcourses == null ? null : existingSubcourses.get(subcourseCode); - Map queryParams = new HashMap<>(); - queryParams.put("code", subcourseCode); - queryParams.put("parentOrganisation.organisationId", course.getOrganisationId()); - List organisations = userManagementService.findByProperties(Organisation.class, queryParams); - // create subcourse - if (organisations.isEmpty()) { - + if (subcourse == null) { ExtCourseClassMap extSubOrgMap = integrationService.createExtCourseClassMap(extServer, creatorId, subcourseCode, subcourseCode, course.getOrganisationId().toString(), false); subcourse = extSubOrgMap.getOrganisation(); subcourse.setCode(subcourseCode); userManagementService.save(subcourse); + if (existingSubcourses == null) { + existingSubcourses = new ConcurrentHashMap<>(); + allExistingSubcourses.put(course.getCode(), existingSubcourses); + } + existingSubcourses.put(subcourse.getCode(), subcourse); + allExistingExtCourses.put(extSubOrgMap.getOrganisation().getOrganisationId(), extSubOrgMap); + String message = "Subcourse created with code and name \"" + courseCode + "\" and ID " + subcourse.getOrganisationId(); logger.info(message); logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, "SPEnrolment: " + message); } else { - subcourse = organisations.get(0); String name = subcourse.getName(); - ExtCourseClassMap extOrgMap = integrationService.getExtCourseClassMap(extServer.getSid(), name); + ExtCourseClassMap extOrgMap = allExistingExtCourses.get(subcourse.getOrganisationId()); if (extOrgMap == null) { extOrgMap = new ExtCourseClassMap(); extOrgMap.setCourseid(name); extOrgMap.setExtServer(extServer); extOrgMap.setOrganisation(subcourse); userManagementService.save(extOrgMap); - String message = "External subcourse created for existing subcourse with code \"" + courseCode - + "\" and name \"" + name + "\" and ID " + course.getOrganisationId(); + String message = "External subcourse created for existing subcourse with code \"" + subcourseCode + + "\" and name \"" + name + "\" and ID " + subcourse.getOrganisationId(); logger.info(message); logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, "SPEnrolment: " + message); @@ -356,6 +434,7 @@ // go through each user for (String login : subcourseEntry.getValue()) { + mappingsProcessed.incrementAndGet(); // check if the user is already a learner/staff member in the subcourse // if so, there is nothing to do @@ -376,7 +455,9 @@ } // the user is not a learner/staff member yet, so assign him the role and add him to lessons - Set existingSubcourseRoles = existingRoles.get(login).get(subcourseId); + Map> existingSubcoursesRoles = allExistingRoles.get(login); + Set existingSubcourseRoles = existingSubcoursesRoles == null ? null + : allExistingRoles.get(login).get(subcourseId); if (existingSubcourseRoles == null) { existingSubcourseRoles = new HashSet<>(); } @@ -386,7 +467,9 @@ } else { existingSubcourseRoles.add(Role.ROLE_LEARNER); } - userManagementService.setRolesForUserOrganisation(userId, subcourseId, existingSubcourseRoles); + User user = allExistingUsers.get(login); + userManagementService.setRolesForUserOrganisation(user, subcourse, + existingSubcourseRoles.stream().map(String::valueOf).collect(Collectors.toList()), false); for (Lesson lesson : lessonService.getLessonsByGroup(subcourseId)) { if (isStaffMode) { @@ -405,7 +488,7 @@ // user is a learner/staff member, but he should not; remove him role from subcourse and lessons for (User user : subcourseUsers) { - Map> existingSubcoursesRoles = existingRoles.get(user.getLogin()); + Map> existingSubcoursesRoles = allExistingRoles.get(user.getLogin()); Set existingSubcourseRoles = existingSubcoursesRoles == null ? null : existingSubcoursesRoles.get(subcourseId); if (existingSubcourseRoles != null) { @@ -439,122 +522,6 @@ return allUsersInSubcourses; } -// @SuppressWarnings("unchecked") -// private Set assignTeachers(Organisation course, List logins, ExtServer extServer, Integer creatorId, -// Set allUsersParsed, Map userIDs, -// Map>> existingRoles) throws UserInfoValidationException { -// // this is for detecting which users should be disabled -// Set allUsersInCourse = new HashSet<>(); -// -// Integer courseId = course.getOrganisationId(); -// -// // get existing teachers for given course -// Collection courseTeachers = userManagementService.getUsersFromOrganisationByRole(courseId, Role.MONITOR, -// true); -// // add users to set containing all users in any course which is processed -// allUsersInCourse.addAll(courseTeachers); -// -// // go through each user -// for (String login : logins) { -// // check if user is alread a teacher in this course -// boolean userAlreadyStaff = false; -// Integer userId = userIDs.get(login); -// User user = null; -// Iterator courseTeacherIterator = courseTeachers.iterator(); -// while (courseTeacherIterator.hasNext()) { -// User nextUser = courseTeacherIterator.next(); -// if (userId.equals(nextUser.getUserId())) { -// user = nextUser; -// // IMPORTANT: if we found a matching existing teacher, we get remove him from this collection -// // so after this loop he does not get removed from the course -// courseTeacherIterator.remove(); -// userAlreadyStaff = true; -// break; -// } -// } -// -// // if user is not a teacher, add him -// if (!userAlreadyStaff) { -// // the user is not a teacher in course yet, so assign him roles -// Set existingCourseRoles = existingRoles.get(login).get(courseId); -// if (existingCourseRoles == null) { -// existingCourseRoles = new HashSet<>(); -// } -// // we modify existing role collection, as he can be also a course admin and/or learner -// existingCourseRoles.add(Role.ROLE_AUTHOR); -// existingCourseRoles.add(Role.ROLE_MONITOR); -// userManagementService.setRolesForUserOrganisation(userId, courseId, existingCourseRoles); -// -// String message = "Teacher \"" + login + "\" added to course " + courseId; -// logger.info(message); -// logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, -// "SPEnrolment: " + message); -// } -// -// // now go through each subcourse and make sure the user is also a teacher there and in its lessons -// for (Organisation subcourse : course.getChildOrganisations()) { -// if (user == null) { -// user = (User) userManagementService.findById(User.class, userId); -// } -// Integer subcourseId = subcourse.getOrganisationId(); -// Set existingSubcourseRoles = userManagementService.getUserOrganisationRoles(subcourseId, login) -// .stream().collect(Collectors.mapping(r -> r.getRole().getRoleId(), Collectors.toSet())); -// userAlreadyStaff = existingSubcourseRoles.contains(Role.ROLE_MONITOR); -// if (!userAlreadyStaff) { -// // we modify existing role collection, as he can be also a learner -// existingSubcourseRoles.add(Role.ROLE_AUTHOR); -// existingSubcourseRoles.add(Role.ROLE_MONITOR); -// userManagementService.setRolesForUserOrganisation(userId, subcourseId, existingSubcourseRoles); -// -// for (Lesson lesson : lessonService.getLessonsByGroup(subcourseId)) { -// lessonService.addStaffMember(lesson.getLessonId(), userId); -// } -// -// String message = "Teacher \"" + login + "\" added to subcourse " + subcourseId + " and its lessons"; -// logger.info(message); -// logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, -// "SPEnrolment: " + message); -// } -// } -// } -// -// // user is a staff member, but he should not; remove all roles from course and lessons -// for (User user : courseTeachers) { -// Map> existingCoursesRoles = existingRoles.get(user.getLogin()); -// Set existingCourseRoles = existingCoursesRoles == null ? null : existingCoursesRoles.get(courseId); -// if (existingCourseRoles != null) { -// Integer userId = user.getUserId(); -// -// existingCourseRoles.remove(Role.ROLE_AUTHOR); -// existingCourseRoles.remove(Role.ROLE_MONITOR); -// userManagementService.setRolesForUserOrganisation(userId, courseId, existingCourseRoles); -// -// for (Organisation subcourse : course.getChildOrganisations()) { -// boolean isLearner = userManagementService.hasRoleInOrganisation(user, Role.ROLE_MONITOR, subcourse); -// Integer subcourseId = subcourse.getOrganisationId(); -// Set subcourseRoles = new HashSet<>(); -// if (isLearner) { -// // there are no course admins in subcourses, so either user looses all roles or he stays just a learner -// subcourseRoles.add(Role.ROLE_LEARNER); -// } -// userManagementService.setRolesForUserOrganisation(userId, subcourseId, subcourseRoles); -// -// for (Lesson lesson : lessonService.getLessonsByGroup(subcourseId)) { -// lessonService.addStaffMember(lesson.getLessonId(), userId); -// } -// } -// } -// -// String message = "Teacher \"" + user.getLogin() + "\" removed from course " + courseId -// + ", its subcourses and its lessons"; -// logger.info(message); -// logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, -// "SPEnrolment: " + message); -// } -// -// return allUsersInCourse; -// } - @Override public void init() throws ServletException { lessonService = (ILessonService) WebApplicationContextUtils Index: lams_common/src/java/org/lamsfoundation/lams/dao/IBaseDAO.java =================================================================== diff -u -r8a37658d37fa3da8260fe7806df498ae20a99f49 -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_common/src/java/org/lamsfoundation/lams/dao/IBaseDAO.java (.../IBaseDAO.java) (revision 8a37658d37fa3da8260fe7806df498ae20a99f49) +++ lams_common/src/java/org/lamsfoundation/lams/dao/IBaseDAO.java (.../IBaseDAO.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -221,6 +221,8 @@ */ public List findByProperty(Class clazz, String name, Object value); + public List findByPropertyValues(Class clazz, String name, Collection values); + /** * @param properties * a map of property names and values Index: lams_common/src/java/org/lamsfoundation/lams/dao/hibernate/LAMSBaseDAO.java =================================================================== diff -u -r8a37658d37fa3da8260fe7806df498ae20a99f49 -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_common/src/java/org/lamsfoundation/lams/dao/hibernate/LAMSBaseDAO.java (.../LAMSBaseDAO.java) (revision 8a37658d37fa3da8260fe7806df498ae20a99f49) +++ lams_common/src/java/org/lamsfoundation/lams/dao/hibernate/LAMSBaseDAO.java (.../LAMSBaseDAO.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -266,6 +266,15 @@ return doFind(queryString, value); } + @Override + public List findByPropertyValues(Class clazz, String name, Collection values) { + if (values == null || values.isEmpty()) { + return new ArrayList<>(); + } + String queryString = "FROM " + clazz.getCanonicalName() + " WHERE " + name + " IN (:param)"; + return getSession().createQuery(queryString, clazz).setParameterList("param", values).getResultList(); + } + /* * (non-Javadoc) * @@ -332,7 +341,7 @@ @Override public List searchByStringProperties(Class clazz, Map properties) { - Map p = new HashMap(); + Map p = new HashMap<>(); for (Map.Entry entry : properties.entrySet()) { p.put(entry.getKey(), entry.getValue()); } @@ -372,7 +381,7 @@ StringBuilder queryString = new StringBuilder(operation).append(clazzName).append(SPACE).append(objName) .append(WHERE); Field[] fields = obj.getClass().getDeclaredFields(); - List values = new ArrayList(); + List values = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { String name = fields[i].getName(); Method readMethod = getReadMethod(fields[i], name, obj.getClass()); Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/IOrganisationDAO.java =================================================================== diff -u -rebb598b9d631fa479aef19110dc7b8c2cce0575b -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/IOrganisationDAO.java (.../IOrganisationDAO.java) (revision ebb598b9d631fa479aef19110dc7b8c2cce0575b) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/IOrganisationDAO.java (.../IOrganisationDAO.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -20,9 +20,9 @@ * **************************************************************** */ - package org.lamsfoundation.lams.usermanagement.dao; +import java.util.Collection; import java.util.List; import org.lamsfoundation.lams.dao.IBaseDAO; @@ -80,14 +80,15 @@ */ int getCountCoursesByParentCourseAndTypeAndState(final Integer parentOrgId, final Integer typeId, final Integer stateId, String searchString); - + /** * Returns list of UserOrganisationCollapsed, indicating which sub-courses was collapsed by the given user. - * + * * @param parentOrganisationId * @param userId * @return */ List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, Integer userId); + List getOrganisationsByCodes(Collection codes); } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/hibernate/OrganisationDAO.java =================================================================== diff -u -rebb598b9d631fa479aef19110dc7b8c2cce0575b -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/hibernate/OrganisationDAO.java (.../OrganisationDAO.java) (revision ebb598b9d631fa479aef19110dc7b8c2cce0575b) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/dao/hibernate/OrganisationDAO.java (.../OrganisationDAO.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -20,10 +20,10 @@ * **************************************************************** */ - package org.lamsfoundation.lams.usermanagement.dao.hibernate; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.hibernate.Query; @@ -42,7 +42,6 @@ @Repository public class OrganisationDAO extends LAMSBaseDAO implements IOrganisationDAO { - private static final String GET_PAGED_COURSES = "SELECT o FROM Organisation o WHERE o.organisationType.organisationTypeId =:typeId " + "AND o.organisationState.organisationStateId =:stateId AND o.parentOrganisation.organisationId =:parentOrgId " + "AND (o.name LIKE CONCAT('%', :searchString, '%')) ORDER BY "; @@ -53,6 +52,8 @@ + " AND o.organisationState.organisationStateId =:stateId " + " AND (o.name LIKE CONCAT('%', :searchString, '%')) "; + private static final String GET_COURSES_BY_CODES = "FROM Organisation WHERE code IN (:codes)"; + @SuppressWarnings("unchecked") @Override public List getActiveCoursesByUser(Integer userId, boolean isSysadmin, int page, int size, @@ -64,12 +65,11 @@ + " AND (o.name LIKE CONCAT('%', :searchString, '%')) ORDER BY o.name"; final String GET_ACTIVE_COURSE_IDS_BY_USER = "SELECT uo.organisation.organisationId, uo.organisation.name" - + " FROM UserOrganisation uo " - + " WHERE uo.organisation.organisationType.organisationTypeId = " + OrganisationType.COURSE_TYPE - + " AND uo.organisation.organisationState.organisationStateId = " + OrganisationState.ACTIVE - + " AND uo.user.userId = :userId " - + " AND (uo.organisation.name LIKE CONCAT('%', :searchString, '%')) ORDER BY uo.organisation.name"; - + + " FROM UserOrganisation uo " + " WHERE uo.organisation.organisationType.organisationTypeId = " + + OrganisationType.COURSE_TYPE + " AND uo.organisation.organisationState.organisationStateId = " + + OrganisationState.ACTIVE + " AND uo.user.userId = :userId " + + " AND (uo.organisation.name LIKE CONCAT('%', :searchString, '%')) ORDER BY uo.organisation.name"; + String queryStr = isSysadmin ? GET_ALL_ACTIVE_COURSE_IDS : GET_ACTIVE_COURSE_IDS_BY_USER; Query query = getSession().createQuery(queryStr); // support for custom search from a toolbar @@ -81,8 +81,8 @@ query.setFirstResult(page * size); query.setMaxResults(size); List list = query.list(); - - List orgDtos = new ArrayList(); + + List orgDtos = new ArrayList<>(); if (list != null && list.size() > 0) { for (Object[] element : list) { @@ -97,22 +97,23 @@ return orgDtos; } - + @Override - public List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, Integer userId) { + public List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, + Integer userId) { final String GET_USER_ORGANISATION_COLLAPSED_BY_USER_AND_PARENT_ORGANISATION = "SELECT uoc FROM UserOrganisationCollapsed uoc " - + " WHERE uoc.organisation.organisationType.organisationTypeId = " + OrganisationType.CLASS_TYPE - + " AND uoc.organisation.organisationState.organisationStateId = " + OrganisationState.ACTIVE - + " AND uoc.organisation.parentOrganisation.organisationId = :organisationId " - + " AND uoc.user.userId = :userId "; - + + " WHERE uoc.organisation.organisationType.organisationTypeId = " + OrganisationType.CLASS_TYPE + + " AND uoc.organisation.organisationState.organisationStateId = " + OrganisationState.ACTIVE + + " AND uoc.organisation.parentOrganisation.organisationId = :organisationId " + + " AND uoc.user.userId = :userId "; + Query query = getSession().createQuery( GET_USER_ORGANISATION_COLLAPSED_BY_USER_AND_PARENT_ORGANISATION, UserOrganisationCollapsed.class); query.setInteger("organisationId", parentOrganisationId); query.setInteger("userId", userId); return query.list(); } - + @Override public int getCountActiveCoursesByUser(Integer userId, boolean isSysadmin, String searchString) { @@ -183,4 +184,10 @@ return ((Number) query.uniqueResult()).intValue(); } + + @Override + public List getOrganisationsByCodes(Collection codes) { + return getSession().createQuery(GET_COURSES_BY_CODES, Organisation.class).setParameter("codes", codes) + .getResultList(); + } } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java =================================================================== diff -u -rebb598b9d631fa479aef19110dc7b8c2cce0575b -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision ebb598b9d631fa479aef19110dc7b8c2cce0575b) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -111,6 +111,8 @@ */ List findByProperty(Class clazz, String name, Object value); + List findByPropertyValues(Class clazz, String name, Collection values); + /** * @param properties * a map of property names and values @@ -173,7 +175,7 @@ * @return true or false */ boolean isUserInRole(Integer userId, Integer orgId, String roleName); - + /** * @param organisationId * @return organisation by its id @@ -224,10 +226,10 @@ * @return a list of UserOrganisationRoles */ List getUserOrganisationRoles(Integer orgId, String login); - + /** * Returns list of UserOrganisationCollapsed, indicating which sub-courses was collapsed by the given user. - * + * * @param parentOrganisationId * @param userId * @return @@ -279,7 +281,7 @@ * @return UserOrganisation */ UserOrganisation getUserOrganisation(Integer userId, Integer orgId); - + /** * @param userId * @param orgId @@ -339,6 +341,18 @@ */ void setRolesForUserOrganisation(User user, Integer organisationId, List rolesList); + /** + * Set the roles for the specified user and organisation using the roleIds in rolesList. If userOrganisation + * exists, + * will also remove roles that are not in rolesList. + * + * @param checkGroupManagerRoles + * whether check if user is a group manager, he should also have other roles in organisation; can be + * false to avoid extra check if we know that user can not be a group manager + */ + void setRolesForUserOrganisation(User user, Organisation org, List rolesList, + boolean checkGroupManagerRoles); + void setRolesForUserOrganisation(Integer userId, Integer organisationId, Set roleIDList); /** @@ -410,6 +424,7 @@ void logPasswordChanged(User user, User modifiedBy); void logUserCreated(User user, User createdBy); + void logUserCreated(User user, UserDTO createdBy); Integer getCountUsers(); Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== diff -u -rebb598b9d631fa479aef19110dc7b8c2cce0575b -rc1af58895d976d53fba617a4a1eaafc071b8f169 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision ebb598b9d631fa479aef19110dc7b8c2cce0575b) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision c1af58895d976d53fba617a4a1eaafc071b8f169) @@ -223,6 +223,11 @@ } @Override + public List findByPropertyValues(Class clazz, String name, Collection values) { + return baseDAO.findByPropertyValues(clazz, name, values); + } + + @Override public List findByProperties(Class clazz, Map properties) { return baseDAO.findByProperties(clazz, properties); } @@ -306,7 +311,7 @@ } return true; } - + @Override public Organisation getOrganisationById(Integer organisationId) { return (Organisation) findById(Organisation.class, organisationId); @@ -342,8 +347,8 @@ return baseDAO.findByProperties(UserOrganisationRole.class, properties); } - @Override @SuppressWarnings("unchecked") + @Override public Map> getRolesForUser(Integer userId) { return ((List) findByProperty(UserOrganisation.class, "user.userId", userId)).stream() .collect(Collectors.toMap(userOrganisation -> userOrganisation.getOrganisation().getOrganisationId(), @@ -371,7 +376,7 @@ properties.put("organisation.parentOrganisation.organisationId", parentOrgId); return baseDAO.findByProperties(UserOrganisation.class, properties); } - + @Override public UserOrganisationCollapsed getUserOrganisationCollapsed(Integer userId, Integer orgId) { Map properties = new HashMap<>(); @@ -380,9 +385,10 @@ List results = baseDAO.findByProperties(UserOrganisationCollapsed.class, properties); return results.isEmpty() ? null : (UserOrganisationCollapsed) results.get(0); } - + @Override - public List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, Integer userId) { + public List getChildOrganisationsCollapsedByUser(Integer parentOrganisationId, + Integer userId) { return organisationDAO.getChildOrganisationsCollapsedByUser(parentOrganisationId, userId); } @@ -649,10 +655,12 @@ // access the org.UserOrganisations set // if org has come from the web layer. Organisation org = (Organisation) findById(Organisation.class, organisationId); - setRolesForUserOrganisation(user, org, rolesList); + setRolesForUserOrganisation(user, org, rolesList, true); } - private void setRolesForUserOrganisation(User user, Organisation org, List rolesList) { + @Override + public void setRolesForUserOrganisation(User user, Organisation org, List rolesList, + boolean checkGroupManagerRoles) { // The private version of setRolesForUserOrganisation can pass around // the org safely as we are within @@ -674,7 +682,7 @@ // course also if not already if (org.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE) && (getUserOrganisation(user.getUserId(), org.getParentOrganisation().getOrganisationId()) == null)) { - setRolesForUserOrganisation(user, org.getParentOrganisation(), rolesList); + setRolesForUserOrganisation(user, org.getParentOrganisation(), rolesList, checkGroupManagerRoles); } List rolesCopy = new ArrayList<>(); @@ -722,8 +730,11 @@ uo.setUserOrganisationRoles(uors); save(uo); } - // make sure group managers have monitor and learner in each subgroup - checkGroupManager(user, org); + + if (checkGroupManagerRoles) { + // make sure group managers have monitor and learner in each subgroup + checkGroupManager(user, org); + } } private void checkGroupManager(User user, Organisation org) {