diff --git a/.hgtags b/.hgtags index 800aedd6840643ddbcecccca6256bbc7e1b34906..59d373f6fabfe5864ea4198d76ffbc1334961cd7 100644 --- a/.hgtags +++ b/.hgtags @@ -173,3 +173,4 @@ bde4d49de3ec377802302debda91373537ee6dae OpenOLAT 11.0.9 3aa428100d40cd4481df316b4feccbb6ab3414a1 OpenOLAT 11.1.2 18b14d1153dd44d638f7362d1d02b4ebeb77d996 OpenOLAT 11.1.2 dced52763f304b670e173b302a2bc4509e5345b8 OpenOLAT 11.2.0 +efc1aac6f9600cd8617e1c2a2b846fa833875861 OpenOLAT 11.2.1 diff --git a/src/main/java/org/olat/basesecurity/AuthHelper.java b/src/main/java/org/olat/basesecurity/AuthHelper.java index 7da43afab34f0a334cd2000f5b1d39954bc67932..f6708fee6aa58e5a06d05587e0a251ae957ee9b0 100644 --- a/src/main/java/org/olat/basesecurity/AuthHelper.java +++ b/src/main/java/org/olat/basesecurity/AuthHelper.java @@ -253,7 +253,7 @@ public class AuthHelper { } else { //fxdiff FXOLAT-151: add eventually the identity to the security group if(!groupDao.hasRole(invitation.getBaseGroup(), identity, GroupRoles.invitee.name())) { - groupDao.addMembership(invitation.getBaseGroup(), identity, GroupRoles.invitee.name()); + groupDao.addMembershipTwoWay(invitation.getBaseGroup(), identity, GroupRoles.invitee.name()); DBFactory.getInstance().commit(); } diff --git a/src/main/java/org/olat/basesecurity/manager/GroupDAO.java b/src/main/java/org/olat/basesecurity/manager/GroupDAO.java index 1b9c05e1026c4707c2c02248ba2cb115b4696bd6..a0c8a5624fdcee58cb6169a00b5b8e53252889bf 100644 --- a/src/main/java/org/olat/basesecurity/manager/GroupDAO.java +++ b/src/main/java/org/olat/basesecurity/manager/GroupDAO.java @@ -80,7 +80,11 @@ public class GroupDAO { return group; } - public GroupMembership addMembership(Group group, Identity identity, String role) { + /** + * Add a membership to the group, in the set of the group too which can be + * reloaded. + */ + public GroupMembership addMembershipTwoWay(Group group, Identity identity, String role) { GroupMembershipImpl membership = new GroupMembershipImpl(); membership.setCreationDate(new Date()); membership.setLastModified(new Date()); @@ -98,6 +102,19 @@ public class GroupDAO { return membership; } + /** + * Create a membership without updating the set in the group. + */ + public void addMembershipOneWay(Group group, Identity identity, String role) { + GroupMembershipImpl membership = new GroupMembershipImpl(); + membership.setCreationDate(new Date()); + membership.setLastModified(new Date()); + membership.setGroup(group); + membership.setIdentity(identity); + membership.setRole(role); + dbInstance.getCurrentEntityManager().persist(membership); + } + public int removeMemberships(Group group) { EntityManager em = dbInstance.getCurrentEntityManager(); List<GroupMembership> memberships = em.createNamedQuery("membershipsByGroup", GroupMembership.class) diff --git a/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java b/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java index 885616b5ab6bd0e990afbe5e618fe24b7a77c175..c9a0de90f03127399f296584cd542a9e0bce68f3 100644 --- a/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java +++ b/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java @@ -59,6 +59,7 @@ import org.olat.core.id.Persistable; @NamedQuery(name="membershipsByGroupAndIdentity", query="select membership from bgroupmember as membership where membership.group.key=:groupKey and membership.identity.key=:identityKey"), @NamedQuery(name="membershipsByGroupIdentityAndRole", query="select membership from bgroupmember as membership where membership.group.key=:groupKey and membership.identity.key=:identityKey and membership.role=:role"), @NamedQuery(name="countMembersByGroup", query="select count(membership.key) from bgroupmember as membership where membership.group.key=:groupKey"), + @NamedQuery(name="countMembersByGroupAndRole", query="select count(membership.key) from bgroupmember as membership where membership.group.key=:groupKey and membership.role=:role"), @NamedQuery(name="membersByGroupAndRole", query="select distinct membership.identity from bgroupmember as membership where membership.group.key=:groupKey and membership.role=:role"), @NamedQuery(name="hasRoleByGroupIdentityAndRole", query="select count(membership.key) from bgroupmember as membership where membership.group.key=:groupKey and membership.identity.key=:identityKey and membership.role=:role") }) diff --git a/src/main/java/org/olat/course/assessment/AssessmentManager.java b/src/main/java/org/olat/course/assessment/AssessmentManager.java index 9605ad14c3f4eb4bef1127f495eb1e0db333642e..5050f2820d0c5b470a9829b9fa62d89af55979d4 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentManager.java +++ b/src/main/java/org/olat/course/assessment/AssessmentManager.java @@ -163,17 +163,21 @@ public interface AssessmentManager { * @return */ public Date getScoreLastModifiedDate(CourseNode courseNode, Identity identity); - + /** * Save the users achieved ScoreEvaluation for this node. If there is already a score property available, it will be - * overwritten with the new value <p> - * - * @param courseNode - * @param identity - * @param assessedIdentity - * @param scoreEvaluation + * overwritten with the new value. + * + * @param courseNode The course element + * @param identity The identity who make the changes + * @param assessedIdentity The assessed identity + * @param scoreEvaluation The updated score evaluation + * @param userCourseEnvironment The user course env. of the assessed identity + * @param incrementUserAttempts */ - public void saveScoreEvaluation(AssessableCourseNode courseNode, Identity identity, Identity assessedIdentity, ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnvironment, boolean incrementUserAttempts); + + public void saveScoreEvaluation(AssessableCourseNode courseNode, Identity identity, Identity assessedIdentity, + ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnvironment, boolean incrementUserAttempts); /** * Provides an OLATResourceable for locking (of score/passed etc.) purposes (if doInSync is called on score/passed data) diff --git a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java index 28d14c6ab48a3f24a660f7086df779b038b02eff..4f791e0137c4be092c68bf1aecb53514a14dabab 100644 --- a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java @@ -329,7 +329,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { } if(course.getCourseConfig().isAutomaticCertificationEnabled()) { - CourseNode rootNode = userCourseEnv.getCourseEnvironment().getRunStructure().getRootNode(); + CourseNode rootNode = courseEnv.getRunStructure().getRootNode(); ScoreEvaluation rootEval = scoreAccounting.evalCourseNode((AssessableCourseNode)rootNode); if(rootEval != null && rootEval.getPassed() != null && rootEval.getPassed().booleanValue() && certificatesManager.isCertificationAllowed(assessedIdentity, cgm.getCourseEntry())) { @@ -388,7 +388,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { AssessmentEntry nodeAssessment = assessmentService .loadAssessmentEntry(identity, cgm.getCourseEntry(), courseNode.getIdent()); - return nodeAssessment == null ? INTEGER_ZERO : nodeAssessment.getAttempts(); + return nodeAssessment == null || nodeAssessment.getAttempts() == null ? INTEGER_ZERO : nodeAssessment.getAttempts(); } @Override diff --git a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java index 04658b2f496c9857b38bf4aa4fdd2a327944f957..453898ab2b81bd38fbb051c7e042cba454038936 100644 --- a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java +++ b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java @@ -559,21 +559,24 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode implements * @param userCourseEnv * @param assessedIdentity */ - public void updateScoreEvaluation(UserCourseEnvironment userCourseEnv, Identity assessedIdentity) { + public void updateScoreEvaluation(Identity identity, UserCourseEnvironment assessedUserCourseEnv, Identity assessedIdentity) { ModuleConfiguration config = getModuleConfiguration(); Boolean sum = (Boolean)config.get(CheckListCourseNode.CONFIG_KEY_PASSED_SUM_CHECKBOX); Float cutValue = (Float)config.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE); Float maxScore = (Float)config.get(MSCourseNode.CONFIG_KEY_SCORE_MAX); + Boolean manualCorrection = (Boolean)config.get(CheckListCourseNode.CONFIG_KEY_PASSED_MANUAL_CORRECTION); if(cutValue != null) { - doUpdateAssessment(cutValue, maxScore, userCourseEnv, assessedIdentity); - } else if(sum != null) { - doUpdateAssessmentBySum(userCourseEnv, assessedIdentity); + doUpdateAssessment(cutValue, maxScore, identity, assessedUserCourseEnv, assessedIdentity); + } else if(sum != null && sum.booleanValue()) { + doUpdateAssessmentBySum(identity, assessedUserCourseEnv, assessedIdentity); + } else if(manualCorrection != null && manualCorrection.booleanValue()) { + doUpdateManualAssessment(maxScore, identity, assessedUserCourseEnv, assessedIdentity); } } - private void doUpdateAssessment(Float cutValue, Float maxScore, UserCourseEnvironment userCourseEnv, Identity assessedIdentity) { + private void doUpdateAssessment(Float cutValue, Float maxScore, Identity identity, UserCourseEnvironment assessedUserCourseEnv, Identity assessedIdentity) { OLATResourceable courseOres = OresHelper - .createOLATResourceableInstance("CourseModule", userCourseEnv.getCourseEnvironment().getCourseResourceableId()); + .createOLATResourceableInstance("CourseModule", assessedUserCourseEnv.getCourseEnvironment().getCourseResourceableId()); CheckboxManager checkboxManager = CoreSpringFactory.getImpl(CheckboxManager.class); float score = checkboxManager.calculateScore(assessedIdentity, courseOres, getIdent()); @@ -588,14 +591,13 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode implements } ScoreEvaluation sceval = new ScoreEvaluation(new Float(score), passed); - AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); - am.saveScoreEvaluation(this, mySelf, assessedIdentity, sceval, userCourseEnv, false); + AssessmentManager am = assessedUserCourseEnv.getCourseEnvironment().getAssessmentManager(); + am.saveScoreEvaluation(this, identity, assessedIdentity, sceval, assessedUserCourseEnv, false); } - private void doUpdateAssessmentBySum(UserCourseEnvironment userCourseEnv, Identity assessedIdentity) { + private void doUpdateAssessmentBySum(Identity identity, UserCourseEnvironment assessedUserCourseEnv, Identity assessedIdentity) { OLATResourceable courseOres = OresHelper - .createOLATResourceableInstance("CourseModule", userCourseEnv.getCourseEnvironment().getCourseResourceableId()); + .createOLATResourceableInstance("CourseModule", assessedUserCourseEnv.getCourseEnvironment().getCourseResourceableId()); ModuleConfiguration config = getModuleConfiguration(); CheckboxManager checkboxManager = CoreSpringFactory.getImpl(CheckboxManager.class); @@ -619,9 +621,24 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode implements ScoreEvaluation sceval = new ScoreEvaluation(score, new Boolean(passed)); - AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); - am.saveScoreEvaluation(this, mySelf, assessedIdentity, sceval, userCourseEnv, false); + AssessmentManager am = assessedUserCourseEnv.getCourseEnvironment().getAssessmentManager(); + am.saveScoreEvaluation(this, identity, assessedIdentity, sceval, assessedUserCourseEnv, false); + } + + private void doUpdateManualAssessment(Float maxScore, Identity identity, UserCourseEnvironment assessedUserCourseEnv, Identity assessedIdentity) { + OLATResourceable courseOres = OresHelper + .createOLATResourceableInstance("CourseModule", assessedUserCourseEnv.getCourseEnvironment().getCourseResourceableId()); + + CheckboxManager checkboxManager = CoreSpringFactory.getImpl(CheckboxManager.class); + float score = checkboxManager.calculateScore(assessedIdentity, courseOres, getIdent()); + if(maxScore != null && maxScore.floatValue() < score) { + score = maxScore.floatValue(); + } + + AssessmentManager am = assessedUserCourseEnv.getCourseEnvironment().getAssessmentManager(); + ScoreEvaluation currentEval = getUserScoreEvaluation(am.getAssessmentEntry(this, assessedIdentity)); + ScoreEvaluation sceval = new ScoreEvaluation(new Float(score), currentEval.getPassed()); + am.saveScoreEvaluation(this, identity, assessedIdentity, sceval, assessedUserCourseEnv, false); } @Override diff --git a/src/main/java/org/olat/course/nodes/cl/ui/AssessedIdentityCheckListController.java b/src/main/java/org/olat/course/nodes/cl/ui/AssessedIdentityCheckListController.java index cb3c3f100d9c5713bbabede70ee84bcbf40992d6..fa630349f8ccef208d520e2f7c09431ecbc70c8e 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/AssessedIdentityCheckListController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/AssessedIdentityCheckListController.java @@ -284,7 +284,7 @@ public class AssessedIdentityCheckListController extends FormBasicController { } checkboxManager.check(courseOres, courseNode.getIdent(), batchElements); - courseNode.updateScoreEvaluation(assessedUserCourseEnv, assessedIdentity); + courseNode.updateScoreEvaluation(getIdentity(), assessedUserCourseEnv, assessedIdentity); } private void doUpdateCheck(CheckboxWrapper wrapper, boolean check) { diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java index 8f730913d27f9d59a0834ae151209d53954b7a1d..b000cdfd3b6b7773ab22d5d36273cbd4c7259192 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java @@ -566,10 +566,10 @@ public class CheckListAssessmentController extends FormBasicController implement DBFactory.getInstance().commit(); ICourse course = CourseFactory.loadCourse(courseOres); - List<Identity> identities = securityManager.loadIdentityByKeys(assessedIdentityToUpdate); - for(Identity identity:identities) { - UserCourseEnvironment assessedUserCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(identity, course); - courseNode.updateScoreEvaluation(assessedUserCourseEnv, identity); + List<Identity> assessedIdentities = securityManager.loadIdentityByKeys(assessedIdentityToUpdate); + for(Identity assessedIdentity:assessedIdentities) { + UserCourseEnvironment assessedUserCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(assessedIdentity, course); + courseNode.updateScoreEvaluation(getIdentity(), assessedUserCourseEnv, assessedIdentity); } } diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckListRunController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckListRunController.java index 4c201c55d33c6ddf69d3dd84c08c6d0e7023594e..660165698cab9e0bba24b05f8e0abcafe483f5ca 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckListRunController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckListRunController.java @@ -284,7 +284,7 @@ public class CheckListRunController extends FormBasicController implements Contr //make sure all results is on the database before calculating some scores //manager commit already DBFactory.getInstance().commit(); - courseNode.updateScoreEvaluation(userCourseEnv, getIdentity()); + courseNode.updateScoreEvaluation(getIdentity(), userCourseEnv, getIdentity()); Checkbox checkbox = wrapper.getCheckbox(); logUpdateCheck(checkbox.getCheckboxId(), checkbox.getTitle()); diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java index fad631cc2725dfb84e1e3fe7e1b1e0802a0b15cb..208d65a756a51f298d42340326bf846696635973 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java @@ -380,10 +380,10 @@ public class CheckboxAssessmentController extends FormBasicController { DBFactory.getInstance().commit(); ICourse course = CourseFactory.loadCourse(courseOres); - List<Identity> identities = securityManager.loadIdentityByKeys(assessedIdentityToUpdate); - for(Identity identity:identities) { - UserCourseEnvironment userCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(identity, course); - courseNode.updateScoreEvaluation(userCourseEnv, identity); + List<Identity> assessedIdentities = securityManager.loadIdentityByKeys(assessedIdentityToUpdate); + for(Identity assessedIdentity:assessedIdentities) { + UserCourseEnvironment assessedUserCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(assessedIdentity, course); + courseNode.updateScoreEvaluation(getIdentity(), assessedUserCourseEnv, assessedIdentity); } } diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_content/run.html b/src/main/java/org/olat/course/nodes/cl/ui/_content/run.html index a9f5cb760d3dfeea8820fc9a5f81829a58eedda6..0222802b04b7393987156303590f4a0a06409587 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/_content/run.html +++ b/src/main/java/org/olat/course/nodes/cl/ui/_content/run.html @@ -53,7 +53,7 @@ </div> #end -#if ($comment) +#if ($r.isNotEmpty($comment)) <div class="panel panel-default o_comment"> <div class="panel-heading" data-toggle="collapse" data-target="#collapseComment"> <h4 class="panel-title"> diff --git a/src/main/java/org/olat/course/nodes/iq/IQRunController.java b/src/main/java/org/olat/course/nodes/iq/IQRunController.java index 989f4eedc62ecf32fabd7f427bde826e83b1ffa9..7823c0f44bebc74ae63650eb58a2b0994f1a7ded 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQRunController.java +++ b/src/main/java/org/olat/course/nodes/iq/IQRunController.java @@ -610,7 +610,7 @@ public class IQRunController extends BasicController implements GenericEventList myContent.contextPut("passed", assessmentEntry.getPassed()); StringBuilder comment = Formatter.stripTabsAndReturns(assessmentEntry.getComment()); myContent.contextPut("comment", StringHelper.xssScan(comment)); - myContent.contextPut("attempts", assessmentEntry.getAttempts()); + myContent.contextPut("attempts", assessmentEntry.getAttempts() == null ? 0 : assessmentEntry.getAttempts()); } } diff --git a/src/main/java/org/olat/course/site/CourseSiteContextEntryControllerCreator.java b/src/main/java/org/olat/course/site/CourseSiteContextEntryControllerCreator.java index 74fac109c15b958fdab788fd5559e92450c87895..ce2fae5ff3ce05b30d1b25ef5583e0a7ac1a9048 100644 --- a/src/main/java/org/olat/course/site/CourseSiteContextEntryControllerCreator.java +++ b/src/main/java/org/olat/course/site/CourseSiteContextEntryControllerCreator.java @@ -32,6 +32,7 @@ import org.olat.core.gui.control.navigation.SiteDefinition; import org.olat.core.gui.control.navigation.SiteDefinitions; import org.olat.core.gui.translator.Translator; import org.olat.core.id.OLATResourceable; +import org.olat.core.id.Roles; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.ContextEntryControllerCreator; @@ -94,6 +95,13 @@ public class CourseSiteContextEntryControllerCreator extends DefaultContextEntry } UserSession usess = ureq.getUserSession(); + if(re.getAccess() == RepositoryEntry.DELETED) { + Roles roles = usess.getRoles(); + if(!roles.isInstitutionalResourceManager() && !roles.isOLATAdmin()) { + return messageController(ureq, wControl, "repositoryentry.deleted"); + } + } + if(usess.isInAssessmentModeProcess() && !usess.matchLockResource(re.getOlatResource())) { return null; } diff --git a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java index ad1ba63e55014a6554b6b821fdde907ef7e77c8c..47134e92332a49dfb844197e0968e1c5eff1b4a5 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java @@ -141,7 +141,7 @@ public class BusinessGroupDAO { Group group = groupDao.createGroup(); businessgroup.setBaseGroup(group); if (creator != null) { - groupDao.addMembership(group, creator, GroupRoles.coach.name()); + groupDao.addMembershipTwoWay(group, creator, GroupRoles.coach.name()); } EntityManager em = dbInstance.getCurrentEntityManager(); diff --git a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java index 5ca80d6859dedc04d5767ad2962da7150ce2eaf6..0693b16d4a5a0707b9933a448e6be64eb144d0d0 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java @@ -39,6 +39,8 @@ import org.olat.basesecurity.model.IdentityRefImpl; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.course.assessment.manager.AssessmentModeDAO; import org.olat.group.BusinessGroup; @@ -61,6 +63,8 @@ import org.springframework.stereotype.Service; */ @Service("businessGroupRelationDao") public class BusinessGroupRelationDAO { + + private static final OLog log = Tracing.createLoggerFor(BusinessGroupRelationDAO.class); @Autowired private DB dbInstance; @@ -75,9 +79,18 @@ public class BusinessGroupRelationDAO { repositoryEntryRelationDao.createRelation(((BusinessGroupImpl)group).getBaseGroup(), re); } - public void addRole(Identity identity, BusinessGroupRef businessGroup, String role) { - Group group = getGroup(businessGroup); - groupDao.addMembership(group, identity, role); + public void addRole(Identity identity, BusinessGroup businessGroup, String role) { + Group group = null; + try { + group = businessGroup.getBaseGroup(); + if(group == null) { + group = getGroup(businessGroup); + } + } catch(Exception e) { + log.warn("", e); + group = getGroup(businessGroup); + } + groupDao.addMembershipOneWay(group, identity, role); } public boolean removeRole(Identity identity, BusinessGroupRef businessGroup, String role) { @@ -195,6 +208,21 @@ public class BusinessGroupRelationDAO { return count == null ? 0 : count.intValue(); } + /** + * Count the number of participants. + * + * @param group + * @return + */ + public int countEnrollment(BusinessGroup group) { + Number count = dbInstance.getCurrentEntityManager() + .createNamedQuery("countMembersByGroupAndRole", Number.class) + .setParameter("groupKey", group.getBaseGroup().getKey()) + .setParameter("role", GroupRoles.participant.name()) + .getSingleResult(); + return count == null ? 0 : count.intValue(); + } + /** * Return the number of coaches with author rights. * @param group diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java index 5cef78b7fa898f45193f066841ff8a2a3ced3281..fd798171b2e4243aaabb09df9c681751ddba67c0 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java @@ -1385,11 +1385,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD reservationDao.deleteReservation(reservation); } } else if (reloadedGroup.getMaxParticipants() != null) { - int participantsCounter = businessGroupRelationDAO.countRoles(reloadedGroup, GroupRoles.participant.name()); + int participantsCounter = businessGroupRelationDAO.countEnrollment(reloadedGroup); int reservations = reservationDao.countReservations(reloadedGroup.getResource()); log.info("doEnroll - participantsCounter: " + participantsCounter + ", reservations: " + reservations + " maxParticipants: " + reloadedGroup.getMaxParticipants().intValue(), identity.getName()); - if (reservation == null && (participantsCounter + reservations) >= reloadedGroup.getMaxParticipants().intValue()) { + if ((participantsCounter + reservations) >= reloadedGroup.getMaxParticipants().intValue()) { // already full, show error and updated choose page again if (reloadedGroup.getWaitingListEnabled().booleanValue()) { addToWaitingList(ureqIdentity, identity, reloadedGroup, mailing, events); diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java index e130e859b6652d0fa0e40d9a1052d3fa8eadf2c7..93e1cf36966c697150ef8941b0bf85065d45cd46 100644 --- a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java +++ b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import org.apache.commons.lang.StringEscapeUtils; import org.cyberneko.html.parsers.SAXParser; import org.olat.core.CoreSpringFactory; import org.olat.core.helpers.Settings; @@ -631,6 +632,8 @@ public class QTI12To21Converter { if(!trimmedText.startsWith("<p") && !trimmedText.startsWith("<div")) { text = "<p>" + trimmedText + "</p>"; } + } else { + text = StringEscapeUtils.unescapeHtml(text); } } return text; diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java index e39ce15e4e95ac1a45bb109f54f86d1e243052ff..4324f1ba8f8f957acc28d56dc5cd1804a5cbfb73 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java +++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java @@ -173,7 +173,7 @@ public class PortfolioServiceImpl implements PortfolioService { public Binder createNewBinder(String title, String summary, String imagePath, Identity owner) { BinderImpl portfolio = binderDao.createAndPersist(title, summary, imagePath, null); if(owner != null) { - groupDao.addMembership(portfolio.getBaseGroup(), owner, PortfolioRoles.owner.name()); + groupDao.addMembershipTwoWay(portfolio.getBaseGroup(), owner, PortfolioRoles.owner.name()); } return portfolio; } @@ -188,7 +188,7 @@ public class PortfolioServiceImpl implements PortfolioService { public void createAndPersistBinderTemplate(Identity owner, RepositoryEntry entry, Locale locale) { BinderImpl binder = binderDao.createAndPersist(entry.getDisplayname(), entry.getDescription(), null, entry); if(owner != null) { - groupDao.addMembership(binder.getBaseGroup(), owner, PortfolioRoles.owner.name()); + groupDao.addMembershipTwoWay(binder.getBaseGroup(), owner, PortfolioRoles.owner.name()); } //add section Translator pt = Util.createPackageTranslator(PortfolioHomeController.class, locale); @@ -564,7 +564,7 @@ public class PortfolioServiceImpl implements PortfolioService { public Binder assignBinder(Identity owner, BinderRef templateBinder, RepositoryEntry entry, String subIdent, Date deadline) { BinderImpl reloadedTemplate = (BinderImpl)binderDao.loadByKey(templateBinder.getKey()); BinderImpl binder = binderDao.createCopy(reloadedTemplate, entry, subIdent); - groupDao.addMembership(binder.getBaseGroup(), owner, PortfolioRoles.owner.name()); + groupDao.addMembershipTwoWay(binder.getBaseGroup(), owner, PortfolioRoles.owner.name()); return binder; } @@ -635,7 +635,7 @@ public class PortfolioServiceImpl implements PortfolioService { public void addAccessRights(PortfolioElement element, Identity identity, PortfolioRoles role) { Group baseGroup = element.getBaseGroup(); if(!groupDao.hasRole(baseGroup, identity, role.name())) { - groupDao.addMembership(baseGroup, identity, role.name()); + groupDao.addMembershipTwoWay(baseGroup, identity, role.name()); } } @@ -647,7 +647,7 @@ public class PortfolioServiceImpl implements PortfolioService { if(change.isAdd()) { if(!groupDao.hasRole(baseGroup, identity, change.getRole().name())) { Group group = getGroup(change.getElement()); - groupDao.addMembership(group, identity, change.getRole().name()); + groupDao.addMembershipOneWay(group, identity, change.getRole().name()); } } else { if(groupDao.hasRole(baseGroup, identity, change.getRole().name())) { @@ -839,7 +839,7 @@ public class PortfolioServiceImpl implements PortfolioService { ((SectionImpl)reloadedSection).setSectionStatus(SectionStatus.inProgress); } Page page = pageDao.createAndPersist(title, summary, imagePath, align, editable, reloadedSection, null); - groupDao.addMembership(page.getBaseGroup(), owner, PortfolioRoles.owner.name()); + groupDao.addMembershipTwoWay(page.getBaseGroup(), owner, PortfolioRoles.owner.name()); return page; } diff --git a/src/main/java/org/olat/modules/reminder/manager/ReminderDAO.java b/src/main/java/org/olat/modules/reminder/manager/ReminderDAO.java index 905868dc0d9d5994f7676405096326a0d7f92eac..d25dcc173c99e8625def453c216cad4e36f4bd57 100644 --- a/src/main/java/org/olat/modules/reminder/manager/ReminderDAO.java +++ b/src/main/java/org/olat/modules/reminder/manager/ReminderDAO.java @@ -128,17 +128,18 @@ public class ReminderDAO { } /** - * Get all reminders of active repository entries. + * Get all reminders of active repository entries (status must be + * open and not "softly" deleted). * * @param startDate - * @return + * @return A list of reminders */ public List<Reminder> getReminders(Date startDate) { StringBuilder sb = new StringBuilder(); sb.append("select rem from reminder rem") .append(" inner join rem.entry entry") .append(" where (rem.startDate is null or rem.startDate<=:startDate)") - .append(" and entry.statusCode=0"); + .append(" and entry.statusCode=0 and entry.access>").append(RepositoryEntry.DELETED); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Reminder.class) @@ -146,6 +147,12 @@ public class ReminderDAO { .getResultList(); } + /** + * Get all reminders without restrictions. + * + * @param entry + * @return A list of remidners + */ public List<Reminder> getReminders(RepositoryEntryRef entry) { String q = "select rem from reminder rem inner join rem.entry entry where entry.key=:entryKey"; return dbInstance.getCurrentEntityManager() diff --git a/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java b/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java index 61d160033d3df55ae53d835dc7805a7ec45fa09a..dd332c2435104114039a434737a0d328ecb5e583 100644 --- a/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java +++ b/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java @@ -225,7 +225,7 @@ public class EPPolicyManager { Group secGroup = groupDao.createGroup(); relation = createBaseRelation(map, secGroup, EPMapPolicy.Type.user.name(), policy.getFrom(), policy.getTo()); for(Identity identity:policy.getIdentities()) { - groupDao.addMembership(secGroup, identity, GroupRoles.participant.name()); + groupDao.addMembershipTwoWay(secGroup, identity, GroupRoles.participant.name()); } } else { EPStructureElementToGroupRelation currentPolicy = reusePolicyInSession(relation, map); @@ -248,7 +248,7 @@ public class EPPolicyManager { groupDao.removeMembership(secGroup, currentMember); } for(Identity newMember:newMembers) { - groupDao.addMembership(secGroup, newMember, GroupRoles.participant.name()); + groupDao.addMembershipTwoWay(secGroup, newMember, GroupRoles.participant.name()); } } return relation; diff --git a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java index c3102bf0e1b4e4c590ed70da457ce7520e087438..6c8067aed974e808bcc7c834e8655e6eca0f1987 100755 --- a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java +++ b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java @@ -1829,7 +1829,7 @@ public class EPStructureManager { Group group = repositoryEntyRelationDao.getDefaultGroup(entry); if(group == null) { group = groupDao.createGroup(); - groupDao.addMembership(group, identity, GroupRoles.owner.name()); + groupDao.addMembershipTwoWay(group, identity, GroupRoles.owner.name()); } EPStructureElementToGroupRelation relation = createBaseRelation(el, group); @@ -1885,7 +1885,7 @@ public class EPStructureManager { relation.setCreationDate(new Date()); relation.setGroup(ownerGroup); relation.setStructureElement(element); - groupDao.addMembership(ownerGroup, author, GroupRoles.owner.name()); + groupDao.addMembershipTwoWay(ownerGroup, author, GroupRoles.owner.name()); return relation; } diff --git a/src/main/java/org/olat/portfolio/manager/InvitationDAO.java b/src/main/java/org/olat/portfolio/manager/InvitationDAO.java index c104acd26e25d091547806bdbc7e7ad23b90f794..b279768530d411721342b9f19e5fe71e6a9b0640 100644 --- a/src/main/java/org/olat/portfolio/manager/InvitationDAO.java +++ b/src/main/java/org/olat/portfolio/manager/InvitationDAO.java @@ -110,7 +110,7 @@ public class InvitationDAO { User user = userManager.createUser(invitation.getFirstName(), invitation.getLastName(), invitation.getMail()); user.getPreferences().setLanguage(locale.toString()); Identity invitee = securityManager.createAndPersistIdentityAndUser(tempUsername, null, user, null, null); - groupDao.addMembership(invitation.getBaseGroup(), invitee, GroupRoles.invitee.name()); + groupDao.addMembershipTwoWay(invitation.getBaseGroup(), invitee, GroupRoles.invitee.name()); return invitee; } @@ -129,7 +129,7 @@ public class InvitationDAO { invitee = securityManager.createAndPersistIdentityAndUser(tempUsername, null, user, null, null, null); } // add invitee to the security group of that portfolio element - groupDao.addMembership(group, invitee, GroupRoles.invitee.name()); + groupDao.addMembershipTwoWay(group, invitee, GroupRoles.invitee.name()); return invitee; } diff --git a/src/main/java/org/olat/repository/RepositoryEntryStatus.java b/src/main/java/org/olat/repository/RepositoryEntryStatus.java index ab875bf55247399ab9962e981daf8958bd334138..5497c5a719224ad1e645ba18c3d18bce3ab10980 100644 --- a/src/main/java/org/olat/repository/RepositoryEntryStatus.java +++ b/src/main/java/org/olat/repository/RepositoryEntryStatus.java @@ -35,6 +35,9 @@ package org.olat.repository; public class RepositoryEntryStatus { public static final int REPOSITORY_STATUS_OPEN = 0; + /** + * Correspond to the "freeze" status + */ public static final int REPOSITORY_STATUS_CLOSED = 2; public static final int REPOSITORY_STATUS_UNPUBLISHED = 4; diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index 7be0516accf22ac92e39827f362b91a3ba155d08..7fac13043046c3b4282e68cad0eaa5dc70060d40 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -418,6 +418,7 @@ repository.admin.leave.label=Standardeinstellung f\u00FCr neue Kurse repository.admin.leave.title=Verlassen von Kursen zulassen repository.admin.lifecycle.title=Automatische Verwaltung des Lebenszyklus repository.admin.title=Repository Einstellungen +repositoryentry.deleted=Diese Ressource wurde gel\u00F6scht und ist nicht mehr verf\u00FCgbar. repositoryentry.not.existing=Diese Ressource ist nicht mehr verf\u00FCgbar. resource.editor=Editor resource.error.test.xml=Die Lernressource konnte nicht hinzugef\u00FCgt werden. Die qti.xml-Datei konnte nicht geparst werden. diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties index 0172982a94c71546805e9dd567a183045b307b79..a8eb6ee4f0908cf4b3fe3354eb8dd7546825386d 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -415,6 +415,7 @@ repository.admin.leave.label=Standard setting for new courses repository.admin.leave.title=Allow leaving courses repository.admin.lifecycle.title=Automatic Life-cycle management repository.admin.title=Repository settings +repositoryentry.deleted=This resource was deleted and is no longer available. repositoryentry.not.existing=This resource is no longer available. resource.editor=Editor resource.error.test.xml=Learning resource could not be added. The qti.xml file could not be parsed. diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java index 85e1eccab580d6e7697f1759cf4f600aa845d441..459a6519ba81662e0c57fa59f0c0b6d57ab7c793 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java +++ b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java @@ -168,7 +168,7 @@ public class RepositoryEntryRelationDAO { public void addRole(Identity identity, RepositoryEntryRef re, String role) { Group group = getDefaultGroup(re); - groupDao.addMembership(group, identity, role); + groupDao.addMembershipOneWay(group, identity, role); } public int removeRole(IdentityRef identity, RepositoryEntryRef re, String role) { diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java index 90f6e7600bf0a4483ae44ed859258d586e7a2a82..bfc6933b253efa78f889a1ea850f05fcb8c6276f 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java +++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java @@ -215,7 +215,7 @@ public class RepositoryServiceImpl implements RepositoryService { re.setGroups(rels); if(initialAuthor != null) { - groupDao.addMembership(group, initialAuthor, GroupRoles.owner.name()); + groupDao.addMembershipTwoWay(group, initialAuthor, GroupRoles.owner.name()); } dbInstance.getCurrentEntityManager().persist(re); diff --git a/src/main/java/org/olat/repository/ui/author/AccessRenderer.java b/src/main/java/org/olat/repository/ui/author/AccessRenderer.java index 83d4f47d9c023197ae64b06b2d532688dd867ff2..1c5130e99753f20585c28961274f36d0b96d557e 100644 --- a/src/main/java/org/olat/repository/ui/author/AccessRenderer.java +++ b/src/main/java/org/olat/repository/ui/author/AccessRenderer.java @@ -49,12 +49,13 @@ public class AccessRenderer implements FlexiCellRenderer { int row, FlexiTableComponent source, URLBuilder ubu, Translator translator) { if(val instanceof RepositoryEntryLight) { RepositoryEntryLight re = (RepositoryEntryLight)val; - if(re.isMembersOnly()) { + if(re.getAccess() == RepositoryEntry.DELETED) { + sb.append(translator.translate("table.header.access.deleted")); + } else if(re.isMembersOnly()) { sb.append(translator.translate("table.header.access.membersonly")); } else { switch (re.getAccess()) { case RepositoryEntry.DELETED: { - sb.append(translator.translate("table.header.access.deleted")); break; } diff --git a/src/main/java/org/olat/repository/ui/author/AuthorDeletedListController.java b/src/main/java/org/olat/repository/ui/author/AuthorDeletedListController.java index f4b5717ae3f00509467f45924bb4537ec5948ae4..291fd03fe6bb05d799ffcc4ac80a05dfac7859b2 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthorDeletedListController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthorDeletedListController.java @@ -121,6 +121,11 @@ public class AuthorDeletedListController extends AuthorListController { reloadRows(); } cleanUp(); + } else if(dToolsCtrl == source) { + if(event == Event.DONE_EVENT) { + toolsCalloutCtrl.deactivate(); + cleanUp(); + } } super.event(ureq, source, event); } diff --git a/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java b/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java index 7da1b5fa3b1506d5251577bce0534f35d528f050..5febf6910c3cff3ccf1f5c66fa1100ed458d3bc8 100644 --- a/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java +++ b/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java @@ -61,18 +61,26 @@ public class GroupDAOTest extends OlatTestCase { public void createGroupMembership() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-"); Group group = groupDao.createGroup(); - GroupMembership membership = groupDao.addMembership(group, id, "author"); + GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author"); dbInstance.commit(); Assert.assertNotNull(membership); } + @Test + public void createGroupMembership_oneWay() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-"); + Group group = groupDao.createGroup(); + groupDao.addMembershipOneWay(group, id, "author"); + dbInstance.commit(); + } + @Test public void createGroupMembership_v2() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-"); Group group = groupDao.createGroup(); - GroupMembership membership = groupDao.addMembership(group, id, "author"); + GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author"); dbInstance.commit(); Assert.assertNotNull(membership); @@ -86,11 +94,25 @@ public class GroupDAOTest extends OlatTestCase { Assert.assertEquals(1, members.size()); } + @Test + public void createGroupMembership_oneWay_v2() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-"); + Group group = groupDao.createGroup(); + groupDao.addMembershipOneWay(group, id, "author"); + dbInstance.commitAndCloseSession(); + + GroupImpl loadedGroup = (GroupImpl)groupDao.loadGroup(group.getKey()); + Assert.assertNotNull(loadedGroup); + Set<GroupMembership> members = loadedGroup.getMembers(); + Assert.assertNotNull(members); + Assert.assertEquals(1, members.size()); + } + @Test public void getMemberships() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-"); Group group = groupDao.createGroup(); - GroupMembership membership = groupDao.addMembership(group, id, "author"); + GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author"); dbInstance.commit(); Assert.assertNotNull(membership); @@ -101,13 +123,25 @@ public class GroupDAOTest extends OlatTestCase { Assert.assertNotNull(members); Assert.assertEquals(1, members.size()); } + + @Test + public void getMemberships_oneWay() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-"); + Group group = groupDao.createGroup(); + groupDao.addMembershipOneWay(group, id, "author"); + dbInstance.commitAndCloseSession(); + + List<GroupMembership> members = groupDao.getMemberships(group, "author"); + Assert.assertNotNull(members); + Assert.assertEquals(1, members.size()); + } @Test public void hasRole() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-2-"); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-2b-"); Group group = groupDao.createGroup(); - GroupMembership membership = groupDao.addMembership(group, id, "author"); + GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author"); dbInstance.commit(); Assert.assertNotNull(membership); @@ -126,7 +160,7 @@ public class GroupDAOTest extends OlatTestCase { public void getMembers() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-3-"); Group group = groupDao.createGroup(); - GroupMembership membership = groupDao.addMembership(group, id, "author"); + GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author"); dbInstance.commit(); Assert.assertNotNull(membership); @@ -143,9 +177,9 @@ public class GroupDAOTest extends OlatTestCase { Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-5-"); Identity id3 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-6-"); Group group = groupDao.createGroup(); - GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot"); - GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot"); - GroupMembership membership3 = groupDao.addMembership(group, id3, "copilot"); + GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot"); + GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot"); + GroupMembership membership3 = groupDao.addMembershipTwoWay(group, id3, "copilot"); dbInstance.commit(); Assert.assertNotNull(membership1); @@ -162,8 +196,8 @@ public class GroupDAOTest extends OlatTestCase { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-7-"); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-8-"); Group group = groupDao.createGroup(); - GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot"); - GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot"); + GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot"); + GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot"); Assert.assertNotNull(membership1); Assert.assertNotNull(membership2); dbInstance.commitAndCloseSession(); @@ -189,9 +223,9 @@ public class GroupDAOTest extends OlatTestCase { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-7-"); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-8-"); Group group = groupDao.createGroup(); - GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot"); - GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot"); - GroupMembership membership2alt = groupDao.addMembership(group, id2, "commander"); + GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot"); + GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot"); + GroupMembership membership2alt = groupDao.addMembershipTwoWay(group, id2, "commander"); Assert.assertNotNull(membership1); Assert.assertNotNull(membership2); Assert.assertNotNull(membership2alt); @@ -226,8 +260,8 @@ public class GroupDAOTest extends OlatTestCase { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-7-"); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-8-"); Group group = groupDao.createGroup(); - GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot"); - GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot"); + GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot"); + GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot"); Assert.assertNotNull(membership1); Assert.assertNotNull(membership2); dbInstance.commitAndCloseSession(); @@ -250,8 +284,8 @@ public class GroupDAOTest extends OlatTestCase { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-12-"); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-13-"); Group group = groupDao.createGroup(); - GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot"); - GroupMembership membership2 = groupDao.addMembership(group, id2, "copilot"); + GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot"); + GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "copilot"); Assert.assertNotNull(membership1); Assert.assertNotNull(membership2); dbInstance.commitAndCloseSession(); @@ -278,14 +312,14 @@ public class GroupDAOTest extends OlatTestCase { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-9-"); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-10-"); Group group1 = groupDao.createGroup(); - GroupMembership membership1 = groupDao.addMembership(group1, id1, "pilot"); - GroupMembership membership2 = groupDao.addMembership(group1, id2, "pilot"); + GroupMembership membership1 = groupDao.addMembershipTwoWay(group1, id1, "pilot"); + GroupMembership membership2 = groupDao.addMembershipTwoWay(group1, id2, "pilot"); Assert.assertNotNull(membership1); Assert.assertNotNull(membership2); dbInstance.commitAndCloseSession(); Group group2 = groupDao.createGroup(); - GroupMembership membership3 = groupDao.addMembership(group2, id1, "passanger"); - GroupMembership membership4 = groupDao.addMembership(group2, id2, "passanger"); + GroupMembership membership3 = groupDao.addMembershipTwoWay(group2, id1, "passanger"); + GroupMembership membership4 = groupDao.addMembershipTwoWay(group2, id2, "passanger"); Assert.assertNotNull(membership3); Assert.assertNotNull(membership4); dbInstance.commitAndCloseSession(); @@ -359,7 +393,7 @@ public class GroupDAOTest extends OlatTestCase { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("grant-1-"); Group group = groupDao.createGroup(); String role = "hasGrant-role"; - groupDao.addMembership(group, id, role); + groupDao.addMembershipTwoWay(group, id, role); OLATResource resource = JunitTestHelper.createRandomResource(); groupDao.addGrant(group, role, "hasGrant-perm", resource); dbInstance.commitAndCloseSession(); @@ -373,7 +407,7 @@ public class GroupDAOTest extends OlatTestCase { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("grant-1-"); Group group = groupDao.createGroup(); String role = "getPermissions-role"; - groupDao.addMembership(group, id, role); + groupDao.addMembershipTwoWay(group, id, role); OLATResource resource = JunitTestHelper.createRandomResource(); groupDao.addGrant(group, role, "getPermissions-perm", resource); dbInstance.commitAndCloseSession(); @@ -389,9 +423,9 @@ public class GroupDAOTest extends OlatTestCase { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("grant-1-"); Group group = groupDao.createGroup(); String role1 = "getPermissions-role-1"; - groupDao.addMembership(group, id, role1); + groupDao.addMembershipTwoWay(group, id, role1); String role2 = "getPermissions-role-2"; - groupDao.addMembership(group, id, role2); + groupDao.addMembershipTwoWay(group, id, role2); OLATResource resource = JunitTestHelper.createRandomResource(); groupDao.addGrant(group, role1, "getPermissions-perm-1", resource); groupDao.addGrant(group, role2, "getPermissions-perm-2", resource); @@ -408,8 +442,8 @@ public class GroupDAOTest extends OlatTestCase { public void addRemoveGrant() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("addremove-1-"); Group group = groupDao.createGroup(); - groupDao.addMembership(group, id, "addremove-1"); - groupDao.addMembership(group, id, "addremove-2"); + groupDao.addMembershipTwoWay(group, id, "addremove-1"); + groupDao.addMembershipTwoWay(group, id, "addremove-2"); OLATResource resource = JunitTestHelper.createRandomResource(); groupDao.addGrant(group, "addremove-1", "addremove-1-perm", resource); groupDao.addGrant(group, "addremove-2", "addremove-2-perm", resource); @@ -436,8 +470,8 @@ public class GroupDAOTest extends OlatTestCase { public void addRemoveGrants() { Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("addremove-1-"); Group group = groupDao.createGroup(); - groupDao.addMembership(group, id, "addremove-1"); - groupDao.addMembership(group, id, "addremove-2"); + groupDao.addMembershipTwoWay(group, id, "addremove-1"); + groupDao.addMembershipTwoWay(group, id, "addremove-2"); OLATResource resource = JunitTestHelper.createRandomResource(); groupDao.addGrant(group, "addremove-1", "addremove-1-perm", resource); groupDao.addGrant(group, "addremove-1", "addremove-11-perm", resource); diff --git a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java index 0bc285744fa416f59ae1febdad118144687059ae..9e46d1b9a0a3eb4178c9a427a867ae757c91500d 100644 --- a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java +++ b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java @@ -33,12 +33,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Random; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.GroupRoles; @@ -58,6 +60,11 @@ import org.olat.core.id.context.BusinessControl; import org.olat.core.id.context.ContextEntry; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; +import org.olat.core.logging.activity.OlatResourceableType; +import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; +import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller; +import org.olat.core.util.SessionInfo; +import org.olat.core.util.UserSession; import org.olat.core.util.Util; import org.olat.course.CourseFactory; import org.olat.course.CourseModule; @@ -75,6 +82,7 @@ import org.olat.resource.OLATResource; import org.olat.resource.OLATResourceManager; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; +import org.olat.util.logging.activity.LoggingResourceable; import org.springframework.beans.factory.annotation.Autowired; /** @@ -249,23 +257,30 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win @Test public void testConcurrentEnrollmentWithWaitingList() { - List<Identity> ids = new ArrayList<Identity>(30); - for(int i=0; i<30; i++) { + int NUM_OF_USERS = 30; + List<Identity> ids = new ArrayList<Identity>(NUM_OF_USERS); + for(int i=0; i<NUM_OF_USERS; i++) { Identity id = JunitTestHelper.createAndPersistIdentityAsUser("enroll-a-" + i + "-" + UUID.randomUUID().toString()); ids.add(id); } ENCourseNode enNode = new ENCourseNode(); - OLATResource resource = resourceManager.createOLATResourceInstance(CourseModule.class); - RepositoryEntry addedEntry = repositoryService.create("Ayanami", "-", "Enrollment test course 2", "A JUnit course", resource); + + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("enroller"); + RepositoryEntry addedEntry = JunitTestHelper.deployBasicCourse(author); CourseEnvironment cenv = CourseFactory.createCourse(addedEntry, "Test-Enroll", "Test", "Test enrollment with concurrent users").getCourseEnvironment(); BusinessGroup group = businessGroupService.createBusinessGroup(id1, "Enrollment", "Enroll", new Integer(1), new Integer(10), true, false, null); Assert.assertNotNull(group); dbInstance.commitAndCloseSession(); final CountDownLatch doneSignal = new CountDownLatch(ids.size()); + EnrollThread[] threads = new EnrollThread[NUM_OF_USERS]; + int t = 0; for(Identity id:ids) { - EnrollThread thread = new EnrollThread(id, group, enNode, cenv, doneSignal); + threads[t++] = new EnrollThread(id, addedEntry, group, enNode, cenv, doneSignal); + } + + for(EnrollThread thread:threads) { thread.start(); } @@ -275,6 +290,8 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win } catch (InterruptedException e) { fail("" + e.getMessage()); } + + dbInstance.commitAndCloseSession(); List<Identity> enrolledIds = businessGroupService.getMembers(group, GroupRoles.participant.name()); Assert.assertNotNull(enrolledIds); @@ -284,17 +301,91 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win Assert.assertNotNull(waitingIds); Assert.assertEquals(ids.size() - 10, waitingIds.size()); } + + + @Test @Ignore + public void testConcurrentEnrollmentWithWaitingList_big() { + List<Identity> ids = new ArrayList<Identity>(100); + for(int i=0; i<100; i++) { + Identity id = JunitTestHelper.createAndPersistIdentityAsUser("enroll-a-" + i + "-" + UUID.randomUUID().toString()); + ids.add(id); + } + + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("enroller"); + RepositoryEntry addedEntry = JunitTestHelper.deployBasicCourse(author); + + ENCourseNode enNode1 = new ENCourseNode(); + ENCourseNode enNode2 = new ENCourseNode(); + ENCourseNode enNode3 = new ENCourseNode(); + ENCourseNode enNode4 = new ENCourseNode(); + ENCourseNode enNode5 = new ENCourseNode(); + + CourseEnvironment cenv = CourseFactory.loadCourse(addedEntry).getCourseEnvironment(); + BusinessGroup group1 = businessGroupService.createBusinessGroup(author, "Enrollment 1", "Enroll 1", new Integer(1), new Integer(8), true, true, addedEntry); + BusinessGroup group2 = businessGroupService.createBusinessGroup(author, "Enrollment 2", "Enroll 2", new Integer(1), new Integer(10), true, true, addedEntry); + BusinessGroup group3 = businessGroupService.createBusinessGroup(author, "Enrollment 3", "Enroll 3", new Integer(1), new Integer(4), true, true, addedEntry); + BusinessGroup group4 = businessGroupService.createBusinessGroup(author, "Enrollment 4", "Enroll 4", new Integer(1), new Integer(10), true, true, addedEntry); + BusinessGroup group5 = businessGroupService.createBusinessGroup(author, "Enrollment 5", "Enroll 5", new Integer(1), new Integer(9), true, true, addedEntry); + dbInstance.commitAndCloseSession(); + + EnrollThread[] threads = new EnrollThread[100]; + + final CountDownLatch doneSignal = new CountDownLatch(ids.size()); + int t = 0; + for(int i=0; i<30; i++) { + threads[t++] = new EnrollThread(ids.get(i), addedEntry, group1, enNode1, cenv, doneSignal); + } + for(int i=30; i<50; i++) { + threads[t++] = new EnrollThread(ids.get(i), addedEntry, group2, enNode2, cenv, doneSignal); + } + for(int i=50; i<70; i++) { + threads[t++] = new EnrollThread(ids.get(i), addedEntry, group3, enNode3, cenv, doneSignal); + } + for(int i=70; i<90; i++) { + threads[t++] = new EnrollThread(ids.get(i), addedEntry, group4, enNode4, cenv, doneSignal); + } + for(int i=90; i<100; i++) { + threads[t++] = new EnrollThread(ids.get(i), addedEntry, group5, enNode5, cenv, doneSignal); + } + + for(EnrollThread thread:threads) { + thread.start(); + } + + try { + boolean interrupt = doneSignal.await(360, TimeUnit.SECONDS); + assertTrue("Test takes too long (more than 10s)", interrupt); + } catch (InterruptedException e) { + fail("" + e.getMessage()); + } + + dbInstance.commitAndCloseSession(); + + List<Identity> enrolled_1_Ids = businessGroupService.getMembers(group1, GroupRoles.participant.name()); + Assert.assertEquals(8, enrolled_1_Ids.size()); + List<Identity> enrolled_2_Ids = businessGroupService.getMembers(group2, GroupRoles.participant.name()); + Assert.assertEquals(10, enrolled_2_Ids.size()); + List<Identity> enrolled_3_Ids = businessGroupService.getMembers(group3, GroupRoles.participant.name()); + Assert.assertEquals(4, enrolled_3_Ids.size()); + List<Identity> enrolled_4_Ids = businessGroupService.getMembers(group4, GroupRoles.participant.name()); + Assert.assertEquals(10, enrolled_4_Ids.size()); + List<Identity> enrolled_5_Ids = businessGroupService.getMembers(group5, GroupRoles.participant.name()); + Assert.assertEquals(9, enrolled_5_Ids.size()); + } private class EnrollThread extends Thread { private final ENCourseNode enNode; private final Identity identity; private final CourseEnvironment cenv; private final BusinessGroup group; + private final RepositoryEntry courseEntry; private final CountDownLatch doneSignal; - public EnrollThread(Identity identity, BusinessGroup group, ENCourseNode enNode, CourseEnvironment cenv, CountDownLatch doneSignal) { + public EnrollThread(Identity identity, RepositoryEntry courseEntry, BusinessGroup group, + ENCourseNode enNode, CourseEnvironment cenv, CountDownLatch doneSignal) { this.enNode = enNode; this.group = group; + this.courseEntry = courseEntry; this.identity = identity; this.cenv = cenv; this.doneSignal = doneSignal; @@ -303,19 +394,30 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win @Override public void run() { try { - sleep(10); + UserSession session = new UserSession(); + session.setIdentity(identity); + session.setSessionInfo(new SessionInfo(identity.getKey(), identity.getName())); + ThreadLocalUserActivityLoggerInstaller.initUserActivityLogger(session); + IdentityEnvironment ienv = new IdentityEnvironment(); ienv.setIdentity(identity); UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv); CoursePropertyManager coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager(); CourseGroupManager courseGroupManager = userCourseEnv.getCourseEnvironment().getCourseGroupManager(); + ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(courseEntry.getOlatResource(), OlatResourceableType.course)); + ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(enNode)); + ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(group)); + + sleep(Math.round(new Random().nextDouble() * 100l)); enrollmentManager.doEnroll(identity, JunitTestHelper.getUserRoles(), group, enNode, coursePropertyManager, EnrollmentManagerConcurrentTest.this /*WindowControl mock*/, testTranslator, new ArrayList<Long>()/*enrollableGroupNames*/, new ArrayList<Long>()/*enrollableAreaNames*/, courseGroupManager); - DBFactory.getInstance().commitAndCloseSession(); + DBFactory.getInstance().commit(); } catch (Exception e) { log.error("", e); } finally { + ThreadLocalUserActivityLoggerInstaller.resetUserActivityLogger(); + DBFactory.getInstance().commitAndCloseSession(); doneSignal.countDown(); } } diff --git a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java index 879d8c41cdf5ad7a174dd39f38d68d653b16d1e5..5a695ccd9bb4db274e2a51af87ec9cdc54ff4c37 100644 --- a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java +++ b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java @@ -93,7 +93,7 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase { dbInstance.commitAndCloseSession(); Group group = ((BusinessGroupImpl)businessGroup).getBaseGroup(); - groupDao.addMembership(group, coach, "coach"); + groupDao.addMembershipTwoWay(group, coach, "coach"); dbInstance.commitAndCloseSession(); List<String> roles = businessGroupRelationDao.getRoles(coach, businessGroup); @@ -582,6 +582,36 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase { Assert.assertEquals(1, numOfAuthors); } + @Test + public void countRoles() { + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("auth-" + UUID.randomUUID().toString()); + Identity test = JunitTestHelper.createAndPersistIdentityAsRndUser("not-auth"); + BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false); + businessGroupRelationDao.addRole(author, group, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(test, group, GroupRoles.coach.name()); + dbInstance.commitAndCloseSession(); + + int numOfCoachs = businessGroupRelationDao.countRoles(group, GroupRoles.coach.name()); + Assert.assertEquals(2, numOfCoachs); + int numOfParticipants = businessGroupRelationDao.countRoles(group, GroupRoles.participant.name()); + Assert.assertEquals(0, numOfParticipants); + } + + @Test + public void countEnrollment() { + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("auth-" + UUID.randomUUID().toString()); + Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("not-auth"); + Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("not-auth"); + BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false); + businessGroupRelationDao.addRole(author, group, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(participant1, group, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(participant2, group, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + int numOfParticipants = businessGroupRelationDao.countEnrollment(group); + Assert.assertEquals(2, numOfParticipants); + } + @Test public void loadForUpdate() { BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false); diff --git a/src/test/java/org/olat/modules/reminder/manager/ReminderDAOTest.java b/src/test/java/org/olat/modules/reminder/manager/ReminderDAOTest.java index 9b676a38ede5797f4677067d96b04253200c42c9..38e9d318919e5d8dd2447310b12a12b0ba756600 100644 --- a/src/test/java/org/olat/modules/reminder/manager/ReminderDAOTest.java +++ b/src/test/java/org/olat/modules/reminder/manager/ReminderDAOTest.java @@ -35,6 +35,7 @@ import org.olat.modules.reminder.model.ReminderImpl; import org.olat.modules.reminder.model.ReminderInfos; import org.olat.modules.reminder.model.SentReminderImpl; import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryService; import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; @@ -53,6 +54,8 @@ public class ReminderDAOTest extends OlatTestCase { @Autowired private ReminderDAO reminderDao; @Autowired + private RepositoryService repositoryService; + @Autowired private RepositoryEntryRelationDAO repositoryEntryRelationDao; @Test @@ -140,6 +143,34 @@ public class ReminderDAOTest extends OlatTestCase { } Assert.assertTrue(found); } + + @Test + public void getReminders_repositoryEntry_softDeleted() { + //create and reminder and an identity + Identity creator = JunitTestHelper.createAndPersistIdentityAsRndUser("creator-rem-12"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + Reminder reminder = reminderDao.createReminder(entry, creator); + reminder.setConfiguration("<rules></rules>"); + reminder.setDescription("Reminder - 12"); + reminder.setEmailBody("Hello, I'm deleted"); + Reminder savedReminder = reminderDao.save(reminder); + Assert.assertNotNull(savedReminder); + dbInstance.commitAndCloseSession(); + + //check that we found the reminder + List<Reminder> loadedReminders = reminderDao.getReminders(new Date()); + Assert.assertNotNull(loadedReminders); + Assert.assertTrue(loadedReminders.contains(savedReminder)); + + // delete the resource + repositoryService.deleteSoftly(entry, creator, false); + dbInstance.commitAndCloseSession(); + + // check we don't found the reminder + List<Reminder> reloadedReminders = reminderDao.getReminders(new Date()); + Assert.assertNotNull(reloadedReminders); + Assert.assertFalse(reloadedReminders.contains(savedReminder)); + } @Test public void getReminders_repositoryEntry() {