diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index 147baf873dc52a67d9f4b507b4a9bcd8a95dda85..77475fc251dca1e1ce1b56aafc33f26b192299e5 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -89,7 +89,6 @@ import org.olat.course.assessment.AssessmentChangedEvent; import org.olat.course.assessment.AssessmentMainController; import org.olat.course.assessment.AssessmentModule; import org.olat.course.assessment.CoachingGroupAccessAssessmentCallback; -import org.olat.course.assessment.EfficiencyStatementManager; import org.olat.course.assessment.FullAccessAssessmentCallback; import org.olat.course.assessment.ui.AssessmentModeListController; import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController; @@ -191,8 +190,6 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im private BusinessGroupService businessGroupService; @Autowired private AssessmentModule assessmentModule; - @Autowired - private EfficiencyStatementManager efficiencyStatementManager; public CourseRuntimeController(UserRequest ureq, WindowControl wControl, RepositoryEntry re, RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator, @@ -443,6 +440,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im ordersLink = LinkFactory.createToolLink("bookings", translate("details.orders"), this, "o_sel_repo_booking"); ordersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_booking"); + ordersLink.setElementCssClass("o_sel_course_ac_tool"); boolean booking = acService.isResourceAccessControled(getRepositoryEntry().getOlatResource(), null); ordersLink.setVisible(!corrupted && booking); tools.addComponent(ordersLink); 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 e459f8a9ddcf9e6aee85f63a11712d5c6a2e4133..be661066c35668eadeb29e26b34ff2adb8700828 100644 --- a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java +++ b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java @@ -217,6 +217,7 @@ public abstract class AbstractMemberListController extends FormBasicController i membersTable.setAndLoadPersistedPreferences(ureq, this.getClass().getSimpleName()); membersTable.setSearchEnabled(true); membersTable.setExportEnabled(true); + membersTable.setElementCssClass("o_sel_member_list"); if(!globallyManaged) { editButton = uifactory.addFormLink("edit.members", formLayout, Link.BUTTON); diff --git a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java index b8b2d68340c9af44e04faf8fbeeaccbb6f8fc45e..c1bb068372dde60c010999d3c0be9df37beb4e6c 100644 --- a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java +++ b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java @@ -61,7 +61,6 @@ import org.olat.core.util.resource.OresHelper; import org.olat.course.CourseModule; import org.olat.course.assessment.AssessmentMode; import org.olat.course.assessment.AssessmentModeManager; -import org.olat.course.assessment.AssessmentModule; import org.olat.course.assessment.model.TransientAssessmentMode; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryManagedFlag; @@ -153,8 +152,6 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController @Autowired protected MarkManager markManager; @Autowired - private AssessmentModule assessmentModule; - @Autowired protected RepositoryModule repositoryModule; @Autowired private RepositoryService repositoryService; @@ -530,6 +527,10 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController } else if(accessCtrl == source) { if(event == Event.CHANGED_EVENT) { re = accessCtrl.getEntry(); + if(ordersLink != null) { + boolean booking = acService.isResourceAccessControled(re.getOlatResource(), null); + ordersLink.setVisible(!corrupted && booking); + } } } else if(descriptionCtrl == source) { if(event == Event.CHANGED_EVENT) { diff --git a/src/main/java/org/olat/repository/ui/author/AuthoringEditAccessController.java b/src/main/java/org/olat/repository/ui/author/AuthoringEditAccessController.java index 5f25c07f9ec369ab11a25c3e84c4f3ad33281534..435f8cabb811528cbe224f800ea74ea79407c614 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthoringEditAccessController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthoringEditAccessController.java @@ -76,6 +76,7 @@ public class AuthoringEditAccessController extends BasicController { boolean managedBookings = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.bookings); acCtr = new AccessConfigurationController(ureq, getWindowControl(), entry.getOlatResource(), entry.getDisplayname(), true, !managedBookings); + listenTo(acCtr); int access = propPupForm.getAccess(); int numOfBookingConfigs = acCtr.getNumOfBookingConfigurations(); if(access == RepositoryEntry.ACC_USERS || access == RepositoryEntry.ACC_USERS_GUESTS) { @@ -140,6 +141,10 @@ public class AuthoringEditAccessController extends BasicController { CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(modifiedEvent, entry); fireEvent(ureq, Event.CHANGED_EVENT); } + } else if(acCtr == source) { + if(event == Event.CHANGED_EVENT) { + fireEvent(ureq, Event.CHANGED_EVENT); + } } } } diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java index d8b45c5db3c3e7d8df156a970dde0175f3cc6f19..312bdcaa2716a9ab523570bdceba88c31ee52572 100644 --- a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java +++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java @@ -31,7 +31,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.GroupRoles; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; @@ -87,8 +86,6 @@ public class ACFrontendManager implements ACService { @Autowired private DB dbInstance; @Autowired - private BaseSecurity securityManager; - @Autowired private RepositoryManager repositoryManager; @Autowired private RepositoryService repositoryService; diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java index 6d0155058ea2b64ec98f1b428f54b8af8f61c6ba..605d53aeaf9415c6cbed3e58578716497de7e88d 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java +++ b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java @@ -241,6 +241,7 @@ public class AccessConfigurationController extends FormBasicController { AccessInfo infos = (AccessInfo)source.getUserObject(); acService.deleteOffer(infos.getLink().getOffer()); confControllers.remove(infos); + fireEvent(ureq, Event.CHANGED_EVENT); } else if("edit".equals(cmd)) { AccessInfo infos = (AccessInfo)source.getUserObject(); editMethod(ureq, infos); diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/OrdersController.java b/src/main/java/org/olat/resource/accesscontrol/ui/OrdersController.java index 3b960dbd28791482303de783715bb5c34958a06f..28b93708ab0207cc5c14fa62364e7f1bd807bf0c 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/OrdersController.java +++ b/src/main/java/org/olat/resource/accesscontrol/ui/OrdersController.java @@ -111,7 +111,6 @@ public class OrdersController extends BasicController implements Activateable2 { tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("order.total", Col.total.ordinal(), null, getLocale())); tableCtr.addColumnDescriptor(new StaticColumnDescriptor(CMD_SELECT, "table.order.details", getTranslator().translate("order.details"))); - listenTo(tableCtr); loadModel(); diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_content/orders.html b/src/main/java/org/olat/resource/accesscontrol/ui/_content/orders.html index 07c5f65bf4cee6263ba6e202a281834f527f7ad2..f77d933b39a0f968b33df388afb830d129d04f22 100644 --- a/src/main/java/org/olat/resource/accesscontrol/ui/_content/orders.html +++ b/src/main/java/org/olat/resource/accesscontrol/ui/_content/orders.html @@ -1,6 +1,8 @@ -<h4><i class="o_icon o_icon_booking"> </i> $title</h4> -<div class="o_info">$description</div> -#if($r.available("searchForm")) - $r.render("searchForm") -#end -$r.render("orderList") \ No newline at end of file +<div class="o_sel_order_list"> + <h4><i class="o_icon o_icon_booking"> </i> $title</h4> + <div class="o_info">$description</div> + #if($r.available("searchForm")) + $r.render("searchForm") + #end + $r.render("orderList") +</div> \ No newline at end of file diff --git a/src/test/java/org/olat/selenium/CourseTest.java b/src/test/java/org/olat/selenium/CourseTest.java index 9f32be5ff77e99e9a4f69493da128a3fc1da3b53..7bbe0b63396b0d532feb6b27a44638feb0cfd346 100644 --- a/src/test/java/org/olat/selenium/CourseTest.java +++ b/src/test/java/org/olat/selenium/CourseTest.java @@ -41,6 +41,7 @@ import org.olat.selenium.page.LoginPage; import org.olat.selenium.page.NavigationPage; import org.olat.selenium.page.Participant; import org.olat.selenium.page.User; +import org.olat.selenium.page.core.BookingPage; import org.olat.selenium.page.course.CourseEditorPageFragment; import org.olat.selenium.page.course.CoursePageFragment; import org.olat.selenium.page.course.CourseWizardPage; @@ -50,7 +51,9 @@ import org.olat.selenium.page.course.PublisherPageFragment.Access; import org.olat.selenium.page.graphene.OOGraphene; import org.olat.selenium.page.repository.AuthoringEnvPage; import org.olat.selenium.page.repository.FeedPage; +import org.olat.selenium.page.repository.RepositoryAccessPage; import org.olat.selenium.page.repository.AuthoringEnvPage.ResourceType; +import org.olat.selenium.page.repository.RepositoryAccessPage.UserAccess; import org.olat.selenium.page.repository.RepositoryEditDescriptionPage; import org.olat.test.ArquillianDeployments; import org.olat.test.rest.UserRestClient; @@ -820,4 +823,91 @@ public class CourseTest { int numOfSurvivingMessages = infoMsgConfig.countMessages(); Assert.assertEquals(3, numOfSurvivingMessages); } + + /** + * An author creates a course, make it visible for + * members and add an access control by password. + * The user search for the course, books it and give + * the password.<br/> + * The author checks in the list of orders if the booking + * of the user is there and after it checks if the user is + * in the member list too. + * + * @param loginPage + * @param ryomouBrowser + * @throws IOException + * @throws URISyntaxException + */ + @Test + @RunAsClient + public void courseBooking(@InitialPage LoginPage loginPage, + @Drone @User WebDriver ryomouBrowser) + throws IOException, URISyntaxException { + UserVO author = new UserRestClient(deploymentUrl).createAuthor(); + loginPage.loginAs(author.getLogin(), author.getPassword()); + UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou"); + + //go to authoring + AuthoringEnvPage authoringEnv = navBar + .assertOnNavigationPage() + .openAuthoringEnvironment(); + + String title = "Create-Selen-" + UUID.randomUUID().toString(); + //create course + authoringEnv + .openCreateDropDown() + .clickCreate(ResourceType.course) + .fillCreateForm(title) + .assertOnGeneralTab(); + + //open course editor + CoursePageFragment course = new CoursePageFragment(browser); + RepositoryAccessPage courseAccess = course + .openToolsMenu() + .edit() + .createNode("info") + .autoPublish() + .accessConfiguration() + .setUserAccess(UserAccess.registred); + //add booking by secret token + courseAccess + .boooking() + .openAddDropMenu() + .addTokenMethod() + .configureTokenMethod("secret", "The password is secret"); + courseAccess + .clickToolbarBack(); + + //a user search the course + LoginPage ryomouLoginPage = LoginPage.getLoginPage(ryomouBrowser, deploymentUrl); + ryomouLoginPage + .loginAs(ryomou.getLogin(), ryomou.getPassword()) + .resume(); + NavigationPage ryomouNavBar = new NavigationPage(ryomouBrowser); + ryomouNavBar + .openMyCourses() + .openSearch() + .extendedSearch(title) + .book(title); + //book the course + BookingPage booking = new BookingPage(ryomouBrowser); + booking + .bookToken("secret"); + //check the course + CoursePageFragment bookedCourse = CoursePageFragment.getCourse(ryomouBrowser); + bookedCourse + .assertOnTitle(title); + + //Author go in the list of bookings of the course + BookingPage bookingList = course + .openToolsMenu() + .bookingTool(); + bookingList + .assertFirstNameInListIsOk(ryomou); + + //Author go to members list + course + .members() + .assertFirstNameInList(ryomou); + } } diff --git a/src/test/java/org/olat/selenium/page/core/BookingPage.java b/src/test/java/org/olat/selenium/page/core/BookingPage.java index 19fd73e7dd4a9c6eecd7a39de9128789bcf4dcd6..7b15d3999b5b1ee05a95388424106b2187dd8a63 100644 --- a/src/test/java/org/olat/selenium/page/core/BookingPage.java +++ b/src/test/java/org/olat/selenium/page/core/BookingPage.java @@ -23,6 +23,7 @@ import java.util.List; import org.junit.Assert; import org.olat.selenium.page.graphene.OOGraphene; +import org.olat.user.restapi.UserVO; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -120,4 +121,30 @@ public class BookingPage { browser.findElement(saveButtonBy).click(); OOGraphene.waitBusy(browser); } + + /** + * Check if a the booking of a user is in the list + * of orders. The assert check by first name and + * if the order is ok. + * + * @param user + * @return + */ + public BookingPage assertFirstNameInListIsOk(UserVO user) { + By firstNameBy = By.xpath("//td[contains(text(),'" + user.getFirstName() + "')]"); + By okBy = By.className("o_ac_order_status_payed_icon"); + By rowBy = By.cssSelector(".o_sel_order_list table.o_table.table tr"); + boolean found = false; + List<WebElement> rows = browser.findElements(rowBy); + for(WebElement row:rows) { + List<WebElement> firstNameEl = row.findElements(firstNameBy); + List<WebElement> okEl = row.findElements(okBy); + if(firstNameEl.size() == 1 && okEl.size() == 1) { + found = true; + break; + } + } + Assert.assertTrue(found); + return this; + } } diff --git a/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java b/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java index c5edf45a7f5485d50a32bcd99fc526124b49aec9..026b30d1aa224fc6400623a74578553c481725b0 100644 --- a/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java +++ b/src/test/java/org/olat/selenium/page/course/CoursePageFragment.java @@ -26,6 +26,7 @@ import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.graphene.Graphene; import org.junit.Assert; import org.olat.restapi.support.vo.CourseVO; +import org.olat.selenium.page.core.BookingPage; import org.olat.selenium.page.core.MenuTreePageFragment; import org.olat.selenium.page.graphene.OOGraphene; import org.olat.selenium.page.repository.RepositoryAccessPage; @@ -50,6 +51,7 @@ public class CoursePageFragment { public static final By editCourseBy = By.className("o_sel_course_editor"); public static final By accessConfigBy = By.className("o_sel_course_access"); + public static final By bookingBy = By.className("o_sel_course_ac_tool"); public static final By assessmentToolBy = By.className("o_sel_course_assessment_tool"); public static final By assessmentModeBy = By.className("o_sel_course_assessment_mode"); public static final By membersCourseBy = By.className("o_sel_course_members"); @@ -201,4 +203,13 @@ public class CoursePageFragment { WebElement main = browser.findElement(By.id("o_main_container")); return Graphene.createPageFragment(EfficiencyStatementConfigurationPage.class, main); } + + public BookingPage bookingTool() { + if(!browser.findElement(toolsMenu).isDisplayed()) { + openToolsMenu(); + } + browser.findElement(bookingBy).click(); + OOGraphene.waitBusy(browser); + return new BookingPage(browser); + } } diff --git a/src/test/java/org/olat/selenium/page/course/MembersPage.java b/src/test/java/org/olat/selenium/page/course/MembersPage.java index 5d4bb065a49fb2b76ebee397b3572ba8fce79723..e33dc2bcefe163390dc0665f32a162b2714aff1a 100644 --- a/src/test/java/org/olat/selenium/page/course/MembersPage.java +++ b/src/test/java/org/olat/selenium/page/course/MembersPage.java @@ -19,7 +19,10 @@ */ package org.olat.selenium.page.course; +import java.util.List; + import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jcodec.common.Assert; import org.olat.selenium.page.graphene.OOGraphene; import org.olat.selenium.page.group.GroupPage; import org.olat.selenium.page.group.GroupsPage; @@ -124,6 +127,27 @@ public class MembersPage { .next().next().next().finish(); } + /** + * Check if the user with the specified first name is in the member list. + * @param user + * @return + */ + public MembersPage assertFirstNameInList(UserVO user) { + By firstNameBy = By.xpath("//td//a[contains(text(),'" + user.getFirstName() + "')]"); + By rowBy = By.cssSelector(".o_sel_member_list table.table tr"); + List<WebElement> rows = browser.findElements(rowBy); + boolean found = false; + for(WebElement row:rows) { + List<WebElement> firstNameEl = row.findElements(firstNameBy); + if(firstNameEl.size() > 0) { + found = true; + break; + } + } + Assert.assertTrue(found); + return this; + } + /** * Click back to the course * diff --git a/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java b/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java index a30cfe27eb9e4d567833bd87ab09a09b51b279dd..14d7b68e74433ed16a3f8b3a7f36108e0403cc51 100644 --- a/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java +++ b/src/test/java/org/olat/selenium/page/course/MyCoursesPage.java @@ -99,6 +99,29 @@ public class MyCoursesPage { return this; } + /** + * Click on the book button of the course specified + * by the title in the course list. + * + * @param title + */ + public void book(String title) { + By bookingBy = By.cssSelector("a.o_book"); + By rowBy = By.cssSelector("div.o_table_row"); + By titleLinkBy = By.cssSelector("h4.o_title a"); + WebElement linkToBook = null; + List<WebElement> rows = browser.findElements(rowBy); + for(WebElement row:rows) { + WebElement titleLink = row.findElement(titleLinkBy); + if(titleLink.getText().contains(title)) { + linkToBook = row.findElement(bookingBy); + } + } + Assert.assertNotNull(linkToBook); + linkToBook.click(); + OOGraphene.waitBusy(browser); + } + public MyCoursesPage selectCatalogEntry(String title) { By titleBy = By.cssSelector(".o_sublevel .o_meta h4.o_title a"); List<WebElement> titleLinks = browser.findElements(titleBy); diff --git a/src/test/java/org/olat/selenium/page/repository/RepositoryAccessPage.java b/src/test/java/org/olat/selenium/page/repository/RepositoryAccessPage.java index 0903145e68a54384edafc90f6b3616f4f039c10e..cc45565dea22e062bc9c89688875d1e1e9bfd514 100644 --- a/src/test/java/org/olat/selenium/page/repository/RepositoryAccessPage.java +++ b/src/test/java/org/olat/selenium/page/repository/RepositoryAccessPage.java @@ -19,7 +19,11 @@ */ package org.olat.selenium.page.repository; +import java.util.List; + import org.jboss.arquillian.drone.api.annotation.Drone; +import org.junit.Assert; +import org.olat.selenium.page.core.BookingPage; import org.olat.selenium.page.graphene.OOGraphene; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; @@ -73,6 +77,13 @@ public class RepositoryAccessPage { return this; } + public BookingPage boooking() { + By bookingFieldsetBy = By.cssSelector("fieldset.o_ac_configuration"); + List<WebElement> bookingFieldsetEls = browser.findElements(bookingFieldsetBy); + Assert.assertEquals(1, bookingFieldsetEls.size()); + return new BookingPage(browser); + } + /** * Click toolbar */ diff --git a/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java b/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java index da9646e8c68161e2ea9cd2365f4d806cd9ac05d8..452c3f6e89a34cfc0d87ff77221f279e9af84035 100644 --- a/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java +++ b/src/test/java/org/olat/selenium/page/repository/RepositoryEditDescriptionPage.java @@ -64,4 +64,5 @@ public class RepositoryEditDescriptionPage { WebElement main = browser.findElement(By.id("o_main_wrapper")); Assert.assertTrue(main.isDisplayed()); } + }