diff --git a/src/main/java/org/olat/admin/user/tools/UserToolCategory.java b/src/main/java/org/olat/admin/user/tools/UserToolCategory.java index 1dd168483f6a33992d0b29285e6fbd6432fd5424..d12a5d7436750d696ba374a5416b561581484403 100644 --- a/src/main/java/org/olat/admin/user/tools/UserToolCategory.java +++ b/src/main/java/org/olat/admin/user/tools/UserToolCategory.java @@ -1,5 +1,30 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ package org.olat.admin.user.tools; +/** + * + * Initial date: 28.10.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ public enum UserToolCategory { search, personal, diff --git a/src/main/java/org/olat/admin/user/tools/UserToolsModule.java b/src/main/java/org/olat/admin/user/tools/UserToolsModule.java index dfc698d28d756911205db9c773736566f78cdbed..ae2c823ed5deca5d089cd8cf683cfb30dbc95443 100644 --- a/src/main/java/org/olat/admin/user/tools/UserToolsModule.java +++ b/src/main/java/org/olat/admin/user/tools/UserToolsModule.java @@ -29,8 +29,10 @@ import org.olat.core.extensions.ExtManager; import org.olat.core.extensions.Extension; import org.olat.core.extensions.ExtensionElement; import org.olat.core.gui.UserRequest; +import org.olat.core.gui.WindowManager; import org.olat.core.util.StringHelper; import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.prefs.Preferences; import org.olat.home.HomeMainController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -76,6 +78,39 @@ public class UserToolsModule extends AbstractSpringModule { init(); } + public String getUserTools(Preferences prefs) { + String selectedToolV2s = (String)prefs.get(WindowManager.class, "user-tools-v2"); + if(!StringHelper.containsNonWhitespace(selectedToolV2s)) { + String selectedTools = (String)prefs.get(WindowManager.class, "user-tools"); + if(StringHelper.containsNonWhitespace(selectedTools)) { + //upgrade + + StringBuilder selectedToolSb = new StringBuilder(selectedTools); + String[] newPresets = new String[]{ + "org.olat.home.HomeMainController:org.olat.gui.control.PrintUserToolExtension", + "org.olat.home.HomeMainController:org.olat.gui.control.HelpUserToolExtension", + "org.olat.home.HomeMainController:org.olat.instantMessaging.ui.ImpressumMainController" + }; + + for(String newPreset:newPresets) { + if(selectedToolSb.indexOf(newPreset) < 0) { + if(selectedToolSb.length() > 0) selectedToolSb.append(","); + selectedToolSb.append(newPreset); + } + } + prefs.put(WindowManager.class, "user-tools-v2", selectedToolSb.toString()); + prefs.save(); + selectedToolV2s = selectedToolSb.toString(); + } + } + return selectedToolV2s; + } + + public void setUserTools(Preferences prefs, String settings) { + prefs.put(WindowManager.class, "user-tools-v2", settings); + prefs.save(); + } + public List<UserToolExtension> getUserToolExtensions(UserRequest ureq) { List<UserToolExtension> tools = new ArrayList<>(); if(!isUserToolsDisabled()) { diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java index f4dc7b9a63d89f1fe5c0b954ad1fcf5df69a1b53..d4842207400798eb1d3ce24dfe033978d1c74a90 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java @@ -358,7 +358,6 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { */ @Override public Roles getRoles(Identity identity) { - boolean isGuestOnly = false; boolean isInvitee = false; @@ -382,9 +381,9 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { public List<String> getRolesAsString(Identity identity) { StringBuilder sb = new StringBuilder(); sb.append("select ngroup.groupName from ").append(NamedGroupImpl.class.getName()).append(" as ngroup ") - .append(" inner join ngroup.securityGroup sgi ") .append(" where exists (") - .append(" select sgmsi from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as sgmsi where sgmsi.identity.key=:identityKey and sgmsi.securityGroup=sgi") + .append(" select sgmsi from ").append(SecurityGroupMembershipImpl.class.getName()) + .append(" as sgmsi where sgmsi.identity.key=:identityKey and sgmsi.securityGroup=ngroup.securityGroup") .append(" )"); return dbInstance.getCurrentEntityManager() diff --git a/src/main/java/org/olat/course/member/MembersOverviewController.java b/src/main/java/org/olat/course/member/MembersOverviewController.java index 0382a56d327d440aa64b63bdda78a9485ae35fbb..92f6bd6baabf7703b2729c17715be2c90c4c197e 100644 --- a/src/main/java/org/olat/course/member/MembersOverviewController.java +++ b/src/main/java/org/olat/course/member/MembersOverviewController.java @@ -267,8 +267,8 @@ public class MembersOverviewController extends BasicController implements Activa Step start = new ImportMember_1b_ChooseMemberStep(ureq, repoEntry, null); StepRunnerCallback finish = new StepRunnerCallback() { @Override - public Step execute(UserRequest ureq, WindowControl wControl, StepsRunContext runContext) { - addMembers(ureq, runContext); + public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) { + addMembers(uureq, runContext); return StepsMainRunController.DONE_MODIFIED; } }; @@ -285,8 +285,8 @@ public class MembersOverviewController extends BasicController implements Activa Step start = new ImportMember_1a_LoginListStep(ureq, repoEntry, null); StepRunnerCallback finish = new StepRunnerCallback() { @Override - public Step execute(UserRequest ureq, WindowControl wControl, StepsRunContext runContext) { - addMembers(ureq, runContext); + public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) { + addMembers(uureq, runContext); if(runContext.containsKey("notFounds")) { showWarning("user.notfound", runContext.get("notFounds").toString()); } diff --git a/src/main/java/org/olat/group/BusinessGroup.java b/src/main/java/org/olat/group/BusinessGroup.java index 83b1688f5b3be6c1ebcaa8f466c8a22ddee2ba4b..878b94587cefbab1ca21aa3c01d2ae15a75d3a00 100644 --- a/src/main/java/org/olat/group/BusinessGroup.java +++ b/src/main/java/org/olat/group/BusinessGroup.java @@ -144,6 +144,10 @@ public interface BusinessGroup extends BusinessGroupShort, Persistable, CreateIn public boolean isDownloadMembersLists(); public void setDownloadMembersLists(boolean downloadMembersLists); + + public boolean isAllowToLeave(); + + public void setAllowToLeave(boolean allow); /** * @return the maximal number of participants diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml b/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml index 24b508e92c083c9ab0c3f2413b2fdfb83964b155..aa5ad79eaca56414561de157fdb11bea4aad1342 100644 --- a/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml +++ b/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml @@ -39,6 +39,7 @@ <property name="waitingListVisibleIntern" column="waitingintern" unique="false" not-null="true" type="boolean"/> <property name="waitingListVisiblePublic" column="waitingpublic" unique="false" not-null="true" type="boolean"/> <property name="downloadMembersLists" column="downloadmembers" unique="false" not-null="true" type="boolean"/> + <property name="allowToLeave" column="allowtoleave" unique="false" not-null="true" type="boolean"/> <property name="name" type="string" column="groupname" unique="false" length="255" index="gp_name_idx"/> <property name="description" type="string" column="descr" length="16777210" not-null="false"/> diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.java b/src/main/java/org/olat/group/BusinessGroupImpl.java index 93b70379b1899991df5e5c29b3aad51fdd7ff5ea..4b0b1040f37c3999153461b1b161ceaac575283c 100644 --- a/src/main/java/org/olat/group/BusinessGroupImpl.java +++ b/src/main/java/org/olat/group/BusinessGroupImpl.java @@ -69,6 +69,7 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup private boolean participantsVisiblePublic; private boolean waitingListVisiblePublic; private boolean downloadMembersLists; + private boolean allowToLeave; /** * constructs an unitialised BusinessGroup, use setXXX for setting attributes @@ -205,6 +206,16 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup this.downloadMembersLists = visible; } + @Override + public boolean isAllowToLeave() { + return allowToLeave; + } + + @Override + public void setAllowToLeave(boolean allow) { + this.allowToLeave = allow; + } + public OLATResource getResource() { return resource; } diff --git a/src/main/java/org/olat/group/BusinessGroupModule.java b/src/main/java/org/olat/group/BusinessGroupModule.java index f1e63c278bce2bcec24d464c6624db64e0228f6e..95d27f3c85284551f42c0d54c063449e99c0c2db 100644 --- a/src/main/java/org/olat/group/BusinessGroupModule.java +++ b/src/main/java/org/olat/group/BusinessGroupModule.java @@ -20,13 +20,16 @@ package org.olat.group; import org.olat.NewControllerFactory; -import org.olat.core.configuration.AbstractOLATModule; -import org.olat.core.configuration.PersistedProperties; +import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.id.Roles; import org.olat.core.id.context.SiteContextEntryControllerCreator; import org.olat.core.util.StringHelper; +import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.resource.OresHelper; import org.olat.group.site.GroupsSite; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; /** * Description:<br> @@ -37,7 +40,8 @@ import org.olat.group.site.GroupsSite; * * @author gnaegi */ -public class BusinessGroupModule extends AbstractOLATModule { +@Service("businessGroupModule") +public class BusinessGroupModule extends AbstractSpringModule { public static String ORES_TYPE_GROUP = OresHelper.calculateTypeName(BusinessGroup.class); @@ -62,39 +66,61 @@ public class BusinessGroupModule extends AbstractOLATModule { private static final String ACCEPT_MEMBERSHIP_GROUPMANAGERS = "acceptMembershipForGroupmanagers"; private static final String ACCEPT_MEMBERSHIP_ADMINISTRATORS = "acceptMembershipForAdministrators"; + private static final String ALLOW_LEAVING_GROUP_BY_LEARNERS = "allowLeavingGroupCreatedByLearners"; + private static final String ALLOW_LEAVING_GROUP_BY_AUTHORS = "allowLeavingGroupCreatedByAuthors"; + private static final String ALLOW_LEAVING_GROUP_OVERRIDE = "allowLeavingGroupOverride"; + private static final String GROUP_MGR_LINK_COURSE_ALLOWED = "groupManagersAllowedToLinkCourses"; private static final String RESOURCE_MGR_LINK_GROUP_ALLOWED = "resourceManagersAllowedToLinkGroups"; private static final String MANAGED_GROUPS_ENABLED = "managedBusinessGroups"; - + @Value("${group.user.create:true}") private boolean userAllowedCreate; + @Value("${group.author.create}") private boolean authorAllowedCreate; + @Value("${group.userlist.download.default.allowed}") private boolean userListDownloadDefaultAllowed; + @Value("${group.card.contact}") private String contactBusinessCard; + @Value("${group.mandatory.enrolment.email.users}") private String mandatoryEnrolmentEmailForUsers; + @Value("${group.mandatory.enrolment.email.authors}") private String mandatoryEnrolmentEmailForAuthors; + @Value("${group.mandatory.enrolment.email.usermanagers}") private String mandatoryEnrolmentEmailForUsermanagers; + @Value("${group.mandatory.enrolment.email.groupmanagers}") private String mandatoryEnrolmentEmailForGroupmanagers; + @Value("${group.mandatory.enrolment.email.administrators}") private String mandatoryEnrolmentEmailForAdministrators; - + + @Value("${group.accept.membership.users}") private String acceptMembershipForUsers; + @Value("${group.accept.membership.authors}") private String acceptMembershipForAuthors; + @Value("${group.accept.membership.usermanagers}") private String acceptMembershipForUsermanagers; + @Value("${group.accept.membership.groupmanagers}") private String acceptMembershipForGroupmanagers; + @Value("${group.accept.membership.administrators}") private String acceptMembershipForAdministrators; + @Value("${group.leaving.group.created.by.learners:true}") + private boolean allowLeavingGroupCreatedByLearners; + @Value("${group.leaving.group.created.by.authors:true}") + private boolean allowLeavingGroupCreatedByAuthors; + @Value("${group.leaving.group.override:true}") + private boolean allowLeavingGroupOverride; + private boolean groupManagersAllowedToLinkCourses; private boolean resourceManagersAllowedToLinkGroups; - + @Value("${group.managed}") private boolean managedBusinessGroups; - /** - * [used by spring] - */ - private BusinessGroupModule() { - // + @Autowired + public BusinessGroupModule(CoordinatorManager coordinatorManager) { + super(coordinatorManager); } /** @@ -113,34 +139,6 @@ public class BusinessGroupModule extends AbstractOLATModule { updateProperties(); } - /** - * @see org.olat.core.configuration.AbstractOLATModule#initDefaultProperties() - */ - @Override - protected void initDefaultProperties() { - userAllowedCreate = getBooleanConfigParameter(USER_ALLOW_CREATE_BG, true); - authorAllowedCreate = getBooleanConfigParameter(AUTHOR_ALLOW_CREATE_BG, true); - contactBusinessCard = getStringConfigParameter(CONTACT_BUSINESS_CARD, CONTACT_BUSINESS_CARD_NEVER, true); - userListDownloadDefaultAllowed = getBooleanConfigParameter(USER_LIST_DOWNLOAD, true); - - mandatoryEnrolmentEmailForUsers = getStringConfigParameter(MANDATORY_ENROLMENT_EMAIL_USERS, "false", true); - mandatoryEnrolmentEmailForAuthors = getStringConfigParameter(MANDATORY_ENROLMENT_EMAIL_AUTHORS, "false", true); - mandatoryEnrolmentEmailForUsermanagers = getStringConfigParameter(MANDATORY_ENROLMENT_EMAIL_USERMANAGERS, "false", true); - mandatoryEnrolmentEmailForGroupmanagers = getStringConfigParameter(MANDATORY_ENROLMENT_EMAIL_GROUPMANAGERS, "false", true); - mandatoryEnrolmentEmailForAdministrators = getStringConfigParameter(MANDATORY_ENROLMENT_EMAIL_ADMINISTRATORS, "false", true); - - acceptMembershipForUsers = getStringConfigParameter(ACCEPT_MEMBERSHIP_USERS, "false", true); - acceptMembershipForAuthors = getStringConfigParameter(ACCEPT_MEMBERSHIP_AUTHORS, "false", true); - acceptMembershipForUsermanagers = getStringConfigParameter(ACCEPT_MEMBERSHIP_USERMANAGERS, "false", true); - acceptMembershipForGroupmanagers = getStringConfigParameter(ACCEPT_MEMBERSHIP_GROUPMANAGERS, "false", true); - acceptMembershipForAdministrators = getStringConfigParameter(ACCEPT_MEMBERSHIP_ADMINISTRATORS, "false", true); - - groupManagersAllowedToLinkCourses = getBooleanConfigParameter(GROUP_MGR_LINK_COURSE_ALLOWED, false); - resourceManagersAllowedToLinkGroups = getBooleanConfigParameter(RESOURCE_MGR_LINK_GROUP_ALLOWED, false); - - managedBusinessGroups = getBooleanConfigParameter(MANAGED_GROUPS_ENABLED, false); - } - @Override protected void initFromChangedProperties() { updateProperties(); @@ -218,17 +216,25 @@ public class BusinessGroupModule extends AbstractOLATModule { resourceManagersAllowedToLinkGroups = "true".equals(linkGroupAllowed); } + String allowLeavingIfCreatedByLearners = getStringPropertyValue(ALLOW_LEAVING_GROUP_BY_LEARNERS, true); + if(StringHelper.containsNonWhitespace(allowLeavingIfCreatedByLearners)) { + allowLeavingGroupCreatedByLearners = "true".equals(allowLeavingIfCreatedByLearners); + } + String allowLeavingIfCreatedByAuthors = getStringPropertyValue(ALLOW_LEAVING_GROUP_BY_AUTHORS, true); + if(StringHelper.containsNonWhitespace(allowLeavingIfCreatedByAuthors)) { + allowLeavingGroupCreatedByAuthors = "true".equals(allowLeavingIfCreatedByAuthors); + } + String allowLeavingOverride = getStringPropertyValue(ALLOW_LEAVING_GROUP_OVERRIDE, true); + if(StringHelper.containsNonWhitespace(allowLeavingOverride)) { + allowLeavingGroupOverride = "true".equals(allowLeavingOverride); + } + String managedGroups = getStringPropertyValue(MANAGED_GROUPS_ENABLED, true); if(StringHelper.containsNonWhitespace(managedGroups)) { managedBusinessGroups = "true".equals(managedGroups); } } - - @Override - public void setPersistedProperties(PersistedProperties persistedProperties) { - this.moduleConfigProperties = persistedProperties; - } - + public boolean isAllowedCreate(Roles roles) { if(roles.isOLATAdmin() || roles.isGroupManager() || (roles.isAuthor() && isAuthorAllowedCreate()) @@ -406,6 +412,33 @@ public class BusinessGroupModule extends AbstractOLATModule { setStringProperty(RESOURCE_MGR_LINK_GROUP_ALLOWED, Boolean.toString(enabled), true); } + public boolean isAllowLeavingGroupCreatedByLearners() { + return allowLeavingGroupCreatedByLearners; + } + + public void setAllowLeavingGroupCreatedByLearners(boolean allow) { + this.allowLeavingGroupCreatedByLearners = allow; + setStringProperty(ALLOW_LEAVING_GROUP_BY_LEARNERS, Boolean.toString(allow), true); + } + + public boolean isAllowLeavingGroupCreatedByAuthors() { + return allowLeavingGroupCreatedByAuthors; + } + + public void setAllowLeavingGroupCreatedByAuthors(boolean allow) { + this.allowLeavingGroupCreatedByAuthors = allow; + setStringProperty(ALLOW_LEAVING_GROUP_BY_AUTHORS, Boolean.toString(allow), true); + } + + public boolean isAllowLeavingGroupOverride() { + return allowLeavingGroupOverride; + } + + public void setAllowLeavingGroupOverride(boolean allow) { + this.allowLeavingGroupOverride = allow; + setStringProperty(ALLOW_LEAVING_GROUP_OVERRIDE, Boolean.toString(allow), true); + } + public boolean isManagedBusinessGroups() { return managedBusinessGroups; } diff --git a/src/main/java/org/olat/group/BusinessGroupService.java b/src/main/java/org/olat/group/BusinessGroupService.java index 6c87806a5ee8f3c48e10acacb895c9ace449886c..2eb49b61e936b5001697466daa6f3294fcb3e88d 100644 --- a/src/main/java/org/olat/group/BusinessGroupService.java +++ b/src/main/java/org/olat/group/BusinessGroupService.java @@ -36,6 +36,7 @@ import org.olat.group.model.BGRepositoryEntryRelation; import org.olat.group.model.BusinessGroupEnvironment; import org.olat.group.model.BusinessGroupMembershipChange; import org.olat.group.model.EnrollState; +import org.olat.group.model.LeaveOption; import org.olat.group.model.MembershipModification; import org.olat.group.model.SearchBusinessGroupParams; import org.olat.repository.RepositoryEntry; @@ -119,6 +120,8 @@ public interface BusinessGroupService { boolean ownersPublis, boolean participantsPublic, boolean waitingListPublic, boolean download); + public BusinessGroup updateAllowToLeaveBusinessGroup(BusinessGroup group, boolean allowLeaving); + /** * Delete a business group from the persistence store * @param group @@ -409,6 +412,9 @@ public interface BusinessGroupService { public void cancelPendingParticipation(Identity ureqIdentity, ResourceReservation reservation); + + public LeaveOption isAllowToLeaveBusinessGroup(Identity identity, BusinessGroup group); + /** * Remove a list of users from a group as participant and does all the magic that needs * to be done: diff --git a/src/main/java/org/olat/group/_spring/businessGroupContext.xml b/src/main/java/org/olat/group/_spring/businessGroupContext.xml index 46fcc3c6fad886ca1f7389017e5c3308e55d6fec..db4d8ee22dcd8d238e3afec793c1b4619b40ba8e 100644 --- a/src/main/java/org/olat/group/_spring/businessGroupContext.xml +++ b/src/main/java/org/olat/group/_spring/businessGroupContext.xml @@ -8,47 +8,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - <context:component-scan base-package="org.olat.group.manager,org.olat.group.area,org.olat.group.right" /> - - <bean id="businessGroupModule" class="org.olat.group.BusinessGroupModule" init-method="init"> - <property name="persistedProperties"> - <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" - depends-on="coordinatorManager,org.olat.core.util.WebappHelper"> - <constructor-arg index="0" ref="coordinatorManager"/> - <constructor-arg index="1" ref="businessGroupModule" /> - </bean> - </property> - </bean> - - <!-- default configuration --> - <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> - <property name="targetObject" ref="businessGroupModule" /> - <property name="targetMethod" value="init" /> - <property name="arguments"> - <value> - user.allowed.create=${group.user.create} - author.allowed.create=${group.author.create} - <!-- Show the contact form in the business group card. - Values are: never,always,groupconfig --> - contact.business.card=${group.card.contact} - userlist.download.default.allowed=${group.userlist.download.default.allowed} - - mandatoryEnrolmentEmailForUsers=${group.mandatory.enrolment.email.users} - mandatoryEnrolmentEmailForAuthors=${group.mandatory.enrolment.email.authors} - mandatoryEnrolmentEmailForUsermanagers=${group.mandatory.enrolment.email.usermanagers} - mandatoryEnrolmentEmailForGroupmanagers=${group.mandatory.enrolment.email.groupmanagers} - mandatoryEnrolmentEmailForAdministrators=${group.mandatory.enrolment.email.administrators} - - acceptMembershipForUsers=${group.accept.membership.users} - acceptMembershipForAuthors=${group.accept.membership.authors} - acceptMembershipForUsermanagers=${group.accept.membership.usermanagers} - acceptMembershipForGroupmanagers=${group.accept.membership.groupmanagers} - acceptMembershipForAdministrators=${group.accept.membership.administrators} - - managedBusinessGroups=${group.managed} - </value> - </property> - </bean> + <context:component-scan base-package="org.olat.group" /> <!-- Login interceptor --> <bean id="reservation.AfterLogin.Injection" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> diff --git a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java index d2b68ec92ced6043ddfea471889ff36d967696e4..3560cea0024f811560af588411e4de8d2c02793b 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java @@ -41,10 +41,12 @@ import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.commons.services.mark.impl.MarkImpl; import org.olat.core.id.Identity; +import org.olat.core.id.Roles; import org.olat.core.util.StringHelper; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupImpl; import org.olat.group.BusinessGroupMembership; +import org.olat.group.BusinessGroupModule; import org.olat.group.BusinessGroupOrder; import org.olat.group.BusinessGroupShort; import org.olat.group.BusinessGroupView; @@ -76,11 +78,13 @@ public class BusinessGroupDAO { @Autowired private GroupDAO groupDao; @Autowired - private BusinessGroupRelationDAO businessGroupRelationDao; - @Autowired private BaseSecurity securityManager; @Autowired private OLATResourceManager olatResourceManager; + @Autowired + private BusinessGroupModule businessGroupModule; + @Autowired + private BusinessGroupRelationDAO businessGroupRelationDao; public BusinessGroup createAndPersist(Identity creator, String name, String description, Integer minParticipants, Integer maxParticipants, boolean waitingListEnabled, boolean autoCloseRanksEnabled, @@ -118,6 +122,17 @@ public class BusinessGroupDAO { businessgroup.setWaitingListVisiblePublic(false); businessgroup.setDownloadMembersLists(false); + if(creator == null) { + businessgroup.setAllowToLeave(businessGroupModule.isAllowLeavingGroupCreatedByAuthors()); + } else { + Roles roles = securityManager.getRoles(creator); + if(roles.isAuthor()) { + businessgroup.setAllowToLeave(businessGroupModule.isAllowLeavingGroupCreatedByAuthors()); + } else { + businessgroup.setAllowToLeave(businessGroupModule.isAllowLeavingGroupCreatedByLearners()); + } + } + businessgroup.setWaitingListEnabled(waitingListEnabled); businessgroup.setAutoCloseRanksEnabled(autoCloseRanksEnabled); diff --git a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java index e7159c4454a5b2cf9c62c4950d0683f743e84923..1aaa48a646a8a417cfd1fd57771759f8d3f466e4 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java @@ -27,9 +27,12 @@ import java.util.List; import javax.persistence.TypedQuery; +import org.olat.basesecurity.Constants; import org.olat.basesecurity.Group; import org.olat.basesecurity.GroupRoles; import org.olat.basesecurity.IdentityRef; +import org.olat.basesecurity.NamedGroupImpl; +import org.olat.basesecurity.SecurityGroupMembershipImpl; import org.olat.basesecurity.manager.GroupDAO; import org.olat.basesecurity.model.GroupMembershipImpl; import org.olat.core.commons.persistence.DB; @@ -135,6 +138,29 @@ public class BusinessGroupRelationDAO { return count == null ? 0 : count.intValue(); } + /** + * Return the number of coaches with author rights. + * @param group + * @return + */ + public int countAuthors(BusinessGroup group) { + StringBuilder sb = new StringBuilder(); + sb.append("select count(membership) from ").append(BusinessGroupImpl.class.getName()).append(" as bgroup ") + .append(" inner join bgroup.baseGroup as baseGroup") + .append(" inner join baseGroup.members as membership") + .append(" where bgroup.key=:businessGroupKey and membership.role='").append(GroupRoles.coach.name()).append("'") + .append(" and exists (") + .append(" select sgmsi from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as sgmsi, ").append(NamedGroupImpl.class.getName()).append(" as ngroup ") + .append(" where sgmsi.identity=membership.identity and sgmsi.securityGroup=ngroup.securityGroup") + .append(" and ngroup.groupName in ('").append(Constants.GROUP_AUTHORS).append("')") + .append(" )"); + + Number count = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Number.class) + .setParameter("businessGroupKey", group.getKey()) + .getSingleResult(); + return count == null ? 0 : count.intValue(); + } + /** * Match the list of roles with the list of specfified roles * @param identity diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java index df2c6e629739638179cb286b40e02697c1e3c317..ae5585e2ce85006e9baee65e176c23cc23e90364 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java @@ -42,6 +42,7 @@ import org.olat.basesecurity.Constants; import org.olat.basesecurity.Group; import org.olat.basesecurity.GroupRoles; import org.olat.basesecurity.IdentityRef; +import org.olat.basesecurity.SecurityGroup; import org.olat.collaboration.CollaborationTools; import org.olat.collaboration.CollaborationToolsFactory; import org.olat.core.CoreSpringFactory; @@ -58,6 +59,7 @@ import org.olat.core.logging.activity.ActionType; import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.util.async.ProgressDelegate; import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.MailBundle; import org.olat.core.util.mail.MailContext; import org.olat.core.util.mail.MailContextImpl; @@ -92,6 +94,7 @@ import org.olat.group.model.BusinessGroupMembershipViewImpl; import org.olat.group.model.BusinessGroupMembershipsChanges; import org.olat.group.model.EnrollState; import org.olat.group.model.IdentityGroupKey; +import org.olat.group.model.LeaveOption; import org.olat.group.model.MembershipModification; import org.olat.group.model.SearchBusinessGroupParams; import org.olat.group.right.BGRightManager; @@ -104,6 +107,7 @@ import org.olat.repository.RepositoryEntryRef; import org.olat.repository.RepositoryEntryRelationType; import org.olat.repository.RepositoryEntryShort; import org.olat.repository.RepositoryManager; +import org.olat.repository.RepositoryService; import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.olat.repository.model.RepositoryEntryToGroupRelation; import org.olat.repository.model.SearchRepositoryEntryParameters; @@ -133,6 +137,8 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD @Autowired private BusinessGroupDAO businessGroupDAO; @Autowired + private RepositoryService repositoryService; + @Autowired private RepositoryManager repositoryManager; @Autowired private PropertyManager propertyManager; @@ -307,6 +313,20 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD return mergedGroup; } + @Override + public BusinessGroup updateAllowToLeaveBusinessGroup(BusinessGroup group, boolean allow) { + BusinessGroup reloadedBusinessGroup = businessGroupDAO.loadForUpdate(group.getKey()); + BusinessGroup mergedGroup = null; + if(reloadedBusinessGroup != null) { + reloadedBusinessGroup.setAllowToLeave(allow); + mergedGroup = businessGroupDAO.merge(reloadedBusinessGroup); + //prevent lazy loading issues + mergedGroup.getBaseGroup().getKey(); + } + dbInstance.commit(); + return mergedGroup; + } + @Override public BusinessGroup setLastUsageFor(final Identity identity, final BusinessGroup group) { BusinessGroup reloadedBusinessGroup = businessGroupDAO.loadForUpdate(group.getKey()); @@ -995,6 +1015,84 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } + @Override + public LeaveOption isAllowToLeaveBusinessGroup(Identity identity, BusinessGroup group) { + LeaveOption opt; + if(groupModule.isAllowLeavingGroupOverride()) { + if(group.isAllowToLeave()) { + opt = new LeaveOption(); + } else { + ContactList list = getAdminContactList(group); + opt = new LeaveOption(false, list); + } + } else if(groupModule.isAllowLeavingGroupCreatedByAuthors() && groupModule.isAllowLeavingGroupCreatedByLearners()) { + opt = new LeaveOption(); + } else if(!groupModule.isAllowLeavingGroupCreatedByAuthors() && !groupModule.isAllowLeavingGroupCreatedByLearners()) { + ContactList list = getAdminContactList(group); + opt = new LeaveOption(false, list); + } else { + int numOfCoaches = countMembers(group, GroupRoles.coach.name()); + if(numOfCoaches == 0) { + int numOfResources = businessGroupRelationDAO.countResources(group); + if(numOfResources > 0) { + //author group + if(groupModule.isAllowLeavingGroupCreatedByAuthors()) { + opt = new LeaveOption(); + } else { + ContactList list = getAdminContactList(group); + opt = new LeaveOption(false, list); + } + + //learner group + } else if(groupModule.isAllowLeavingGroupCreatedByLearners()) { + opt = new LeaveOption(); + } else { + ContactList list = getAdminContactList(group); + opt = new LeaveOption(false, list); + } + } else { + int numOfAuthors = businessGroupRelationDAO.countAuthors(group); + if(numOfAuthors > 0) { + if(groupModule.isAllowLeavingGroupCreatedByAuthors()) { + opt = new LeaveOption(); + } else { + ContactList list = getAdminContactList(group); + opt = new LeaveOption(false, list); + } + } else if(groupModule.isAllowLeavingGroupCreatedByLearners()) { + opt = new LeaveOption(); + } else { + ContactList list = getAdminContactList(group); + opt = new LeaveOption(false, list); + } + } + } + return opt; + } + + public ContactList getAdminContactList(BusinessGroup group) { + ContactList list = new ContactList("Contact"); + List<Identity> coaches = getMembers(group, GroupRoles.coach.name()); + if(coaches.isEmpty()) { + Collection<BusinessGroup> groups = Collections.singletonList(group); + List<RepositoryEntry> entries = businessGroupRelationDAO.findRepositoryEntries(groups, 0, -1); + for(RepositoryEntry re:entries) { + coaches.addAll(repositoryService.getMembers(re, GroupRoles.coach.name())); + } + + if(coaches.isEmpty()) { + //get system administrators + SecurityGroup adminSecGroup = securityManager.findSecurityGroupByName(Constants.GROUP_ADMIN); + List<Identity> admins = securityManager.getIdentitiesByPowerSearch(null, null, false, new SecurityGroup[]{ adminSecGroup }, + null, null, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT); + coaches.addAll(admins); + } + } + + list.addAllIdentites(coaches); + return list; + } + @Override public void removeParticipants(Identity ureqIdentity, List<Identity> identities, BusinessGroup group, MailPackage mailing) { group = businessGroupDAO.loadForUpdate(group.getKey()); @@ -1219,6 +1317,9 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD response.getAddedIdentities().add(identity); // notification mail is handled in controller } else { + if (businessGroupRelationDAO.hasRole(identity, currBusinessGroup, GroupRoles.waiting.name()) ) { + removeFromWaitingList(ureqIdentity, identity, currBusinessGroup, mailing, events); + } response.getIdentitiesAlreadyInGroup().add(identity); } } diff --git a/src/main/java/org/olat/group/model/LeaveOption.java b/src/main/java/org/olat/group/model/LeaveOption.java new file mode 100644 index 0000000000000000000000000000000000000000..ebe3b6f7b6cf1797fb39f5ad26731aea306642f2 --- /dev/null +++ b/src/main/java/org/olat/group/model/LeaveOption.java @@ -0,0 +1,52 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.group.model; + +import org.olat.core.util.mail.ContactList; + +/** + * + * Initial date: 31.10.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class LeaveOption { + + private final boolean allowToLeave; + private final ContactList contacts; + + public LeaveOption() { + this(true, null); + } + + public LeaveOption(boolean allowToLeave, ContactList contacts) { + this.allowToLeave = allowToLeave; + this.contacts = contacts; + + } + + public boolean isAllowToLeave() { + return allowToLeave; + } + + public ContactList getContacts() { + return contacts; + } +} diff --git a/src/main/java/org/olat/group/model/SearchBusinessGroupParams.java b/src/main/java/org/olat/group/model/SearchBusinessGroupParams.java index 8a1e136df547f699584d50c93396443fbf5db87f..5421835659fbd5f5877e1b820592732d6dd28c4f 100644 --- a/src/main/java/org/olat/group/model/SearchBusinessGroupParams.java +++ b/src/main/java/org/olat/group/model/SearchBusinessGroupParams.java @@ -78,11 +78,11 @@ public class SearchBusinessGroupParams { this.tools = tools; } - public void addTools(String... tools) { + public void addTools(String... toolsToAdd) { if(this.tools == null) { this.tools = new ArrayList<String>(); } - for(String tool:tools) { + for(String tool:toolsToAdd) { this.tools.add(tool); } } diff --git a/src/main/java/org/olat/group/ui/BusinessGroupModuleAdminController.java b/src/main/java/org/olat/group/ui/BusinessGroupModuleAdminController.java index ba0466ab2ef462eb5e16fb876b9e2dc9fb127db6..64eadf3db388730bbee42f0fe83ce8e3924cd29a 100644 --- a/src/main/java/org/olat/group/ui/BusinessGroupModuleAdminController.java +++ b/src/main/java/org/olat/group/ui/BusinessGroupModuleAdminController.java @@ -55,6 +55,7 @@ public class BusinessGroupModuleAdminController extends FormBasicController impl private MultipleSelectionElement membershipEl; private MultipleSelectionElement assignCoursesEl; private MultipleSelectionElement assignGroupsEl; + private MultipleSelectionElement allowLeavingGroupsEl; private Panel mainPopPanel; private CloseableModalController cmc; @@ -68,6 +69,10 @@ public class BusinessGroupModuleAdminController extends FormBasicController impl "users","authors", "usermanagers", "groupmanagers", "administrators" }; private String[] assignKeys = new String[]{"granted"}; + private String[] allowLeavingKeys = new String[]{ + "groupMadeByLearners", "groupMadeByAuthors", "groupOverride" + }; + public BusinessGroupModuleAdminController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl, "bg_admin"); @@ -133,7 +138,18 @@ public class BusinessGroupModuleAdminController extends FormBasicController impl membershipEl.select("groupmanagers", "true".equals(module.getAcceptMembershipForGroupmanagers())); membershipEl.select("administrators", "true".equals(module.getAcceptMembershipForAdministrators())); membershipEl.addActionListener(FormEvent.ONCHANGE); - + + String[] allowLeavingValues = new String[]{ + translate("leaving.group.learners"), + translate("leaving.group.authors"), + translate("leaving.group.override"), + }; + allowLeavingGroupsEl = uifactory.addCheckboxesVertical("leaving.group", privacyOptionsContainer, allowLeavingKeys, allowLeavingValues, 1); + allowLeavingGroupsEl.select("groupMadeByLearners", module.isAllowLeavingGroupCreatedByLearners()); + allowLeavingGroupsEl.select("groupMadeByAuthors", module.isAllowLeavingGroupCreatedByAuthors()); + allowLeavingGroupsEl.select("groupOverride", module.isAllowLeavingGroupOverride()); + allowLeavingGroupsEl.addActionListener(FormEvent.ONCHANGE); + FormLayoutContainer dedupCont = FormLayoutContainer.createDefaultFormLayout("dedup", getTranslator()); formLayout.add(dedupCont); dedupLink = uifactory.addFormLink("dedup.members", dedupCont, Link.BUTTON); @@ -169,8 +185,6 @@ public class BusinessGroupModuleAdminController extends FormBasicController impl dedupCtrl = null; cmc = null; } - - @Override public void setMax(float max) { @@ -220,6 +234,11 @@ public class BusinessGroupModuleAdminController extends FormBasicController impl module.setMandatoryEnrolmentEmailForUsermanagers(enrolmentSelectedKeys.contains("usermanagers") ? "true" : "false"); module.setMandatoryEnrolmentEmailForGroupmanagers(enrolmentSelectedKeys.contains("groupmanagers") ? "true" : "false"); module.setMandatoryEnrolmentEmailForAdministrators(enrolmentSelectedKeys.contains("administrators") ? "true" : "false"); + } else if(source == allowLeavingGroupsEl) { + Collection<String> leavingSelectedKeys = allowLeavingGroupsEl.getSelectedKeys(); + module.setAllowLeavingGroupCreatedByLearners(leavingSelectedKeys.contains("groupMadeByLearners")); + module.setAllowLeavingGroupCreatedByAuthors(leavingSelectedKeys.contains("groupMadeByAuthors")); + module.setAllowLeavingGroupOverride(leavingSelectedKeys.contains("groupOverride")); } else if(assignCoursesEl == source) { module.setGroupManagersAllowedToLinkCourses(assignCoursesEl.isSelected(0)); } else if(assignGroupsEl == source) { diff --git a/src/main/java/org/olat/group/ui/BusinessGroupTableModelWithMaxSize.java b/src/main/java/org/olat/group/ui/BusinessGroupTableModelWithMaxSize.java index fd0df7c334f99fb53d5d4e9c09161ee4deaad7db..1e35c34fa733d57ebea89f700dc94eadb0aed857 100644 --- a/src/main/java/org/olat/group/ui/BusinessGroupTableModelWithMaxSize.java +++ b/src/main/java/org/olat/group/ui/BusinessGroupTableModelWithMaxSize.java @@ -187,12 +187,12 @@ public class BusinessGroupTableModelWithMaxSize extends DefaultTableDataModel<Bu /** * Check if an identity is in certain security-group. * @param businessGroup - * @param identity + * @param ident * @return true: Found identity in PartipiciantGroup or WaitingGroup. */ - private boolean isEnrolledIn(BusinessGroup businessGroup, Identity identity) { - if (businessGroupService.hasRoles(identity, businessGroup, GroupRoles.participant.name()) - || businessGroupService.hasRoles(identity, businessGroup, GroupRoles.waiting.name())) { + private boolean isEnrolledIn(BusinessGroup businessGroup, Identity ident) { + if (businessGroupService.hasRoles(ident, businessGroup, GroupRoles.participant.name()) + || businessGroupService.hasRoles(ident, businessGroup, GroupRoles.waiting.name())) { return true; } return false; @@ -200,13 +200,13 @@ public class BusinessGroupTableModelWithMaxSize extends DefaultTableDataModel<Bu /** * Check if an identity is in any security-group. - * @param identity + * @param ident * @return true: Found identity in any security-group of this table model. */ - private boolean isEnrolledInAnyGroup(Identity identity) { + private boolean isEnrolledInAnyGroup(Identity ident) { // loop over all business-groups for (BusinessGroup businessGroup:objects) { - if (isEnrolledIn(businessGroup, identity) ) { + if (isEnrolledIn(businessGroup, ident) ) { return true; } } diff --git a/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties index 76b4188fd880e99543087e4f83e863e75b296c34..0aefb7956460f0ed015556217ee42193f607a566 100644 --- a/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties @@ -71,6 +71,10 @@ groupsPortlet.no_member=Sie wurden aus dieser Gruppe ausgetragen oder die Gruppe groupsPortlet.nogroups=Sie sind in keiner Gruppe groupsPortlet.showAll=Alle anzeigen groupsPortlet.title=Meine Gruppen +leaving.group=Members can leave group +leaving.group.learners=Allow group exit by members of groups created by learners +leaving.group.authors=Allow group exit by members of groups created by authors +leaving.group.override=Allow group exit configuration override by author users mandatory.enrolment=E-Mail Benachrichtigung erzwungen bei Einladung durch mandatory.membership=Best\u00E4tigung Mitgliedschaft erforderlich bei Einladung durch membership.administrators=$\:enrolment.email.administrators diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java index 738504dff40b2ae92a21739896c482f612a149c6..04512361064bb6164426999f62620060c18a447b 100644 --- a/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java +++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java @@ -59,6 +59,7 @@ public class BusinessGroupMembersController extends BasicController { private final VelocityContainer mainVC; private final DisplayMemberSwitchForm dmsForm; + private final MembershipConfigurationForm configForm; private MemberListController membersController; private final Link importMemberLink, addMemberLink; private StepsMainRunController importMembersWizard; @@ -88,6 +89,12 @@ public class BusinessGroupMembersController extends BasicController { dmsForm.setDisplayMembers(businessGroup); mainVC.put("displayMembers", dmsForm.getInitialComponent()); + configForm = new MembershipConfigurationForm (ureq, getWindowControl()); + configForm.setEnabled(!BusinessGroupManagedFlag.isManaged(businessGroup, BusinessGroupManagedFlag.membersmanagement)); + listenTo(configForm); + configForm.setMembershipConfiguration(businessGroup); + mainVC.put("configMembers", configForm.getInitialComponent()); + boolean managed = BusinessGroupManagedFlag.isManaged(businessGroup, BusinessGroupManagedFlag.membersmanagement); SearchMembersParams searchParams = new SearchMembersParams(false, false, false, true, true, true, true); membersController = new MemberListController(ureq, getWindowControl(), businessGroup, searchParams); @@ -127,8 +134,8 @@ public class BusinessGroupMembersController extends BasicController { } } - protected void updateBusinessGroup(BusinessGroup businessGroup) { - this.businessGroup = businessGroup; + protected void updateBusinessGroup(BusinessGroup bGroup) { + this.businessGroup = bGroup; boolean hasWaitingList = businessGroup.getWaitingListEnabled().booleanValue(); Boolean waitingFlag = (Boolean)mainVC.getContext().get("hasWaitingGrp"); @@ -162,6 +169,16 @@ public class BusinessGroupMembersController extends BasicController { ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_CONFIGURATION_CHANGED, getClass()); fireEvent(ureq, event); } + } else if (source == configForm) { + if(event == Event.CHANGED_EVENT) { + boolean allow = configForm.isAllowToLeaveBusinessGroup(); + businessGroup = businessGroupService.updateAllowToLeaveBusinessGroup(businessGroup, allow); + // notify current active users of this business group + BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.CONFIGURATION_MODIFIED_EVENT, businessGroup, null); + // do loggin + ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_CONFIGURATION_CHANGED, getClass()); + fireEvent(ureq, event); + } } else if(source == importMembersWizard) { if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { getWindowControl().pop(); diff --git a/src/main/java/org/olat/group/ui/edit/MembershipConfigurationForm.java b/src/main/java/org/olat/group/ui/edit/MembershipConfigurationForm.java new file mode 100644 index 0000000000000000000000000000000000000000..6f56f5f4cf6a5c7f8f1cebd89dbee1a11269f5af --- /dev/null +++ b/src/main/java/org/olat/group/ui/edit/MembershipConfigurationForm.java @@ -0,0 +1,107 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.group.ui.edit; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.SelectionElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.Roles; +import org.olat.group.BusinessGroup; +import org.olat.group.BusinessGroupModule; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 31.10.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MembershipConfigurationForm extends FormBasicController { + + private SelectionElement allowToLeaveEl; + + @Autowired + private BusinessGroupModule businessGroupModule; + + /** + * @param name + * @param transl + * @param hasPartips + * @param hasOwners + */ + public MembershipConfigurationForm(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, LAYOUT_DEFAULT_6_6); + initForm(ureq); + } + + public boolean isAllowToLeaveBusinessGroup() { + return allowToLeaveEl.isSelected(0); + } + + public void setMembershipConfiguration(BusinessGroup group) { + if(allowToLeaveEl.isEnabled()) { + allowToLeaveEl.select("xx", group.isAllowToLeave()); + } + } + + public void setEnabled(boolean enabled) { + allowToLeaveEl.setEnabled(enabled); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(allowToLeaveEl == source) { + fireEvent (ureq, Event.CHANGED_EVENT); + } + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + allowToLeaveEl = uifactory.addCheckboxesHorizontal("allow.leaving", "allow.leaving.group", formLayout, new String[]{"xx"}, new String[]{""}); + allowToLeaveEl.addActionListener(FormEvent.ONCLICK); + if(businessGroupModule.isAllowLeavingGroupOverride()) { + allowToLeaveEl.setEnabled(true); + } else { + allowToLeaveEl.setEnabled(false); + Roles roles = ureq.getUserSession().getRoles(); + if(roles.isAuthor()) { + allowToLeaveEl.select("xx", businessGroupModule.isAllowLeavingGroupCreatedByAuthors()); + } else { + allowToLeaveEl.select("xx", businessGroupModule.isAllowLeavingGroupCreatedByLearners()); + } + } + } + + @Override + protected void doDispose() { + // + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/group/ui/edit/_chelp/grp-leaving.html b/src/main/java/org/olat/group/ui/edit/_chelp/grp-leaving.html new file mode 100644 index 0000000000000000000000000000000000000000..d27dc220d23f994fdf196bd171eb22915749f8bb --- /dev/null +++ b/src/main/java/org/olat/group/ui/edit/_chelp/grp-leaving.html @@ -0,0 +1 @@ +<p>[Placeholder help]</p> \ No newline at end of file diff --git a/src/main/java/org/olat/group/ui/edit/_content/tab_bgGrpMngmnt.html b/src/main/java/org/olat/group/ui/edit/_content/tab_bgGrpMngmnt.html index a62ac66784f866d62fc41d3af2dd290c8a4e4ca5..24e84eb2e9e8e08b223ff87732d1771ba1e3a8fa 100644 --- a/src/main/java/org/olat/group/ui/edit/_content/tab_bgGrpMngmnt.html +++ b/src/main/java/org/olat/group/ui/edit/_content/tab_bgGrpMngmnt.html @@ -4,6 +4,12 @@ $r.translate("fieldset.legend.displaymembers")</legend> $r.render("displayMembers") </fieldset> +<fieldset> + <legend> + $r.contextHelpWithWrapper("org.olat.group.ui.edit","grp-leaving.html","help.hover.allowLeaving") + $r.translate("fieldset.legend.allow.leaving")</legend> + $r.render("configMembers") +</fieldset> <fieldset> <legend> $r.contextHelpWithWrapper("org.olat.group.ui.edit","grp-memberOwner.html","help.hover.bgGrpMngmntOwner") diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties index cdfcaf89f08b4c71e26fb9d3663e45bde1390c8d..5fa0629031af8b3517edf0a40dbf22a98664c021 100644 --- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties @@ -1,4 +1,5 @@ #Mon Mar 02 09:54:04 CET 2009 +allow.leaving.group=Teilnehmer können Gruppe austreten areachoice.no.areas.admin=Es wurde kein Lernbereich gefunden. Bitte erstellen Sie im Gruppenmanagement einen Lernbereich. areachoice.no.areas.owner=Es wurde kein Lernbereich gefunden. Lernbereiche k\u00F6nnen nur von Personen mit Berechtigung f\u00FCr das gesamte Gruppenmanagement erstellt werden. chelp.area1=Sofern im Kurs Lerngruppen erstellt worden sind, erscheinen diese im Tab. @@ -20,6 +21,7 @@ chelp.desc.learn9=Sofern Sie die Anzahl Teilnehmer beschr\u00E4nkt haben, k\u00F chelp.grp-assign.title=Gruppe: Rechte zuweisen chelp.grp-Area-select-learn.title=Lernbereiche: Lerngruppen zuweisen chelp.grp-des.title=$org.olat.group.ui\:LearningGroup: Beschreibung +chelp.grp-leaving.title=Teilnehmer Konfiguration chelp.grp-member.title=$org.olat.group.ui\:LearningGroup: Mitglieder chelp.grp-memberOwner.title=$org.olat.group.ui\:LearningGroup: $org.olat.group.ui\:fieldset.legend.groupowners chelp.grp-memberParticipants.title=$org.olat.group.ui\:LearningGroup: Teilnehmer @@ -57,6 +59,7 @@ chelp.tools.learn10=Sie k\u00F6nnen der $org.olat.group.ui\:LearningGroup ein eP chelp.tools.learn13=Sie können der Gruppe einen privaten Chatraum zur Verfügung stellen. chelp.tools.quota=Der verf\u00FCgbare Speicherplatz betr\u00E4gt 10 MB. chelp.tools.title=Konfiguration kollaborativer Werkzeuge +help.hover.allowLeaving=Hile zur Konfiguration den Teilnehmer help.hover.bgArea=Hilfe zur Zuweisung von Lernbereichen zu Gruppe help.hover.bgCollabTools=Hilfe zu den kollaborativen Werkzeugen einer Gruppe help.hover.bgDetail=Hilfe zur Beschreibung einer Gruppe @@ -77,6 +80,7 @@ chkBox.open.downloadList=Benutzer d cmd.addresource=Kurs hinzuf\u00FCgen error.message.locked=Diese Gruppe wird im Moment vom Benutzer {0} ({1}) ver\u00E4ndert und ist daher gesperrt. Bitte versuchen Sie es sp\u00E4ter noch einmal. error.msg.send.no.rcps=$org.olat.modules.co\:error.msg.send.no.rcps +fieldset.legend.allow.leaving=Mitglieder Konfiguration fieldset.legend.areas=Zugewiesene Lernbereiche fieldset.legend.collabtools=Kollaborative Werkzeuge fieldset.legend.details=Details diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties index 5844699260ebadd96aa721af2a7c1203a1ecf2e6..d2cdd88c65e68f21d5a8a84f7025e08fac71e705 100644 --- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties @@ -1,5 +1,6 @@ #Thu Aug 08 08:49:27 CEST 2013 add.member=$org.olat.group.ui.main\:add.member +allow.leaving.group=Members can leave the group areachoice.no.areas.admin=No learning areas found. Please create a learning area within your group management. areachoice.no.areas.owner=No learning areas found. New learning areas can only be created by users who have access to the entire group management. assessment=$org.olat.group.ui.main\:assessment @@ -22,6 +23,7 @@ chelp.desc.learn9=If you want to limit the number of participants you can nevert chelp.grp-Area-select-learn.title=Learning areas\: assign groups chelp.grp-assign.title=Group\: assign rights chelp.grp-des.title=Group\: description +chelp.grp-leaving.title=Membership configuration chelp.grp-member.title=Group\: members chelp.grp-memberOwner.title=Group\: coaches chelp.grp-memberParticipants.title=Group\: participants @@ -74,6 +76,7 @@ edit.member=$org.olat.group.ui.main\:edit.member edit.member.groups=$org.olat.group.ui.main\:edit.member.groups error.message.locked=This group is being edited by user {0} ({1}) and therefore locked. Please try again later. error.msg.send.no.rcps=$org.olat.modules.co\:error.msg.send.no.rcps +fieldset.legend.allow.leaving=Membership configuration fieldset.legend.areas=Assigned learning areas fieldset.legend.collabtools=Collaborative tools fieldset.legend.details=Details @@ -93,6 +96,7 @@ group.edit.tab.members=Members group.edit.tab.resources=Courses group.edit.tab.rights=Rights group.edit.title=Edit group <i>{0}</i> +help.hover.allowLeaving=Help to configure membership help.hover.bgArea=Help to assign learning areas to groups help.hover.bgCollabTools=Help to use collaborative tools of groups help.hover.bgDetail=Help to describe a group diff --git a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java index f7775b785210c7bffd4496fc7abc9e05f92e72a6..c6612d7117e950e37cf784fd004348c8242507f8 100644 --- a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java +++ b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java @@ -66,11 +66,14 @@ import org.olat.core.gui.control.generic.wizard.StepsRunContext; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.id.Roles; +import org.olat.core.id.UserConstants; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.ContactMessage; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailPackage; import org.olat.core.util.mail.MailTemplate; @@ -90,6 +93,7 @@ import org.olat.group.manager.BusinessGroupMailing; import org.olat.group.manager.BusinessGroupMailing.MailType; import org.olat.group.model.BGRepositoryEntryRelation; import org.olat.group.model.BusinessGroupSelectionEvent; +import org.olat.group.model.LeaveOption; import org.olat.group.model.MembershipModification; import org.olat.group.model.SearchBusinessGroupParams; import org.olat.group.right.BGRightManager; @@ -104,6 +108,7 @@ import org.olat.group.ui.wizard.BGMailNotificationEditController; import org.olat.group.ui.wizard.BGMergeStep; import org.olat.group.ui.wizard.BGUserMailTemplate; import org.olat.group.ui.wizard.BGUserManagementController; +import org.olat.modules.co.ContactFormController; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.olat.repository.RepositoryEntryShort; @@ -142,6 +147,7 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr protected FormLink createButton, deleteButton, duplicateButton, configButton, emailButton, usersButton, mergeButton, selectButton; + private ContactFormController contactCtrl; private NewBGController groupCreateController; private BGUserManagementController userManagementController; private BGMailNotificationEditController userManagementSendMailController; @@ -352,9 +358,7 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr } else if(TABLE_ACTION_ACCESS.equals(cmd)) { doAccess(ureq, businessGroup); } else if(TABLE_ACTION_LEAVE.equals(cmd)) { - String groupName = StringHelper.escapeHtml(businessGroup.getName()); - leaveDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.leave.text", groupName), leaveDialogBox); - leaveDialogBox.setUserObject(businessGroup); + doConfirmLeaving(ureq, businessGroup); } } } else if(source == tableEl) { @@ -378,9 +382,7 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr } else if(TABLE_ACTION_EDIT.equals(cmd)) { doEdit(ureq, businessGroup); } else if(TABLE_ACTION_LEAVE.equals(cmd)) { - String groupName = StringHelper.escapeHtml(businessGroup.getName()); - leaveDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.leave.text", groupName), leaveDialogBox); - leaveDialogBox.setUserObject(businessGroup); + doConfirmLeaving(ureq, businessGroup); } else if (TABLE_ACTION_ACCESS.equals(cmd)) { doAccess(ureq, businessGroup); } else if (TABLE_ACTION_SELECT.equals(cmd)) { @@ -479,6 +481,9 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr if(event instanceof SearchEvent) { doSearch(ureq, (SearchEvent)event); } + } else if(source == contactCtrl) { + cmc.deactivate(); + cleanUpPopups(); } else if (source == cmc) { cleanUpPopups(); } @@ -495,11 +500,13 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr */ protected void cleanUpPopups() { removeAsListenerAndDispose(cmc); + removeAsListenerAndDispose(contactCtrl); removeAsListenerAndDispose(deleteDialogBox); removeAsListenerAndDispose(groupCreateController); removeAsListenerAndDispose(businessGroupWizard); removeAsListenerAndDispose(leaveDialogBox); cmc = null; + contactCtrl = null; leaveDialogBox = null; deleteDialogBox = null; groupCreateController = null; @@ -536,6 +543,47 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); } + private void doConfirmLeaving(UserRequest ureq, BusinessGroup businessGroup) { + if (businessGroupService.hasRoles(getIdentity(), businessGroup, GroupRoles.coach.name()) + || businessGroupService.hasRoles(getIdentity(), businessGroup, GroupRoles.waiting.name()) ) { + doOpenConfirmLeavingDialog(ureq, businessGroup); + } else { + LeaveOption option = businessGroupService.isAllowToLeaveBusinessGroup(getIdentity(), businessGroup); + if(option.isAllowToLeave()) { + doOpenConfirmLeavingDialog(ureq, businessGroup); + } else { + doAskToLeaveGroup(ureq, businessGroup, option.getContacts()); + } + } + } + + private void doOpenConfirmLeavingDialog(UserRequest ureq, BusinessGroup businessGroup) { + String groupName = StringHelper.escapeHtml(businessGroup.getName()); + leaveDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.leave.text", groupName), leaveDialogBox); + leaveDialogBox.setUserObject(businessGroup); + } + + private void doAskToLeaveGroup(UserRequest ureq, BusinessGroup businessGroup, ContactList contacts) { + String[] args = new String[]{ + businessGroup.getName(), + businessGroup.getKey().toString(), + "",//courses + getIdentity().getUser().getProperty(UserConstants.FIRSTNAME, getLocale()), + getIdentity().getUser().getProperty(UserConstants.LASTNAME, getLocale()) + }; + ContactMessage msg = new ContactMessage(getIdentity()); + msg.setSubject(translate("request.leaving.subject", args)); + msg.setBodyText(translate("request.leaving.body", args)); + msg.addEmailTo(contacts); + + contactCtrl = new ContactFormController(ureq, getWindowControl(), true, false, true, msg); + listenTo(contactCtrl); + cmc = new CloseableModalController(getWindowControl(), "close", contactCtrl.getInitialComponent(), + true, translate("dialog.modal.bg.asktoleave.title")); + cmc.activate(); + listenTo(cmc); + } + /** * Removes user from the group as owner and participant. If * no other owner are found the user won't be removed from the owner group diff --git a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java index a036ba4606574efde2be71a932553177223cf5bd..33e39333f92b6f586b539905fd201953961829a3 100644 --- a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java +++ b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java @@ -525,6 +525,38 @@ public abstract class AbstractMemberListController extends BasicController imple List<Identity> identitiesToGraduate = securityManager.loadIdentityByKeys(identityKeys); businessGroupService.moveIdentityFromWaitingListToParticipant(getIdentity(), identitiesToGraduate, businessGroup, null); + } else { + Map<Long, BusinessGroup> groupsMap = new HashMap<>(); + Map<BusinessGroup, List<Identity>> graduatesMap = new HashMap<>(); + for(MemberView member:members) { + List<BusinessGroupShort> groups = member.getGroups(); + if(groups != null && groups.size() > 0) { + Identity memberIdentity = securityManager.loadIdentityByKey(member.getIdentityKey()); + for(BusinessGroupShort group:groups) { + if(businessGroupService.hasRoles(memberIdentity, group, GroupRoles.waiting.name())) { + BusinessGroup fullGroup = groupsMap.get(group.getKey()); + if(fullGroup == null) { + fullGroup = businessGroupService.loadBusinessGroup(group.getKey()); + groupsMap.put(group.getKey(), fullGroup); + } + + List<Identity> identitiesToGraduate = graduatesMap.get(fullGroup); + if(identitiesToGraduate == null) { + identitiesToGraduate = new ArrayList<>(); + graduatesMap.put(fullGroup, identitiesToGraduate); + } + identitiesToGraduate.add(memberIdentity); + } + } + } + } + + for(Map.Entry<BusinessGroup, List<Identity>> entry:graduatesMap.entrySet()) { + BusinessGroup fullGroup = entry.getKey(); + List<Identity> identitiesToGraduate = entry.getValue(); + businessGroupService.moveIdentityFromWaitingListToParticipant(getIdentity(), identitiesToGraduate, + fullGroup, null); + } } reloadModel(); } diff --git a/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java b/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java index 97fa9de26a1ffc6a5cf7e3bc8b4f26a1ca26f570..b28f5db756c321326f5977ae5d3d5c53c581533e 100644 --- a/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java +++ b/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java @@ -38,10 +38,10 @@ import org.olat.group.model.BGMembership; */ public class BGRoleCellRenderer implements CustomCellRenderer, FlexiCellRenderer { - private final Translator translator; + private final Translator trans; public BGRoleCellRenderer(Locale locale) { - translator = Util.createPackageTranslator(BGRoleCellRenderer.class, locale); + trans = Util.createPackageTranslator(BGRoleCellRenderer.class, locale); } @Override @@ -62,22 +62,22 @@ public class BGRoleCellRenderer implements CustomCellRenderer, FlexiCellRenderer boolean and = false; if(membership.isOwner()) { and = and(sb, and); - sb.append(translator.translate("owned.groups")); + sb.append(trans.translate("owned.groups")); } if(membership.isParticipant()) { and = and(sb, and); - sb.append(translator.translate("search.attendee")); + sb.append(trans.translate("search.attendee")); } if(membership.isWaiting()) { and = and(sb, and); - sb.append(translator.translate("search.waiting")); + sb.append(trans.translate("search.waiting")); } } else if (val instanceof BGMembership) { BGMembership membership = (BGMembership)val; switch(membership) { - case owner: sb.append(translator.translate("owned.groups")); break; - case participant: sb.append(translator.translate("search.attendee")); break; - case waiting: sb.append(translator.translate("search.waiting")); break; + case owner: sb.append(trans.translate("owned.groups")); break; + case participant: sb.append(trans.translate("search.attendee")); break; + case waiting: sb.append(trans.translate("search.waiting")); break; } } } diff --git a/src/main/java/org/olat/group/ui/main/EditMembershipController.java b/src/main/java/org/olat/group/ui/main/EditMembershipController.java index 1fba9b5f90d755f4df2285f3b35c0b5cc7099969..9010e1792891545193d8dd83950e5c6f87900736 100644 --- a/src/main/java/org/olat/group/ui/main/EditMembershipController.java +++ b/src/main/java/org/olat/group/ui/main/EditMembershipController.java @@ -29,12 +29,14 @@ import java.util.UUID; import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.EscapeMode; +import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement.Layout; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.form.flexible.impl.elements.MultipleSelectionElementImpl; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; @@ -157,7 +159,7 @@ public class EditMembershipController extends FormBasicController { loadModel(member); } - private void loadModel(Identity member) { + private void loadModel(Identity memberToLoad) { RepositoryEntryRef resource = null; SearchBusinessGroupParams params = new SearchBusinessGroupParams(); if(repoEntry == null) { @@ -168,7 +170,7 @@ public class EditMembershipController extends FormBasicController { List<BusinessGroupView> groups = businessGroupService.findBusinessGroupViews(params, resource, 0, -1); boolean defaultMembership = false; - if(member == null) { + if(memberToLoad == null) { if(repoEntry != null && groups.isEmpty()) { boolean managed = RepositoryEntryManagedFlag.isManaged(repoEntry, RepositoryEntryManagedFlag.membersmanagement); if(!managed) { @@ -183,13 +185,13 @@ public class EditMembershipController extends FormBasicController { } List<Long> businessGroupKeys = PersistenceHelper.toKeys(groups); - groupMemberships = member == null ? - Collections.<BusinessGroupMembership>emptyList() : businessGroupService.getBusinessGroupMembership(businessGroupKeys, member); + groupMemberships = memberToLoad == null ? + Collections.<BusinessGroupMembership>emptyList() : businessGroupService.getBusinessGroupMembership(businessGroupKeys, memberToLoad); List<MemberOption> options = new ArrayList<MemberOption>(); for(BusinessGroupView group:groups) { boolean managed = BusinessGroupManagedFlag.isManaged(group.getManagedFlags(), BusinessGroupManagedFlag.membersmanagement); MemberOption option = new MemberOption(group); - BGPermission bgPermission = PermissionHelper.getPermission(group.getKey(), member, groupMemberships); + BGPermission bgPermission = PermissionHelper.getPermission(group.getKey(), memberToLoad, groupMemberships); option.setTutor(createSelection(bgPermission.isTutor(), !managed)); option.setParticipant(createSelection(bgPermission.isParticipant() || defaultMembership, !managed)); boolean waitingListEnable = !managed && group.getWaitingListEnabled() != null && group.getWaitingListEnabled().booleanValue(); @@ -203,6 +205,7 @@ public class EditMembershipController extends FormBasicController { private MultipleSelectionElement createSelection(boolean selected, boolean enabled) { String name = "cb" + UUID.randomUUID().toString().replace("-", ""); MultipleSelectionElement selection = new MultipleSelectionElementImpl(name, Layout.horizontal); + selection.addActionListener(FormEvent.ONCHANGE); selection.setKeysAndValues(keys, values); flc.add(name, selection); selection.select(keys[0], selected); @@ -286,6 +289,30 @@ public class EditMembershipController extends FormBasicController { fireEvent(ureq, Event.CANCELLED_EVENT); } + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source instanceof MultipleSelectionElement) { + MultipleSelectionElement selectEl = (MultipleSelectionElement)source; + if(selectEl.isSelected(0)) { + for(MemberOption option:tableDataModel.getObjects()) { + if(option.getWaiting() == selectEl) { + if(option.getParticipant().isSelected(0)) { + option.getParticipant().select(keys[0], false); + } + if(option.getTutor().isSelected(0)) { + option.getTutor().select(keys[0], false); + } + } else if(option.getParticipant() == selectEl || option.getTutor() == selectEl) { + if(option.getWaiting() != null && option.getWaiting().isSelected(0)) { + option.getWaiting().select(keys[0], false); + } + } + } + } + } + super.formInnerEvent(ureq, source, event); + } + public void collectRepoChanges(MemberPermissionChangeEvent e) { if(repoEntry == null) return; diff --git a/src/main/java/org/olat/group/ui/main/MemberPermissionChangeEvent.java b/src/main/java/org/olat/group/ui/main/MemberPermissionChangeEvent.java index d7d7107a5f07856538194ce7778730e9e8c25245..4afaf50497be8035b3fe132445053ba5954397dd 100644 --- a/src/main/java/org/olat/group/ui/main/MemberPermissionChangeEvent.java +++ b/src/main/java/org/olat/group/ui/main/MemberPermissionChangeEvent.java @@ -83,15 +83,15 @@ public class MemberPermissionChangeEvent extends RepositoryEntryPermissionChange if(members == null || members.isEmpty()) { return Collections.emptyList(); } - List<BusinessGroupMembershipChange> groupChanges = getGroupChanges(); - if(groupChanges == null || groupChanges.isEmpty()) { + List<BusinessGroupMembershipChange> grChanges = getGroupChanges(); + if(grChanges == null || grChanges.isEmpty()) { return Collections.emptyList(); } List<BusinessGroupMembershipChange> allModifications = new ArrayList<BusinessGroupMembershipChange>(); - for(BusinessGroupMembershipChange groupChange:groupChanges) { + for(BusinessGroupMembershipChange grChange:grChanges) { for(Identity member:members) { - allModifications.add(new BusinessGroupMembershipChange(member, groupChange)); + allModifications.add(new BusinessGroupMembershipChange(member, grChange)); } } return allModifications; diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties index b998a3a44b2bb08e1131dd9310c8185ee73734b8..c62240ca6338edcfbe02e4b9bbb8085fe4aa8d2f 100644 --- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties @@ -17,6 +17,7 @@ dialog.modal.bg.mail.text=Wollen Sie die Mitglieder per Mail benachrichtigen? dialog.modal.bg.leave.text=Wenn Sie die Gruppe "{0}" verlassen, haben Sie keinen Zugang mehr.<br/> Wollen Sie die Gruppe wirklich verlassen? dialog.modal.bg.remove.text=Wollen Sie wirklich "{0}" aus dieser Gruppe entfernen? dialog.modal.bg.send.mail=Wollen Sie die betroffene(n) Person(en) per E-mail benachrichtigen? +dialog.modal.bg.asktoleave.title=Anfrage Gruppe zu verlassen remove.send.mail=Benachrichtigung remove.send.mail.label=E-mail versenden error.atleastone=Es muss mindestens einen Besitzer im Kurs geben. @@ -30,7 +31,8 @@ index.header=Gruppen index.intro=In der untenstehenden Liste finden Sie alle Gruppen, an denen Sie teilnehmen. index.table.nogroup=Sie sind in keiner Gruppe eingetragen. info.group.deleted=Die Gruppe wurde gel\u00F6scht. - +request.leaving.subject=Anfrage Gruppe "{0}" mit ID "{1}" zu verlassen +request.leaving.body=Sehr geehrter Gruppenbetreuer<br /><br />Ich m\u00F6chte dieser Gruppe verlasse<br /><br />Mit freundliche Grüsse<br />{3} {4}<br />\Gruppename: {0}<br />Gruppe ID:{1}<br />Gruppekurse: {2} menu.group.admin=Gruppenverwaltung menu.group.admin.alt=Gruppenverwaltung menu.index=Gruppen diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties index e790f71b81620c96817e5efea4ed7ead6321ffd4..be71c65f79cf9bb6700974757b408adb3917e80d 100644 --- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties @@ -36,6 +36,7 @@ dialog.modal.bg.leave.text=If you leave the group "{0}" you will no longer have dialog.modal.bg.mail.text=Do you want to inform the members of this group by email? dialog.modal.bg.remove.text=Do you really want to remove these persons "{0}" from the group? dialog.modal.bg.send.mail=Would you like to notify the respective members? +dialog.modal.bg.asktoleave.title=Group leaving request edit.member=Edit membership edit.members=Edit edit.member.groups=Group memberships @@ -90,6 +91,8 @@ owned.groups=Coach owned.groups.2=Coached pending.reservations=<h4>Accept group and course memberships</h4>You have been invited to the following groups and courses. For each listed groups and courses select the button "$\:accept" or "$\:reject" and finally save your choice with the button "$org.olat.core\:ok". You can safely skip this question now using the button "$org.olat.core\:cancel" and answer them on your next login. reject=Reject +request.leaving.subject=Request to leave group "{0}" (ID {1}) +request.leaving.body=Dear group coach<br /><br />Please remove me from this group.<br /><br />Best regards<br />{3} {4}<br /><br />Group name: {0}<br />Group ID: {1}<br />Group used in course: {2} remove.send.mail=Notification remove.send.mail.label=Send E-mail reservation.coach=as coach diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java index 7856827eb64d0ca41ebc36d0d3097d955b0c6f0a..00ad6ecfce18d401cb1361a04a2cb830bc4e9424 100644 --- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java +++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java @@ -310,8 +310,6 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im Object wildcard = ureq.getUserSession().getEntry("wild_card_" + businessGroup.getKey()); if(wildcard == null) { //check managed - //fxdiff VCRP-1,2: access control of resources - ACService acService = CoreSpringFactory.getImpl(ACService.class); AccessResult acResult = acService.isAccessible(businessGroup, getIdentity(), false); if(acResult.isAccessible()) { needActivation = false; diff --git a/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java b/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java index f44b48d9a20f90f7712b5bb5f23be7f9d17f22ca..48fa728960a6815ff71b9063399fa684fb32d119 100644 --- a/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java +++ b/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java @@ -96,17 +96,17 @@ public class BGMailTemplateController extends FormBasicController { /** * Update the given templates with the values entered in the form - * @param template + * @param mailTemplate */ - public void updateTemplateFromForm(MailTemplate template) { + public void updateTemplateFromForm(MailTemplate mailTemplate) { if(subjectElem != null) { - template.setSubjectTemplate(subjectElem.getValue()); + mailTemplate.setSubjectTemplate(subjectElem.getValue()); } if(bodyElem != null) { - template.setBodyTemplate(bodyElem.getValue()); + mailTemplate.setBodyTemplate(bodyElem.getValue()); } if(ccSender != null) { - template.setCpfrom(ccSender.isSelected(0)); + mailTemplate.setCpfrom(ccSender.isSelected(0)); } } diff --git a/src/main/java/org/olat/gui/control/OlatTopNavController.java b/src/main/java/org/olat/gui/control/OlatTopNavController.java index a3cf622d8c6c49fe946d70019dd99608d32c10f6..d7e99327bc1d7c5063f1f3be2d3e8b5ca1b8721d 100644 --- a/src/main/java/org/olat/gui/control/OlatTopNavController.java +++ b/src/main/java/org/olat/gui/control/OlatTopNavController.java @@ -30,7 +30,6 @@ import org.olat.admin.user.tools.UserToolsModule; import org.olat.core.dispatcher.DispatcherModule; import org.olat.core.extensions.ExtManager; import org.olat.core.gui.UserRequest; -import org.olat.core.gui.WindowManager; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; @@ -121,7 +120,7 @@ public class OlatTopNavController extends BasicController { List<Tool> toolSetLinksName = new ArrayList<Tool>(); Preferences prefs = ureq.getUserSession().getGuiPreferences(); - String selectedTools = (String)prefs.get(WindowManager.class, "user-tools"); + String selectedTools = userToolsModule.getUserTools(prefs); if(!StringHelper.containsNonWhitespace(selectedTools)) { selectedTools = userToolsModule.getDefaultPresetOfUserTools(); } diff --git a/src/main/java/org/olat/gui/control/UserToolsMenuController.java b/src/main/java/org/olat/gui/control/UserToolsMenuController.java index 731dd94574f4341fac2bc695a1fe500dd907af6f..61e48d9f253e36b0ad79823e3eebc997e74d6161 100644 --- a/src/main/java/org/olat/gui/control/UserToolsMenuController.java +++ b/src/main/java/org/olat/gui/control/UserToolsMenuController.java @@ -1,3 +1,22 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ package org.olat.gui.control; import java.util.ArrayList; @@ -11,7 +30,6 @@ import org.olat.admin.user.tools.UserToolExtension; import org.olat.admin.user.tools.UserToolsModule; import org.olat.basesecurity.AuthHelper; import org.olat.core.gui.UserRequest; -import org.olat.core.gui.WindowManager; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Disposable; @@ -60,7 +78,7 @@ public class UserToolsMenuController extends BasicController { List<String> systemLinksName = new ArrayList<String>(); Preferences prefs = ureq.getUserSession().getGuiPreferences(); - String selectedTools = (String)prefs.get(WindowManager.class, "user-tools"); + String selectedTools = userToolsModule.getUserTools(prefs); if(!StringHelper.containsNonWhitespace(selectedTools)) { selectedTools = userToolsModule.getDefaultPresetOfUserTools(); } diff --git a/src/main/java/org/olat/gui/control/_content/menu.html b/src/main/java/org/olat/gui/control/_content/menu.html index 844aa364400604d1e1c71dd2341825ca102b0c80..1a1856dce9c99193dd15a0edb29762995e3efc50 100644 --- a/src/main/java/org/olat/gui/control/_content/menu.html +++ b/src/main/java/org/olat/gui/control/_content/menu.html @@ -3,19 +3,25 @@ #foreach($search in $searchs) <li>$r.render($search)</li> #end - <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.tools")</li> - #foreach($personalTool in $personalTools) - <li>$r.render($personalTool)</li> + #if($personalTools.size() > 0) + <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.tools")</li> + #foreach($personalTool in $personalTools) + <li>$r.render($personalTool)</li> + #end #end - <li role="presentation" class="divider"></li> - <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.configurations")</li> - #foreach($config in $configs) - <li>$r.render($config)</li> + #if($configs.size() > 0) + <li role="presentation" class="divider"></li> + <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.configurations")</li> + #foreach($config in $configs) + <li>$r.render($config)</li> + #end #end - <li role="presentation" class="divider"></li> - <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.systems")</li> - #foreach($system in $systems) - <li>$r.render($system)</li> + #if($systems.size() > 0) + <li role="presentation" class="divider"></li> + <li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.systems")</li> + #foreach($system in $systems) + <li>$r.render($system)</li> + #end #end <li role="presentation" class="divider"></li> <li> diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_10_1_0.java b/src/main/java/org/olat/upgrade/OLATUpgrade_10_1_0.java new file mode 100644 index 0000000000000000000000000000000000000000..362b86f9207a4c17c76a51ccca9ac146bce2992f --- /dev/null +++ b/src/main/java/org/olat/upgrade/OLATUpgrade_10_1_0.java @@ -0,0 +1,134 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.upgrade; + +import org.olat.admin.user.tools.UserToolsModule; +import org.olat.core.commons.persistence.DB; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 27.02.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class OLATUpgrade_10_1_0 extends OLATUpgrade { + + private static final String TASK_USER_TOOLS = "Upgrade user tools"; + private static final String VERSION = "OLAT_10.1.0"; + + @Autowired + private DB dbInstance; + @Autowired + private UserToolsModule userToolsModule; + + + public OLATUpgrade_10_1_0() { + super(); + } + + @Override + public String getVersion() { + return VERSION; + } + + @Override + public boolean doPreSystemInitUpgrade(UpgradeManager upgradeManager) { + return false; + } + + @Override + public boolean doPostSystemInitUpgrade(UpgradeManager upgradeManager) { + UpgradeHistoryData uhd = upgradeManager.getUpgradesHistory(VERSION); + if (uhd == null) { + // has never been called, initialize + uhd = new UpgradeHistoryData(); + } else if (uhd.isInstallationComplete()) { + return false; + } + + boolean allOk = true; + allOk &= upgradeUserTools(upgradeManager, uhd); + + + uhd.setInstallationComplete(allOk); + upgradeManager.setUpgradesHistory(uhd, VERSION); + if(allOk) { + log.audit("Finished OLATUpgrade_10_1_0 successfully!"); + } else { + log.audit("OLATUpgrade_10_1_0 not finished, try to restart OpenOLAT!"); + } + return allOk; + } + + /** + * Add the static tools to the configurable ones. + * + * @param upgradeManager + * @param uhd + * @return + */ + private boolean upgradeUserTools(UpgradeManager upgradeManager, UpgradeHistoryData uhd) { + if (!uhd.getBooleanDataValue(TASK_USER_TOOLS)) { + try { + String tools = userToolsModule.getAvailableUserTools(); + StringBuilder toolsSb = new StringBuilder(tools); + String[] defaultUserTools = new String[]{ + "org.olat.home.HomeMainController:org.olat.gui.control.PrintUserToolExtension", + "org.olat.home.HomeMainController:org.olat.gui.control.SearchUserToolExtension", + "org.olat.home.HomeMainController:org.olat.gui.control.HelpUserToolExtension", + "org.olat.home.HomeMainController:org.olat.instantMessaging.ui.ImpressumMainController", + "org.olat.home.HomeMainController:org.olat.instantMessaging.ui.InstantMessagingMainController" + }; + + for(String defaultUserTool:defaultUserTools) { + if(toolsSb.indexOf(defaultUserTool) < 0) { + if(toolsSb.length() > 0) toolsSb.append(","); + toolsSb.append(defaultUserTool); + } + } + userToolsModule.setAvailableUserTools(toolsSb.toString()); + + String defPreset = userToolsModule.getDefaultPresetOfUserTools(); + StringBuilder defPresetSb = new StringBuilder(defPreset); + String[] defaultPresets = new String[]{ + "org.olat.home.HomeMainController:org.olat.gui.control.PrintUserToolExtension", + "org.olat.home.HomeMainController:org.olat.gui.control.HelpUserToolExtension", + "org.olat.home.HomeMainController:org.olat.instantMessaging.ui.ImpressumMainController" + }; + + for(String defaultPreset:defaultPresets) { + if(defPresetSb.indexOf(defaultPreset) < 0) { + if(defPresetSb.length() > 0) defPresetSb.append(","); + defPresetSb.append(defaultPreset); + } + } + userToolsModule.setDefaultPresetOfUserTools(defPresetSb.toString()); + + uhd.setBooleanDataValue(TASK_USER_TOOLS, false); + upgradeManager.setUpgradesHistory(uhd, VERSION); + } catch (Exception e) { + log.error("", e); + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml index 6aca92e0cdaa7b9bada90639c955bb86137224c3..1114906de85ac21ecc55ee7871e39ad9c992a788 100644 --- a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml +++ b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml @@ -42,6 +42,7 @@ <bean id="upgrade_9_4_0" class="org.olat.upgrade.OLATUpgrade_9_4_0"/> <bean id="upgrade_10_0_0" class="org.olat.upgrade.OLATUpgrade_10_0_0"/> <bean id="upgrade_10_0_3" class="org.olat.upgrade.OLATUpgrade_10_0_3"/> + <bean id="upgrade_10_1_0" class="org.olat.upgrade.OLATUpgrade_10_1_0"/> </list> </property> </bean> diff --git a/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.hbm.xml b/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.hbm.xml index 32b2b041886bfb473c49f1472f02a37c491dc28d..c70d328087f0559069522a448ca35f1f912923f7 100644 --- a/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.hbm.xml +++ b/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.hbm.xml @@ -39,6 +39,7 @@ <property name="waitingListVisibleIntern" column="waitingintern" unique="false" not-null="true" type="boolean"/> <property name="waitingListVisiblePublic" column="waitingpublic" unique="false" not-null="true" type="boolean"/> <property name="downloadMembersLists" column="downloadmembers" unique="false" not-null="true" type="boolean"/> + <property name="allowToLeave" column="allowtoleave" unique="false" not-null="true" type="boolean"/> <property name="name" type="string" column="groupname" unique="false" length="255" index="gp_name_idx"/> <property name="description" type="string" column="descr" length="16777210" not-null="false"/> diff --git a/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.java b/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.java index 5cd15c4c03b1ec3553bea1cb2c292e30f48ecd53..2df40f3c479a31384beef2c7f4d06650f8e7d447 100644 --- a/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.java +++ b/src/main/java/org/olat/upgrade/model/BusinessGroupUpgrade.java @@ -76,6 +76,7 @@ public class BusinessGroupUpgrade extends PersistentObject implements BusinessGr private boolean participantsVisiblePublic; private boolean waitingListVisiblePublic; private boolean downloadMembersLists; + private boolean allowToLeave; /** * constructs an unitialised BusinessGroup, use setXXX for setting attributes @@ -209,6 +210,14 @@ public class BusinessGroupUpgrade extends PersistentObject implements BusinessGr this.downloadMembersLists = visible; } + public boolean isAllowToLeave() { + return allowToLeave; + } + + public void setAllowToLeave(boolean allow) { + this.allowToLeave = allow; + } + public OLATResource getResource() { return resource; } diff --git a/src/main/java/org/olat/user/ToolsPrefsController.java b/src/main/java/org/olat/user/ToolsPrefsController.java index dedb09eabf4029aab7381a587fd1d739dd53321f..efe020d08d0f04fb11e85bbc035383614dced28e 100644 --- a/src/main/java/org/olat/user/ToolsPrefsController.java +++ b/src/main/java/org/olat/user/ToolsPrefsController.java @@ -28,7 +28,6 @@ import org.olat.admin.user.tools.UserToolExtension; import org.olat.admin.user.tools.UserToolsModule; import org.olat.core.extensions.ExtManager; import org.olat.core.gui.UserRequest; -import org.olat.core.gui.WindowManager; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; @@ -153,7 +152,7 @@ public class ToolsPrefsController extends FormBasicController { } private void initPresetElementUserData() { - String selectedTools = (String)prefs.get(WindowManager.class, "user-tools"); + String selectedTools = userToolsModule.getUserTools(prefs); if(!StringHelper.containsNonWhitespace(selectedTools)) { // use presets when user has not yet any values selectedTools = userToolsModule.getDefaultPresetOfUserTools(); @@ -184,7 +183,6 @@ public class ToolsPrefsController extends FormBasicController { } else { sb.append("none"); } - prefs.put(WindowManager.class, "user-tools", sb.toString()); - prefs.save(); + userToolsModule.setUserTools(prefs, sb.toString()); } } diff --git a/src/main/resources/database/mysql/alter_10_0_0_to_10_1_0.sql b/src/main/resources/database/mysql/alter_10_0_0_to_10_1_0.sql index 637bca792d972384a509e26ef3ce47973d68e1a5..19e86cc3ca10add3d0015bfa224d57642e8d8e66 100644 --- a/src/main/resources/database/mysql/alter_10_0_0_to_10_1_0.sql +++ b/src/main/resources/database/mysql/alter_10_0_0_to_10_1_0.sql @@ -30,6 +30,9 @@ create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource create index cer_uuid_idx on o_cer_certificate (c_uuid); +alter table o_gp_business add column allowtoleave boolean default 1; + + drop view o_qp_item_shared_v; drop view o_qp_item_pool_v; drop view o_qp_item_author_v; diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index 69a7702c136c19e0619d2dfd9b96388915b9312b..1fd3d14d3d80b4d3be0b77100dc6770922cc78e3 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -78,6 +78,7 @@ create table if not exists o_gp_business ( participantspublic bit not null default 0, waitingpublic bit not null default 0, downloadmembers bit not null default 0, + allowtoleave bit not null default 1, fk_resource bigint unique, fk_group_id bigint unique, primary key (group_id) diff --git a/src/main/resources/database/oracle/alter_10_0_0_to_10_1_0.sql b/src/main/resources/database/oracle/alter_10_0_0_to_10_1_0.sql index 86f0942f793d7cdb2f2db4828bd4dffd9a647049..c420ed598d37495eb79c08fa5590811bb54debf0 100644 --- a/src/main/resources/database/oracle/alter_10_0_0_to_10_1_0.sql +++ b/src/main/resources/database/oracle/alter_10_0_0_to_10_1_0.sql @@ -1,3 +1,38 @@ +create table o_cer_template ( + id number(20) not null, + creationdate date not null, + lastmodified date not null, + c_name varchar2(256 char) not null, + c_path varchar2(1024 char) not null, + c_public number default 0 not null, + primary key (id) +); + +create table o_cer_certificate ( + id number(20) not null, + creationdate date not null, + lastmodified date not null, + c_uuid varchar2(36 char) not null, + c_name varchar2(256 char) not null, + c_path varchar2(1024 char) not null, + c_last number default 1 not null, + c_archived_resource_id number(20) not null, + fk_olatresource number(20), + fk_identity number(20) not null, + primary key (id) +); + +alter table o_cer_certificate add constraint cer_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index cer_identity_idx on o_cer_certificate (fk_identity); +alter table o_cer_certificate add constraint cer_to_resource_idx foreign key (fk_olatresource) references o_olatresource (resource_id); +create index cer_resource_idx on o_cer_certificate (fk_olatresource); +create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource_id); +create index cer_uuid_idx on o_cer_certificate (c_uuid); + + +alter table o_gp_business add allowtoleave number default 1 not null; + + drop view o_qp_item_shared_v; drop view o_qp_item_pool_v; drop view o_qp_item_author_v; diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql index fef80cd1c40ed1146eb6a3c601dcc5c5824dde7d..6c02e56268757b7e7dcc57417926235ba8e5fe88 100644 --- a/src/main/resources/database/oracle/setupDatabase.sql +++ b/src/main/resources/database/oracle/setupDatabase.sql @@ -83,6 +83,7 @@ CREATE TABLE o_gp_business ( participantspublic number default 0 not null, waitingpublic number default 0 not null, downloadmembers number default 0 not null, + allowtoleave number default 1 not null, fk_resource number(20), fk_group_id number(20), CONSTRAINT u_o_gp_business03 UNIQUE (fk_resource), @@ -1093,6 +1094,30 @@ create table o_as_user_course_infos ( primary key (id) ); +create table o_cer_template ( + id number(20) not null, + creationdate date not null, + lastmodified date not null, + c_name varchar2(256 char) not null, + c_path varchar2(1024 char) not null, + c_public number default 0 not null, + primary key (id) +); + +create table o_cer_certificate ( + id number(20) not null, + creationdate date not null, + lastmodified date not null, + c_uuid varchar2(36 char) not null, + c_name varchar2(256 char) not null, + c_path varchar2(1024 char) not null, + c_last number default 1 not null, + c_archived_resource_id number(20) not null, + fk_olatresource number(20), + fk_identity number(20) not null, + primary key (id) +); + create table o_im_message ( id number(20) not null, creationdate date, @@ -2185,6 +2210,14 @@ create index idx_lti_outcome_ident_id_idx on o_lti_outcome (fk_identity_id); alter table o_lti_outcome add constraint idx_lti_outcome_rsrc_id foreign key (fk_resource_id) references o_olatresource(resource_id); create index idx_lti_outcome_rsrc_id_idx on o_lti_outcome (fk_resource_id); +--certificates +alter table o_cer_certificate add constraint cer_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index cer_identity_idx on o_cer_certificate (fk_identity); +alter table o_cer_certificate add constraint cer_to_resource_idx foreign key (fk_olatresource) references o_olatresource (resource_id); +create index cer_resource_idx on o_cer_certificate (fk_olatresource); +create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource_id); +create index cer_uuid_idx on o_cer_certificate (c_uuid); + insert into o_stat_lastupdated (until_datetime, lastupdated) values (to_date('1999-01-01', 'YYYY-mm-dd'), to_date('1999-01-01', 'YYYY-mm-dd')); insert into hibernate_unique_key values ( 0 ); diff --git a/src/main/resources/database/postgresql/alter_10_0_0_to_10_1_0.sql b/src/main/resources/database/postgresql/alter_10_0_0_to_10_1_0.sql index 3fb3ab11fd1a2a81e4c4f93cd9b16d7fc26e69fa..1c5827722188f511389b7e0909d7f898491f1825 100644 --- a/src/main/resources/database/postgresql/alter_10_0_0_to_10_1_0.sql +++ b/src/main/resources/database/postgresql/alter_10_0_0_to_10_1_0.sql @@ -30,6 +30,9 @@ create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource create index cer_uuid_idx on o_cer_certificate (c_uuid); +alter table o_gp_business add column allowtoleave bool not null default true; + + drop view o_qp_item_shared_v; drop view o_qp_item_pool_v; drop view o_qp_item_author_v; diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 5479d5704d144b2ffd64c20e0b11383c4acb81e0..daca63302befb76cbb9dd473eac1ae629cb28a26 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -76,6 +76,7 @@ create table o_gp_business ( participantspublic bool not null default false, waitingpublic bool not null default false, downloadmembers bool not null default false, + allowtoleave bool not null default true, fk_resource int8 unique, fk_group_id int8 unique, primary key (group_id) diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 1821bde5127d4ea11acbe2c5d78809591d19145c..e78a0e233c5459ed0caeab0c20d4fcbbf45a83d0 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -248,6 +248,13 @@ group.accept.membership.usermanagers=false group.accept.membership.groupmanagers=false group.accept.membership.administrators=false +# Allow leaving groups created by learners +group.leaving.group.created.by.learners=true +# Allow leaving groups created by authors +group.leaving.group.created.by.authors=true +# Allow configuration of this settoing on a per-groupe base +group.leaving.group.override=true + #enable managed groups group.managed=false group.managed.values=true,false diff --git a/src/test/java/org/olat/group/test/BGRightManagerTest.java b/src/test/java/org/olat/group/test/BGRightManagerTest.java index e9c2b7d53384187c22183d0828bfd0c226ceff16..5c0b005eae2104f9b048df3ceb3754621a22fdf2 100644 --- a/src/test/java/org/olat/group/test/BGRightManagerTest.java +++ b/src/test/java/org/olat/group/test/BGRightManagerTest.java @@ -194,15 +194,15 @@ public class BGRightManagerTest extends OlatTestCase { @Test public void hasBGRightWithResource_tutor_participant() { //create 2 rights for the three identities - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("tp-rights-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("tp-rights-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("tp-rights-" + UUID.randomUUID().toString()); + Identity identity1 = JunitTestHelper.createAndPersistIdentityAsUser("tp-rights-" + UUID.randomUUID().toString()); + Identity identity2 = JunitTestHelper.createAndPersistIdentityAsUser("tp-rights-" + UUID.randomUUID().toString()); + Identity identity3 = JunitTestHelper.createAndPersistIdentityAsUser("tp-rights-" + UUID.randomUUID().toString()); RepositoryEntry resource = JunitTestHelper.createAndPersistRepositoryEntry(); BusinessGroup group = businessGroupService.createBusinessGroup(null, "tpBGRight", null, -1, -1, false, false, resource); - businessGroupRelationDao.addRole(id1, group, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id2, group, GroupRoles.coach.name()); - businessGroupRelationDao.addRole(id2, group, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id3, group, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(identity1, group, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(identity2, group, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(identity2, group, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(identity3, group, GroupRoles.coach.name()); rightManager.addBGRight("bgr.right1", group, resource.getOlatResource(), BGRightsRole.tutor); rightManager.addBGRight("bgr.right2", group, resource.getOlatResource(), BGRightsRole.participant); dbInstance.commitAndCloseSession(); @@ -216,14 +216,14 @@ public class BGRightManagerTest extends OlatTestCase { Assert.assertEquals("bgr.right2", participantRights.get(0)); //id1 -> right2 - Assert.assertFalse(rightManager.hasBGRight("bgr.right1", id1, resource.getOlatResource())); - Assert.assertTrue(rightManager.hasBGRight("bgr.right2", id1, resource.getOlatResource())); + Assert.assertFalse(rightManager.hasBGRight("bgr.right1", identity1, resource.getOlatResource())); + Assert.assertTrue(rightManager.hasBGRight("bgr.right2", identity1, resource.getOlatResource())); //id2 -> right1 and right2 - Assert.assertTrue(rightManager.hasBGRight("bgr.right1", id2, resource.getOlatResource())); - Assert.assertTrue(rightManager.hasBGRight("bgr.right2", id2, resource.getOlatResource())); + Assert.assertTrue(rightManager.hasBGRight("bgr.right1", identity2, resource.getOlatResource())); + Assert.assertTrue(rightManager.hasBGRight("bgr.right2", identity2, resource.getOlatResource())); //id3 -> right2 - Assert.assertTrue(rightManager.hasBGRight("bgr.right1", id3, resource.getOlatResource())); - Assert.assertFalse(rightManager.hasBGRight("bgr.right2", id3, resource.getOlatResource())); + Assert.assertTrue(rightManager.hasBGRight("bgr.right1", identity3, resource.getOlatResource())); + Assert.assertFalse(rightManager.hasBGRight("bgr.right2", identity3, resource.getOlatResource())); } @Test diff --git a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java index fdcdefcab720cffde314608a9030f987e260f950..b17ff247e7717fff87628af41678c3d88ff739e9 100644 --- a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java +++ b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java @@ -506,6 +506,19 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase { Assert.assertTrue(participant6.contains(part4)); } + @Test + public void countAuthors() { + 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 numOfAuthors = businessGroupRelationDao.countAuthors(group); + Assert.assertEquals(1, numOfAuthors); + } + @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/group/test/BusinessGroupServiceTest.java b/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java index 8a8fd4b18c1341e01cbad32565e27b3cb2cc4e5d..4a3e2d89cdd7bcf64d9c7176b4d061642cc4a982 100644 --- a/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java +++ b/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java @@ -24,12 +24,14 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.UUID; import junit.framework.Assert; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.olat.basesecurity.BaseSecurity; @@ -43,11 +45,14 @@ import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.core.id.Roles; import org.olat.core.id.User; +import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.MailPackage; import org.olat.group.BusinessGroup; +import org.olat.group.BusinessGroupModule; import org.olat.group.BusinessGroupService; import org.olat.group.manager.BusinessGroupRelationDAO; import org.olat.group.model.BusinessGroupMembershipChange; +import org.olat.group.model.LeaveOption; import org.olat.group.model.MembershipModification; import org.olat.group.model.SearchBusinessGroupParams; import org.olat.repository.RepositoryEntry; @@ -82,6 +87,8 @@ public class BusinessGroupServiceTest extends OlatTestCase { @Autowired private BusinessGroupRelationDAO businessGroupRelationDao; @Autowired + private BusinessGroupModule businessGroupModule; + @Autowired private BusinessGroupService businessGroupService; // Identities for tests @@ -173,6 +180,13 @@ public class BusinessGroupServiceTest extends OlatTestCase { initialize = true; } + @After + public void resetBusinessGroupModule() { + businessGroupModule.setAllowLeavingGroupCreatedByAuthors(true); + businessGroupModule.setAllowLeavingGroupCreatedByLearners(true); + businessGroupModule.setAllowLeavingGroupOverride(true); + } + @Test public void should_service_present() { Assert.assertNotNull(businessGroupService); @@ -252,24 +266,24 @@ public class BusinessGroupServiceTest extends OlatTestCase { @Test public void testUpdateBusinessGroupAndAutoRank_v1() { //create a group with 1 participant and 2 users in waiting list - Identity id0 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-0-" + UUID.randomUUID().toString()); - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-3-" + UUID.randomUUID().toString()); - Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-4-" + UUID.randomUUID().toString()); + Identity ident0 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-0-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-3-" + UUID.randomUUID().toString()); + Identity ident4 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-4-" + UUID.randomUUID().toString()); RepositoryEntry resource = JunitTestHelper.createAndPersistRepositoryEntry(); - BusinessGroup group = businessGroupService.createBusinessGroup(id0, "auto-1", "auto-1-desc", new Integer(0), new Integer(1), true, true, resource); + BusinessGroup group = businessGroupService.createBusinessGroup(ident0, "auto-1", "auto-1-desc", new Integer(0), new Integer(1), true, true, resource); Assert.assertNotNull(group); - businessGroupRelationDao.addRole(id1, group, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id2, group, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id3, group, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id4, group, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident1, group, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident2, group, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident3, group, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident4, group, GroupRoles.waiting.name()); dbInstance.commitAndCloseSession(); //update max participants - BusinessGroup updateGroup = businessGroupService.updateBusinessGroup(id0, group, "auto-1", "auto-1-desc", null, null, new Integer(0), new Integer(3)); + BusinessGroup updateGroup = businessGroupService.updateBusinessGroup(ident0, group, "auto-1", "auto-1-desc", null, null, new Integer(0), new Integer(3)); Assert.assertNotNull(updateGroup); dbInstance.commitAndCloseSession(); @@ -277,7 +291,7 @@ public class BusinessGroupServiceTest extends OlatTestCase { List<Identity> participants = businessGroupRelationDao.getMembers(group, GroupRoles.participant.name()); Assert.assertNotNull(participants); Assert.assertEquals(3, participants.size()); - Assert.assertTrue(participants.contains(id1)); + Assert.assertTrue(participants.contains(ident1)); List<Identity> waitingList = businessGroupRelationDao.getMembers(group, GroupRoles.waiting.name()); Assert.assertNotNull(waitingList); @@ -287,24 +301,24 @@ public class BusinessGroupServiceTest extends OlatTestCase { @Test public void testUpdateBusinessGroupAndAutoRank_v2() { //create a group with 1 participant and 2 users in waiting list - Identity id0 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-0-" + UUID.randomUUID().toString()); - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-3-" + UUID.randomUUID().toString()); - Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-4-" + UUID.randomUUID().toString()); + Identity ident0 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-0-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-3-" + UUID.randomUUID().toString()); + Identity ident4 = JunitTestHelper.createAndPersistIdentityAsUser("grp-auto-4-" + UUID.randomUUID().toString()); RepositoryEntry resource = JunitTestHelper.createAndPersistRepositoryEntry(); - BusinessGroup group = businessGroupService.createBusinessGroup(id0, "auto-1", "auto-1-desc", new Integer(0), new Integer(1), false, false, resource); + BusinessGroup group = businessGroupService.createBusinessGroup(ident0, "auto-1", "auto-1-desc", new Integer(0), new Integer(1), false, false, resource); Assert.assertNotNull(group); - businessGroupRelationDao.addRole(id1, group, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id2, group, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id3, group, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id4, group, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident1, group, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident2, group, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident3, group, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident4, group, GroupRoles.waiting.name()); dbInstance.commitAndCloseSession(); //update max participants - BusinessGroup updateGroup = businessGroupService.updateBusinessGroup(id0, group, "auto-1", "auto-1-desc", new Integer(0), new Integer(3), Boolean.TRUE, Boolean.TRUE); + BusinessGroup updateGroup = businessGroupService.updateBusinessGroup(ident0, group, "auto-1", "auto-1-desc", new Integer(0), new Integer(3), Boolean.TRUE, Boolean.TRUE); Assert.assertNotNull(updateGroup); dbInstance.commitAndCloseSession(); @@ -312,7 +326,7 @@ public class BusinessGroupServiceTest extends OlatTestCase { List<Identity> participants = businessGroupRelationDao.getMembers(group, GroupRoles.participant.name()); Assert.assertNotNull(participants); Assert.assertEquals(3, participants.size()); - Assert.assertTrue(participants.contains(id1)); + Assert.assertTrue(participants.contains(ident1)); List<Identity> waitingList = businessGroupRelationDao.getMembers(group, GroupRoles.waiting.name()); Assert.assertNotNull(waitingList); @@ -352,24 +366,24 @@ public class BusinessGroupServiceTest extends OlatTestCase { @Test public void mergeGroups() { //create some identities - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("merge-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("merge-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("merge-3-" + UUID.randomUUID().toString()); - Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("merge-4-" + UUID.randomUUID().toString()); - Identity id5 = JunitTestHelper.createAndPersistIdentityAsUser("merge-5-" + UUID.randomUUID().toString()); - Identity id6 = JunitTestHelper.createAndPersistIdentityAsUser("merge-6-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("merge-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("merge-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("merge-3-" + UUID.randomUUID().toString()); + Identity ident4 = JunitTestHelper.createAndPersistIdentityAsUser("merge-4-" + UUID.randomUUID().toString()); + Identity ident5 = JunitTestHelper.createAndPersistIdentityAsUser("merge-5-" + UUID.randomUUID().toString()); + Identity ident6 = JunitTestHelper.createAndPersistIdentityAsUser("merge-6-" + UUID.randomUUID().toString()); //create groups and memberships BusinessGroup g1 = businessGroupService.createBusinessGroup(null, "old-1", null, 0, 10, false, false, null); - businessGroupRelationDao.addRole(id1, g1, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id2, g1, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id3, g1, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(ident1, g1, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident2, g1, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident3, g1, GroupRoles.coach.name()); BusinessGroup g2 = businessGroupService.createBusinessGroup(null, "old-2", null, 0, 10, false, false, null); - businessGroupRelationDao.addRole(id2, g2, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id4, g2, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id5, g2, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id6, g2, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(ident2, g2, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident4, g2, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident5, g2, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident6, g2, GroupRoles.coach.name()); BusinessGroup g3 = businessGroupService.createBusinessGroup(null, "target", null, 0, 10, false, false, null); - businessGroupRelationDao.addRole(id1, g3, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident1, g3, GroupRoles.participant.name()); dbInstance.commitAndCloseSession(); //merge @@ -386,18 +400,18 @@ public class BusinessGroupServiceTest extends OlatTestCase { List<Identity> owners = businessGroupRelationDao.getMembers(mergedGroup, GroupRoles.coach.name()); Assert.assertNotNull(owners); Assert.assertEquals(2, owners.size()); - Assert.assertTrue(owners.contains(id3)); - Assert.assertTrue(owners.contains(id6)); + Assert.assertTrue(owners.contains(ident3)); + Assert.assertTrue(owners.contains(ident6)); List<Identity> participants = businessGroupRelationDao.getMembers(mergedGroup, GroupRoles.participant.name()); Assert.assertNotNull(participants); Assert.assertEquals(3, participants.size()); - Assert.assertTrue(participants.contains(id1)); - Assert.assertTrue(participants.contains(id2)); - Assert.assertTrue(participants.contains(id5)); + Assert.assertTrue(participants.contains(ident1)); + Assert.assertTrue(participants.contains(ident2)); + Assert.assertTrue(participants.contains(ident5)); List<Identity> waitingList = businessGroupRelationDao.getMembers(mergedGroup, GroupRoles.waiting.name()); Assert.assertNotNull(waitingList); Assert.assertEquals(1, waitingList.size()); - Assert.assertTrue(waitingList.contains(id4)); + Assert.assertTrue(waitingList.contains(ident4)); } /** @@ -454,24 +468,24 @@ public class BusinessGroupServiceTest extends OlatTestCase { throws Exception { //add 2 identities in waiting group and 1 in as participant Identity admin = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-0-" + UUID.randomUUID().toString()); - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-3-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("move-w1-3-" + UUID.randomUUID().toString()); BusinessGroup group = businessGroupService.createBusinessGroup(null, "move-bg-1", "move-desc", 0, 10, true, false, null); - businessGroupService.addToWaitingList(admin, Collections.singletonList(id1), group, null); - businessGroupService.addToWaitingList(admin, Collections.singletonList(id2), group, null); - businessGroupService.addParticipants(admin, JunitTestHelper.getAdminRoles(), Collections.singletonList(id3), group, null); + businessGroupService.addToWaitingList(admin, Collections.singletonList(ident1), group, null); + businessGroupService.addToWaitingList(admin, Collections.singletonList(ident2), group, null); + businessGroupService.addParticipants(admin, JunitTestHelper.getAdminRoles(), Collections.singletonList(ident3), group, null); dbInstance.commitAndCloseSession(); //move id1 from waiting-list to participant - List<Identity> identities = Collections.singletonList(id1); + List<Identity> identities = Collections.singletonList(ident1); businessGroupService.moveIdentityFromWaitingListToParticipant(admin, identities, group, null); //check position of 'id2' - int pos = businessGroupService.getPositionInWaitingListFor(id2, group); + int pos = businessGroupService.getPositionInWaitingListFor(ident2, group); Assert.assertEquals("pos must be 1, bit is=" + pos, 1, pos); //check if 'id3' is in participant-list - boolean negatifCheck = businessGroupService.isIdentityInBusinessGroup(id3, group); + boolean negatifCheck = businessGroupService.isIdentityInBusinessGroup(ident3, group); assertTrue("Identity is not in participant-list", negatifCheck); } @@ -481,29 +495,29 @@ public class BusinessGroupServiceTest extends OlatTestCase { @Test public void testAddToWaitingListAndFireEventAndCheckPosition() throws Exception { //add 2 identities in waiting group and 1 in as participant - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w2-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w2-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("move-w2-3-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w2-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w2-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("move-w2-3-" + UUID.randomUUID().toString()); BusinessGroup group = businessGroupService.createBusinessGroup(null, "move-bg-1", "move-desc", 0, 10, true, false, null); //add id1 - businessGroupService.addToWaitingList(id1, Collections.singletonList(id1), group, null); + businessGroupService.addToWaitingList(ident1, Collections.singletonList(ident1), group, null); dbInstance.commitAndCloseSession(); //add id2 - businessGroupService.addToWaitingList(id2, Collections.singletonList(id2), group, null); + businessGroupService.addToWaitingList(ident2, Collections.singletonList(ident2), group, null); dbInstance.commitAndCloseSession(); //add id3 - businessGroupService.addToWaitingList(id3, Collections.singletonList(id3), group, null); + businessGroupService.addToWaitingList(ident3, Collections.singletonList(ident3), group, null); dbInstance.commitAndCloseSession(); // Check position of 'id1' - int pos1 = businessGroupService.getPositionInWaitingListFor(id1, group); + int pos1 = businessGroupService.getPositionInWaitingListFor(ident1, group); Assert.assertEquals("pos must be 1, bit is=" + pos1, 1, pos1); // Check position of 'id2' - int pos2 = businessGroupService.getPositionInWaitingListFor(id2, group); + int pos2 = businessGroupService.getPositionInWaitingListFor(ident2, group); Assert.assertEquals("pos must be 2, bit is=" + pos2, 2, pos2); // Check position of 'id3' - int pos3 = businessGroupService.getPositionInWaitingListFor(id3, group); + int pos3 = businessGroupService.getPositionInWaitingListFor(ident3, group); Assert.assertEquals("pos must be 3, bit is=" + pos3, 3, pos3); } @@ -514,49 +528,49 @@ public class BusinessGroupServiceTest extends OlatTestCase { @Test public void testRemoveFromWaitingListAndFireEvent() throws Exception { //add 3 identities in waiting group - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w3-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w3-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("move-w3-3-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w3-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w3-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("move-w3-3-" + UUID.randomUUID().toString()); BusinessGroup group = businessGroupService.createBusinessGroup(null, "move-bg-3", "move-desc", 0, 10, true, false, null); - businessGroupService.addToWaitingList(id1, Collections.singletonList(id1), group, null); - businessGroupService.addToWaitingList(id2, Collections.singletonList(id2), group, null); - businessGroupService.addToWaitingList(id3, Collections.singletonList(id3), group, null); + businessGroupService.addToWaitingList(ident1, Collections.singletonList(ident1), group, null); + businessGroupService.addToWaitingList(ident2, Collections.singletonList(ident2), group, null); + businessGroupService.addToWaitingList(ident3, Collections.singletonList(ident3), group, null); dbInstance.commitAndCloseSession(); //remove id2 - businessGroupService.removeFromWaitingList(wg1, Collections.singletonList(id2), group, null); + businessGroupService.removeFromWaitingList(wg1, Collections.singletonList(ident2), group, null); dbInstance.commitAndCloseSession(); //check position of 'id1' - int pos1 = businessGroupService.getPositionInWaitingListFor(id1, group); + int pos1 = businessGroupService.getPositionInWaitingListFor(ident1, group); Assert.assertEquals("pos must be 1, bit is=" + pos1, 1, pos1); //check position of 'id3' - int pos3 = businessGroupService.getPositionInWaitingListFor(id3, group); + int pos3 = businessGroupService.getPositionInWaitingListFor(ident3, group); Assert.assertEquals("pos must be 2, bit is=" + pos3, 2, pos3); //check position of id2 - int pos2 = businessGroupService.getPositionInWaitingListFor(id2, group); + int pos2 = businessGroupService.getPositionInWaitingListFor(ident2, group); Assert.assertEquals("pos must be -1, not in list bit is=" + pos2, -1, pos2); } @Test public void testRemoveMembers() { Identity admin = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-0-" + UUID.randomUUID().toString()); - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-2-" + UUID.randomUUID().toString()); - Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-3-" + UUID.randomUUID().toString()); - Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-4-" + UUID.randomUUID().toString()); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-2-" + UUID.randomUUID().toString()); + Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-3-" + UUID.randomUUID().toString()); + Identity ident4 = JunitTestHelper.createAndPersistIdentityAsUser("rm-w3-4-" + UUID.randomUUID().toString()); RepositoryEntry resource = JunitTestHelper.createAndPersistRepositoryEntry(); - BusinessGroup group1 = businessGroupService.createBusinessGroup(id1, "move-bg-3", "move-desc", 0, 10, true, false, resource); - BusinessGroup group2 = businessGroupService.createBusinessGroup(id2, "move-bg-3", "move-desc", 0, 10, true, false, resource); - BusinessGroup group3 = businessGroupService.createBusinessGroup(id3, "move-bg-3", "move-desc", 0, 10, true, false, resource); - - businessGroupRelationDao.addRole(id2, group1, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id3, group1, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id3, group2, GroupRoles.waiting.name()); - businessGroupRelationDao.addRole(id2, group2, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id1, group3, GroupRoles.coach.name()); - businessGroupRelationDao.addRole(id2, group3, GroupRoles.participant.name()); - businessGroupRelationDao.addRole(id4, group3, GroupRoles.waiting.name()); + BusinessGroup group1 = businessGroupService.createBusinessGroup(ident1, "move-bg-3", "move-desc", 0, 10, true, false, resource); + BusinessGroup group2 = businessGroupService.createBusinessGroup(ident2, "move-bg-3", "move-desc", 0, 10, true, false, resource); + BusinessGroup group3 = businessGroupService.createBusinessGroup(ident3, "move-bg-3", "move-desc", 0, 10, true, false, resource); + + businessGroupRelationDao.addRole(ident2, group1, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident3, group1, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident3, group2, GroupRoles.waiting.name()); + businessGroupRelationDao.addRole(ident2, group2, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident1, group3, GroupRoles.coach.name()); + businessGroupRelationDao.addRole(ident2, group3, GroupRoles.participant.name()); + businessGroupRelationDao.addRole(ident4, group3, GroupRoles.waiting.name()); dbInstance.commitAndCloseSession(); //this groups and relations have been created //group1: id1, id2, id3 @@ -566,8 +580,8 @@ public class BusinessGroupServiceTest extends OlatTestCase { //-> remove id1, id3 from the resource List<Identity> identitiesToRemove = new ArrayList<Identity>(); - identitiesToRemove.add(id1); - identitiesToRemove.add(id3); + identitiesToRemove.add(ident1); + identitiesToRemove.add(ident3); businessGroupService.removeMembers(admin, identitiesToRemove, resource.getOlatResource(), null); dbInstance.commitAndCloseSession(); @@ -581,17 +595,17 @@ public class BusinessGroupServiceTest extends OlatTestCase { List<Identity> waitingGroup1 = businessGroupRelationDao.getMembers(group1, GroupRoles.waiting.name()); Assert.assertNotNull(waitingGroup1); Assert.assertEquals(1, waitingGroup1.size()); - Assert.assertEquals(id2, waitingGroup1.get(0)); + Assert.assertEquals(ident2, waitingGroup1.get(0)); //check in group2 id2 as owner and participant List<Identity> ownerGroup2 = businessGroupService.getMembers(group2, GroupRoles.coach.name()); Assert.assertNotNull(ownerGroup2); Assert.assertEquals(1, ownerGroup2.size()); - Assert.assertEquals(id2, ownerGroup2.get(0)); + Assert.assertEquals(ident2, ownerGroup2.get(0)); List<Identity> participantGroup2 = businessGroupRelationDao.getMembers(group2, GroupRoles.participant.name()); Assert.assertNotNull(participantGroup2); Assert.assertEquals(1, participantGroup2.size()); - Assert.assertEquals(id2, participantGroup2.get(0)); + Assert.assertEquals(ident2, participantGroup2.get(0)); List<Identity> waitingGroup2 = businessGroupRelationDao.getMembers(group2, GroupRoles.waiting.name()); Assert.assertNotNull(waitingGroup2); Assert.assertTrue(waitingGroup2.isEmpty()); @@ -603,57 +617,57 @@ public class BusinessGroupServiceTest extends OlatTestCase { List<Identity> participantGroup3 = businessGroupRelationDao.getMembers(group3, GroupRoles.participant.name()); Assert.assertNotNull(participantGroup3); Assert.assertEquals(1, participantGroup3.size()); - Assert.assertEquals(id2, participantGroup3.get(0)); + Assert.assertEquals(ident2, participantGroup3.get(0)); List<Identity> waitingGroup3 = businessGroupRelationDao.getMembers(group3, GroupRoles.waiting.name()); Assert.assertNotNull(waitingGroup3); Assert.assertEquals(1, waitingGroup3.size()); - Assert.assertEquals(id4, waitingGroup3.get(0)); + Assert.assertEquals(ident4, waitingGroup3.get(0)); } @Test public void testMoveRegisteredIdentityFromWaitingToParticipant() throws Exception { //add 1 identity as participant - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w4-1-" + UUID.randomUUID().toString()); - Roles rolesId1 = securityManager.getRoles(id1); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w4-1-" + UUID.randomUUID().toString()); + Roles rolesId1 = securityManager.getRoles(ident1); BusinessGroup group = businessGroupService.createBusinessGroup(null, "move-bg-4", "move-desc", 0, 10, true, false, null); - businessGroupService.addParticipants(id1, rolesId1, Collections.singletonList(id1), group, null); + businessGroupService.addParticipants(ident1, rolesId1, Collections.singletonList(ident1), group, null); dbInstance.commitAndCloseSession(); //add a user to waiting-list which is already in participant-list - businessGroupService.addToWaitingList(id1, Collections.singletonList(id1), group, null); + businessGroupService.addToWaitingList(ident1, Collections.singletonList(ident1), group, null); dbInstance.commitAndCloseSession(); //try to move this user => user will be removed from waiting-list - businessGroupService.moveIdentityFromWaitingListToParticipant(id1, Collections.singletonList(id1), group, null); + businessGroupService.moveIdentityFromWaitingListToParticipant(ident1, Collections.singletonList(ident1), group, null); dbInstance.commitAndCloseSession(); //check position of 'id1' - int pos = businessGroupService.getPositionInWaitingListFor(id1, group); + int pos = businessGroupService.getPositionInWaitingListFor(ident1, group); Assert.assertEquals("pos must be -1, bit is=" + pos, -1, pos); //check if 'id1' is still in participant-list - boolean member = businessGroupService.isIdentityInBusinessGroup(id1, group); + boolean member = businessGroupService.isIdentityInBusinessGroup(ident1, group); Assert.assertTrue("Identity is not in participant-list", member); } @Test public void testAutoTransferFromWaitingListToParticipants() { //add 1 identity as participant, 1 in waiting list - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w5-1-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w5-2-" + UUID.randomUUID().toString());; - Roles rolesId1 = securityManager.getRoles(id1); + Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("move-w5-1-" + UUID.randomUUID().toString()); + Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("move-w5-2-" + UUID.randomUUID().toString());; + Roles rolesId1 = securityManager.getRoles(ident1); BusinessGroup group = businessGroupService.createBusinessGroup(null, "move-bg-5", "move-desc", 0, 1, true, true, null); - businessGroupService.addParticipants(id1, rolesId1, Collections.singletonList(id1), group, null); - businessGroupService.addToWaitingList(id2, Collections.singletonList(id2), group, null); + businessGroupService.addParticipants(ident1, rolesId1, Collections.singletonList(ident1), group, null); + businessGroupService.addToWaitingList(ident2, Collections.singletonList(ident2), group, null); dbInstance.commitAndCloseSession(); //add a user to waiting-list which is already in participant-list - businessGroupService.removeParticipants(id1, Collections.singletonList(id1), group, null); + businessGroupService.removeParticipants(ident1, Collections.singletonList(ident1), group, null); dbInstance.commitAndCloseSession(); //check position of 'id2' - int pos = businessGroupService.getPositionInWaitingListFor(id2, group); + int pos = businessGroupService.getPositionInWaitingListFor(ident2, group); Assert.assertEquals("pos must be -1, bit is=" + pos, -1, pos); //check if 'id1' is still in participant-list - boolean member = businessGroupService.isIdentityInBusinessGroup(id2, group); + boolean member = businessGroupService.isIdentityInBusinessGroup(ident2, group); Assert.assertTrue("Identity is in participant-list", member); } @@ -941,4 +955,186 @@ public class BusinessGroupServiceTest extends OlatTestCase { Assert.assertNotNull(reservations); Assert.assertTrue(reservations.isEmpty()); } + + /** + * Test the default settings. Participants are allowed to leave business groups. + */ + @Test + public void allowToLeavingBusinessGroup_defaultSettings() { + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("leave-auth-1-" + UUID.randomUUID().toString()); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-bg-1-"); + BusinessGroup group = businessGroupService.createBusinessGroup(author, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, group, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + LeaveOption optionToLeave = businessGroupService.isAllowToLeaveBusinessGroup(participant, group); + Assert.assertNotNull(optionToLeave); + Assert.assertTrue(optionToLeave.isAllowToLeave()); + } + + /** + * Test the default settings but the author set the business group to "leaving not allowed". + */ + @Test + public void allowToLeavingBusinessGroup_defaultSettings_groupOverride() { + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("leave-auth-2-" + UUID.randomUUID().toString()); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-bg-2-"); + BusinessGroup group = businessGroupService.createBusinessGroup(author, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, group, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + group = businessGroupService.updateAllowToLeaveBusinessGroup(group, false); + dbInstance.commitAndCloseSession(); + + LeaveOption optionToLeave = businessGroupService.isAllowToLeaveBusinessGroup(participant, group); + Assert.assertNotNull(optionToLeave); + Assert.assertFalse(optionToLeave.isAllowToLeave()); + + ContactList contacts = optionToLeave.getContacts(); + Assert.assertNotNull(contacts); + Collection<Identity> contactList = contacts.getIdentiEmails().values(); + Assert.assertNotNull(contactList); + Assert.assertEquals(1, contactList.size()); + Assert.assertTrue(contactList.contains(author)); + } + + /** + * Override of allow is forbidden system-wide. If a group have the settings not "not allowed to leave", + * the setting must be ignored and the participants allowed to leave the group. + */ + @Test + public void allowToLeavingBusinessGroup_overrideForbidden() { + businessGroupModule.setAllowLeavingGroupOverride(false); + + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("leave-auth-3-" + UUID.randomUUID().toString()); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-bg-3-"); + BusinessGroup group = businessGroupService.createBusinessGroup(author, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, group, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + group = businessGroupService.updateAllowToLeaveBusinessGroup(group, false); + dbInstance.commitAndCloseSession(); + + LeaveOption optionToLeave = businessGroupService.isAllowToLeaveBusinessGroup(participant, group); + Assert.assertNotNull(optionToLeave); + Assert.assertTrue(optionToLeave.isAllowToLeave()); + } + + /** + * Override of allow is forbidden system-wide. If a group have the settings not "not allowed to leave", + * the setting must be ignored for learners group but not for authors group. + */ + @Test + public void allowToLeavingBusinessGroup_overrideForbidden_notAllowForAuthorsGroups_butForLearnersGroup() { + businessGroupModule.setAllowLeavingGroupOverride(false); + businessGroupModule.setAllowLeavingGroupCreatedByAuthors(false); + businessGroupModule.setAllowLeavingGroupCreatedByLearners(true); + + //authors group + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("leave-auth-4-" + UUID.randomUUID().toString()); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-bg-4-"); + BusinessGroup authorsGroup = businessGroupService.createBusinessGroup(author, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, authorsGroup, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + authorsGroup = businessGroupService.updateAllowToLeaveBusinessGroup(authorsGroup, false); + dbInstance.commitAndCloseSession(); + + //check the authors group leaving option + LeaveOption optionToLeaveAuthorsGroup = businessGroupService.isAllowToLeaveBusinessGroup(participant, authorsGroup); + Assert.assertNotNull(optionToLeaveAuthorsGroup); + Assert.assertFalse(optionToLeaveAuthorsGroup.isAllowToLeave()); + + //learners group + Identity learner = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-learn-4-" + UUID.randomUUID().toString()); + BusinessGroup learnersGroup = businessGroupService.createBusinessGroup(learner, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, learnersGroup, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + learnersGroup = businessGroupService.updateAllowToLeaveBusinessGroup(learnersGroup, false); + dbInstance.commitAndCloseSession(); + + //check the learners group leaving option + LeaveOption optionToLeaveLearnersGroup = businessGroupService.isAllowToLeaveBusinessGroup(participant, learnersGroup); + Assert.assertNotNull(optionToLeaveLearnersGroup); + Assert.assertTrue(optionToLeaveLearnersGroup.isAllowToLeave()); + } + + /** + * Override of allow is forbidden system-wide. If a group have the settings not "not allowed to leave", + * the setting must be ignored for learners group but not for authors group. + */ + @Test + public void allowToLeavingBusinessGroup_overrideForbidden_notAllowForAuthorsAndLearnersGroups() { + businessGroupModule.setAllowLeavingGroupOverride(false); + businessGroupModule.setAllowLeavingGroupCreatedByAuthors(false); + businessGroupModule.setAllowLeavingGroupCreatedByLearners(false); + + //authors group + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("leave-auth-5-" + UUID.randomUUID().toString()); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-bg-5-"); + BusinessGroup authorsGroup = businessGroupService.createBusinessGroup(author, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, authorsGroup, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + authorsGroup = businessGroupService.updateAllowToLeaveBusinessGroup(authorsGroup, false); + dbInstance.commitAndCloseSession(); + + //check the authors group leaving option + LeaveOption optionToLeaveAuthorsGroup = businessGroupService.isAllowToLeaveBusinessGroup(participant, authorsGroup); + Assert.assertNotNull(optionToLeaveAuthorsGroup); + Assert.assertFalse(optionToLeaveAuthorsGroup.isAllowToLeave()); + + //learners group + Identity learner = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-learn-5-" + UUID.randomUUID().toString()); + BusinessGroup learnersGroup = businessGroupService.createBusinessGroup(learner, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, null); + businessGroupRelationDao.addRole(participant, learnersGroup, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + learnersGroup = businessGroupService.updateAllowToLeaveBusinessGroup(learnersGroup, false); + dbInstance.commitAndCloseSession(); + + //check the learners group leaving option + LeaveOption optionToLeaveLearnersGroup = businessGroupService.isAllowToLeaveBusinessGroup(participant, learnersGroup); + Assert.assertNotNull(optionToLeaveLearnersGroup); + Assert.assertFalse(optionToLeaveLearnersGroup.isAllowToLeave()); + } + + /** + * + */ + @Test + public void allowToLeavingBusinessGroup_withCourse() { + //authors group + RepositoryEntry resource = JunitTestHelper.createAndPersistRepositoryEntry(); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("leave-bg-5-"); + BusinessGroup group = businessGroupService.createBusinessGroup(null, "Leaving group", "But you cannot leave :-(", new Integer(0), new Integer(2), false, false, resource); + businessGroupRelationDao.addRole(participant, group, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + //set to not allowed to leave + group = businessGroupService.updateAllowToLeaveBusinessGroup(group, false); + dbInstance.commitAndCloseSession(); + + //check the authors group leaving option + LeaveOption optionToLeave = businessGroupService.isAllowToLeaveBusinessGroup(participant, group); + Assert.assertNotNull(optionToLeave); + Assert.assertFalse(optionToLeave.isAllowToLeave()); + ContactList contacts = optionToLeave.getContacts(); + Collection<Identity> contactList = contacts.getIdentiEmails().values(); + Assert.assertNotNull(contactList); + Assert.assertFalse(contactList.isEmpty()); + + for(Identity contact:contactList) { + Roles roles = securityManager.getRoles(contact); + Assert.assertNotNull(roles); + Assert.assertTrue(roles.isOLATAdmin()); + } + } } \ No newline at end of file