diff --git a/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java b/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java index 208d32ba2c4563670f71cdbc91e599b38e9ce186..29ad79004059836e5c3740bbc476966e91af7ac5 100644 --- a/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java +++ b/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java @@ -21,8 +21,8 @@ package org.olat.course.condition.interpreter; -import org.olat.core.id.Identity; import org.apache.logging.log4j.Logger; +import org.olat.core.id.Identity; import org.olat.core.logging.Tracing; import org.olat.course.editor.CourseEditorEnv; import org.olat.course.run.userview.UserCourseEnvironment; @@ -70,7 +70,7 @@ public class IsCourseParticipantFunction extends AbstractFunction { //administrator of any course isParticipant = getUserCourseEnv().isParticipantOfAnyCourse(); } else { - isParticipant = getUserCourseEnv().isParticipant(); + isParticipant = getUserCourseEnv().isMemberParticipant(); } if (log.isDebugEnabled()) { Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity(); diff --git a/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java b/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java index 783342d80f8fb110f9e04131ac48b453f79ad242..062246115af018cbbfd69decffad483b6cff356d 100644 --- a/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java +++ b/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java @@ -144,6 +144,11 @@ public class EditorUserCourseEnvironmentImpl implements UserCourseEnvironment { return false; } + @Override + public boolean isMemberParticipant() { + return false; + } + @Override public boolean isAdministratorOfAnyCourse() { return false; diff --git a/src/main/java/org/olat/course/nodes/cal/CourseCalendars.java b/src/main/java/org/olat/course/nodes/cal/CourseCalendars.java index 1b8f04ee7715b85e3c6cd8fd6d2dabab854f8062..c7f2b397ba6c71e1a51591d9079a9a886bd94c5b 100644 --- a/src/main/java/org/olat/course/nodes/cal/CourseCalendars.java +++ b/src/main/java/org/olat/course/nodes/cal/CourseCalendars.java @@ -109,7 +109,7 @@ public class CourseCalendars { courseKalendarWrapper.setPrivateEventsVisible(true); } else { courseKalendarWrapper.setAccess(KalendarRenderWrapper.ACCESS_READ_ONLY); - courseKalendarWrapper.setPrivateEventsVisible(userCourseEnv.isAdmin() || userCourseEnv.isCoach() || userCourseEnv.isParticipant()); + courseKalendarWrapper.setPrivateEventsVisible(userCourseEnv.isAdmin() || userCourseEnv.isCoach() || userCourseEnv.isMemberParticipant()); } CalendarUserConfiguration config = calendarManager.findCalendarConfigForIdentity(courseKalendarWrapper.getKalendar(), ureq.getIdentity()); if (config != null) { diff --git a/src/main/java/org/olat/course/run/calendar/CourseCalendarController.java b/src/main/java/org/olat/course/run/calendar/CourseCalendarController.java index 7ca107e40b9a532a5585ffbf8b259ad305d7e8a9..7575f1cb5585ceb3e8f9f1397edae0743fa7c16f 100644 --- a/src/main/java/org/olat/course/run/calendar/CourseCalendarController.java +++ b/src/main/java/org/olat/course/run/calendar/CourseCalendarController.java @@ -82,7 +82,7 @@ public class CourseCalendarController extends BasicController { courseKalendarWrapper.setPrivateEventsVisible(true); } else { courseKalendarWrapper.setAccess(KalendarRenderWrapper.ACCESS_READ_ONLY); - courseKalendarWrapper.setPrivateEventsVisible(userCourseEnv.isAdmin() || userCourseEnv.isCoach() || userCourseEnv.isParticipant()); + courseKalendarWrapper.setPrivateEventsVisible(userCourseEnv.isAdmin() || userCourseEnv.isCoach() || userCourseEnv.isMemberParticipant()); } CalendarUserConfiguration config = calendarManager.findCalendarConfigForIdentity(courseKalendarWrapper.getKalendar(), getIdentity()); if (config != null) { diff --git a/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java b/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java index 3b7bfdadd88257f6f3e877fc1da6dd1289ebedde..1c796c5df421b7df4342a16fba376b149de436ed 100644 --- a/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java +++ b/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java @@ -81,10 +81,19 @@ public interface UserCourseEnvironment { /** * Is a participant of the course, within the course as in relation of a group. + * Users in a open course are participants as well. + * * @return */ public boolean isParticipant(); + /** + * Is the identity a member with the role participant of the course? + * + * @return + */ + public boolean isMemberParticipant(); + public boolean isIdentityInCourseGroup(Long groupKey); diff --git a/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java b/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java index 1eff5d2676f40d435718d5953c1c7a8057f84e77..96cb87905caeb6e05af85947e327467a0afa2bbb 100644 --- a/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java +++ b/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java @@ -70,7 +70,7 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { private final WindowControl windowControl; - private Boolean admin, coach, participant; + private Boolean admin, coach, participant, allUsersParticipant; private Boolean adminAnyCourse, coachAnyCourse, participantAnyCourse; private Boolean certification; @@ -101,7 +101,6 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { this.participant = participant; this.windowControl = windowControl; this.courseReadOnly = courseReadOnly; - initScoreAccounting(); } public static UserCourseEnvironmentImpl load(UserRequest ureq, ICourse course, RepositoryEntrySecurity reSecurity, WindowControl wControl) { @@ -130,14 +129,6 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { reSecurity.isCoach(), reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() , reSecurity.isParticipant(), reSecurity.isReadOnly() || reSecurity.isOnlyPrincipal() || reSecurity.isOnlyMasterCoach()); } - - private void initScoreAccounting() { - if (isParticipant()) { - scoreAccounting = new AssessmentAccounting(this); - } else { - scoreAccounting = new NoEvaluationAccounting(); - } - } @Override public CourseEnvironment getCourseEnvironment() { @@ -161,8 +152,15 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { @Override public ScoreAccounting getScoreAccounting() { + if (scoreAccounting == null) { + initScoreAccounting(); + } return scoreAccounting; } + + private void initScoreAccounting() { + scoreAccounting = isParticipant()? new AssessmentAccounting(this): new NoEvaluationAccounting(); + } @Override public CourseEditorEnv getCourseEditorEnv() { @@ -212,15 +210,37 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { @Override public boolean isParticipant() { - if(participant != null) { - return participant.booleanValue(); + // User is membership participant + if(participant != null && participant.booleanValue()) { + return true; + } + + // If a course is open to all users, a user may is not a member but has access as well. + // Such a user has to act as a participant as well. + if (allUsersParticipant == null) { + boolean allUsersOnly = !isAdmin() && !isCoach() && !getIdentityEnvironment().getRoles().isGuestOnly(); + allUsersParticipant = Boolean.valueOf(allUsersOnly); + } + if (allUsersParticipant.booleanValue()) { + return true; } + + // User is not membership participant + if(participant != null && !participant.booleanValue()) { + return false; + } + //lazy loading CourseGroupManager cgm = courseEnvironment.getCourseGroupManager(); boolean partLazy = cgm.isIdentityCourseParticipant(identityEnvironment.getIdentity()); participant = Boolean.valueOf(partLazy); return partLazy; } + + @Override + public boolean isMemberParticipant() { + return courseEnvironment.getCourseGroupManager().isIdentityCourseParticipant(identityEnvironment.getIdentity()); + } @Override public boolean isAdministratorOfAnyCourse() { @@ -354,5 +374,6 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment { if (participantChanged) { initScoreAccounting(); } + this.allUsersParticipant = null; } } diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java index 91b4a19412a3739d35ac54f782c4918bb6ec81cb..98ace2ba45ad25e138be9205c58f3eff4d1d89e0 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java @@ -120,7 +120,7 @@ public class CurriculumElementCalendarController extends BasicController impleme courseKalendarWrapper.setPrivateEventsVisible(true); } else { courseKalendarWrapper.setAccess(KalendarRenderWrapper.ACCESS_READ_ONLY); - courseKalendarWrapper.setPrivateEventsVisible(userCourseEnv.isAdmin() || userCourseEnv.isCoach() || userCourseEnv.isParticipant()); + courseKalendarWrapper.setPrivateEventsVisible(userCourseEnv.isAdmin() || userCourseEnv.isCoach() || userCourseEnv.isMemberParticipant()); } CalendarUserConfiguration config = calendarManager.findCalendarConfigForIdentity(courseKalendarWrapper.getKalendar(), getIdentity()); if (config != null) { diff --git a/src/test/java/org/olat/course/run/userview/UserCourseEnvironmentImplTest.java b/src/test/java/org/olat/course/run/userview/UserCourseEnvironmentImplTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e208f3aac3c1813d8f23e6de0e9647766efdeef8 --- /dev/null +++ b/src/test/java/org/olat/course/run/userview/UserCourseEnvironmentImplTest.java @@ -0,0 +1,92 @@ +/** + * <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.course.run.userview; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.olat.core.id.IdentityEnvironment; +import org.olat.core.id.Roles; +import org.olat.course.run.environment.CourseEnvironment; + +/** + * + * Initial date: 21.02.2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class UserCourseEnvironmentImplTest { + + @Test + public void shouldBeParticipantIfIsMemebershipParticipant() { + IdentityEnvironment identEnv = mock(IdentityEnvironment.class, RETURNS_DEEP_STUBS); + CourseEnvironment courseEnv = mock(CourseEnvironment.class, RETURNS_DEEP_STUBS); + UserCourseEnvironmentImpl sut = new UserCourseEnvironmentImpl(identEnv, courseEnv); + + sut.setUserRoles(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE); + + assertThat(sut.isParticipant()).isTrue(); + } + + @Test + public void shouldNotBeParticipantIfIsMemberAdminOnly() { + IdentityEnvironment identEnv = mock(IdentityEnvironment.class, RETURNS_DEEP_STUBS); + CourseEnvironment courseEnv = mock(CourseEnvironment.class, RETURNS_DEEP_STUBS); + UserCourseEnvironmentImpl sut = new UserCourseEnvironmentImpl(identEnv, courseEnv); + + sut.setUserRoles(Boolean.TRUE, Boolean.FALSE, Boolean.FALSE); + + assertThat(sut.isParticipant()).isFalse(); + } + + @Test + public void shouldNotBeParticipantIfIsMemberCoachOnly() { + IdentityEnvironment identEnv = mock(IdentityEnvironment.class, RETURNS_DEEP_STUBS); + CourseEnvironment courseEnv = mock(CourseEnvironment.class, RETURNS_DEEP_STUBS); + UserCourseEnvironmentImpl sut = new UserCourseEnvironmentImpl(identEnv, courseEnv); + + sut.setUserRoles(Boolean.FALSE, Boolean.TRUE, Boolean.FALSE); + + assertThat(sut.isParticipant()).isFalse(); + } + + @Test + public void shouldNotBeParticipantIfIsGuestOnly() { + IdentityEnvironment identEnv = mock(IdentityEnvironment.class); + when(identEnv.getRoles()).thenReturn(Roles.guestRoles()); + CourseEnvironment courseEnv = mock(CourseEnvironment.class, RETURNS_DEEP_STUBS); + UserCourseEnvironmentImpl sut = new UserCourseEnvironmentImpl(identEnv, courseEnv); + + assertThat(sut.isParticipant()).isFalse(); + } + + @Test + public void shouldBeParticipantIfIsWhetherMemberNorGuestOnly() { + IdentityEnvironment identEnv = mock(IdentityEnvironment.class, RETURNS_DEEP_STUBS); + CourseEnvironment courseEnv = mock(CourseEnvironment.class, RETURNS_DEEP_STUBS); + UserCourseEnvironmentImpl sut = new UserCourseEnvironmentImpl(identEnv, courseEnv); + + assertThat(sut.isParticipant()).isTrue(); + } + +} diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 2a60aaafa87a71f7776abe282eb1077b6cfa25a2..5f2d79787a17a399b1d6ea98e88f1967b24cbd1b 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -487,6 +487,7 @@ import org.junit.runners.Suite; org.olat.course.nodes.st.assessment.STLastModificationsEvaluatorTest.class, org.olat.course.nodes.st.assessment.STStatusEvaluatorTest.class, org.olat.course.run.scoring.AverageCompletionEvaluatorTest.class, + org.olat.course.run.userview.UserCourseEnvironmentImplTest.class, org.olat.login.validation.PasswordSyntaxValidatorTest.class, org.olat.login.validation.PasswordValidationRuleFactoryTest.class, org.olat.modules.assessment.model.OverridableImplTest.class,