diff --git a/src/main/java/org/olat/commons/calendar/ui/WeeklyCalendarController.java b/src/main/java/org/olat/commons/calendar/ui/WeeklyCalendarController.java index 9ccdea2abd8dc31d47992f24661493860e4173a4..e5b4d0f84e1ca324721d27ea0dada00cf013080b 100644 --- a/src/main/java/org/olat/commons/calendar/ui/WeeklyCalendarController.java +++ b/src/main/java/org/olat/commons/calendar/ui/WeeklyCalendarController.java @@ -365,6 +365,7 @@ public class WeeklyCalendarController extends FormBasicController implements Act } } eventCalloutCtr.deactivate(); + cleanUp(); } else if(source == cmc) { calendarEl.getComponent().setDirty(true); cleanUp(); @@ -417,6 +418,10 @@ public class WeeklyCalendarController extends FormBasicController implements Act } else if(event instanceof CalendarGUISettingEvent) { calendarEl.setCalendars(calendarWrappers); } + } else if(eventCalloutCtr == source) { + cleanUp(); + } else if(eventDetailsCtr == source) { + } if (calendarEl.getComponent().isDirty()) { @@ -437,8 +442,12 @@ public class WeeklyCalendarController extends FormBasicController implements Act private void cleanUp() { removeAsListenerAndDispose(configurationCtrl); + removeAsListenerAndDispose(eventCalloutCtr); + removeAsListenerAndDispose(eventDetailsCtr); removeAsListenerAndDispose(editController); removeAsListenerAndDispose(cmc); + eventCalloutCtr = null; + eventDetailsCtr = null; configurationCtrl = null; editController = null; cmc = null; @@ -509,6 +518,8 @@ public class WeeklyCalendarController extends FormBasicController implements Act } private void doPrintEventCallout(UserRequest ureq, String targetDomId) { + if(eventCalloutCtr != null && printCtrl != null) return; + removeAsListenerAndDispose(eventCalloutCtr); removeAsListenerAndDispose(printCtrl); @@ -523,6 +534,8 @@ public class WeeklyCalendarController extends FormBasicController implements Act } private void doOpenEventCallout(UserRequest ureq, KalendarEvent calEvent, KalendarRenderWrapper calWrapper, String targetDomId) { + if(eventCalloutCtr != null && eventDetailsCtr != null) return; + removeAsListenerAndDispose(eventCalloutCtr); removeAsListenerAndDispose(eventDetailsCtr); diff --git a/src/main/java/org/olat/restapi/repository/RepositoryEntryResource.java b/src/main/java/org/olat/restapi/repository/RepositoryEntryResource.java index e2d538363917cecfaa6b2dd2c9caef635f4187aa..0ff48402cc7b909f8219e88a1dfc80d9087de34d 100644 --- a/src/main/java/org/olat/restapi/repository/RepositoryEntryResource.java +++ b/src/main/java/org/olat/restapi/repository/RepositoryEntryResource.java @@ -685,7 +685,7 @@ public class RepositoryEntryResource { int count = 0; UserVO[] ownerVOs = new UserVO[identities.size()]; for(Identity identity:identities) { - ownerVOs[count++] = UserVOFactory.get(identity); + ownerVOs[count++] = UserVOFactory.get(identity, true, true); } return Response.ok(ownerVOs).build(); } diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java index c6db2ca51b43c0f0086822b5bb34e5456b144641..f96fc086b44e91c46db57e7e9aaac7b1feeb05bc 100644 --- a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java +++ b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java @@ -214,7 +214,9 @@ public class CoursesWebService { * @param shortTitle The short title * @param title The title * @param sharedFolderSoftKey The repository entry key of a shared folder (optional) - * @param copyFrom The cours key to make a copy from (optional) + * @param copyFrom The course primary key key to make a copy from (optional) + * @param initialAuthor The primary key of the initial author (optional) + * @param noAuthor True to create a course without the author * @param request The HTTP request * @return It returns the id of the newly created Course */ @@ -226,8 +228,8 @@ public class CoursesWebService { @QueryParam("externalId") String externalId, @QueryParam("externalRef") String externalRef, @QueryParam("authors") String authors, @QueryParam("location") String location, @QueryParam("managedFlags") String managedFlags, @QueryParam("sharedFolderSoftKey") String sharedFolderSoftKey, - @QueryParam("copyFrom") Long copyFrom, - @Context HttpServletRequest request) { + @QueryParam("copyFrom") Long copyFrom, @QueryParam("initialAuthor") Long initialAuthor, + @QueryParam("setAuthor") @DefaultValue("true") Boolean setAuthor, @Context HttpServletRequest request) { if(!isAuthor(request)) { return Response.serverError().status(Status.UNAUTHORIZED).build(); } @@ -239,13 +241,22 @@ public class CoursesWebService { if(!StringHelper.containsNonWhitespace(displayName)) { displayName = shortTitle; } - + ICourse course; UserRequest ureq = getUserRequest(request); + Identity id = null; + if(setAuthor != null && setAuthor.booleanValue()) { + if (initialAuthor != null) { + id = getIdentity(initialAuthor); + } + if (id == null) { + id = ureq.getIdentity(); + } + } if(copyFrom != null) { - course = copyCourse(copyFrom, ureq, shortTitle, title, displayName, softKey, accessInt, membersOnlyBool, authors, location, externalId, externalRef, managedFlags, configVO); + course = copyCourse(copyFrom, ureq, id, shortTitle, title, displayName, softKey, accessInt, membersOnlyBool, authors, location, externalId, externalRef, managedFlags, configVO); } else { - course = createEmptyCourse(ureq.getIdentity(), shortTitle, title, displayName, softKey, accessInt, membersOnlyBool, authors, location, externalId, externalRef, managedFlags, configVO); + course = createEmptyCourse(id, shortTitle, title, displayName, softKey, accessInt, membersOnlyBool, authors, location, externalId, externalRef, managedFlags, configVO); } CourseVO vo = ObjectFactory.get(course); return Response.ok(vo).build(); @@ -254,12 +265,12 @@ public class CoursesWebService { /** * Creates an empty course * @response.representation.200.qname {http://www.example.com}courseVO - * @response.representation.200.mediaType application/xml, application/json - * @response.representation.200.doc The metadatas of the created course - * @response.representation.200.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_COURSEVO} + * @response.representation.200.mediaType application/xml, application/json + * @response.representation.200.doc The metadatas of the created course + * @response.representation.200.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_COURSEVO} * @response.representation.401.doc The roles of the authenticated user are not sufficient - * @param courseVo The course - * @param request The HTTP request + * @param courseVo The course + * @param request The HTTP request * @return It returns the newly created course */ @PUT @@ -384,7 +395,7 @@ public class CoursesWebService { return course; } - private static ICourse copyCourse(Long copyFrom, UserRequest ureq, String shortTitle, String longTitle, String displayName, + private static ICourse copyCourse(Long copyFrom, UserRequest ureq, Identity initialAuthor, String shortTitle, String longTitle, String displayName, String softKey, int access, boolean membersOnly, String authors, String location, String externalId, String externalRef, String managedFlags, CourseConfigVO courseConfigVO) { @@ -423,11 +434,11 @@ public class CoursesWebService { OLATResource sourceResource = src.getOlatResource(); OLATResource copyResource = OLATResourceManager.getInstance().createOLATResourceInstance(sourceResource.getResourceableTypeName()); - RepositoryEntry preparedEntry = repositoryService.create(ureq.getIdentity(), null, resName, name, + RepositoryEntry preparedEntry = repositoryService.create(initialAuthor, null, resName, name, description, copyResource, RepositoryEntry.ACC_OWNERS); RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(src); - preparedEntry = handler.copy(ureq.getIdentity(), src, preparedEntry); + preparedEntry = handler.copy(initialAuthor, src, preparedEntry); preparedEntry.setCanDownload(src.getCanDownload()); if(StringHelper.containsNonWhitespace(softKey)) { diff --git a/src/main/java/org/olat/restapi/security/RestSecurityHelper.java b/src/main/java/org/olat/restapi/security/RestSecurityHelper.java index 704919ee879a7c53cdb55edbb7d8d258737979c2..e347e34aaba7c09073027859fdbbe26e559a0085 100644 --- a/src/main/java/org/olat/restapi/security/RestSecurityHelper.java +++ b/src/main/java/org/olat/restapi/security/RestSecurityHelper.java @@ -65,6 +65,10 @@ public class RestSecurityHelper { return ureq.getIdentity(); } + public static Identity getIdentity(Long identityKey) { + return BaseSecurityManager.getInstance().loadIdentityByKey(identityKey); + } + public static boolean isUserManager(HttpServletRequest request) { try { Roles roles = getRoles(request); diff --git a/src/main/java/org/olat/user/restapi/UserVOFactory.java b/src/main/java/org/olat/user/restapi/UserVOFactory.java index dc4e005692306582bd0237d2e2722a2676b1f1e4..9fb49499e22c01ac96b2139811b6cc5bf3cacd66 100644 --- a/src/main/java/org/olat/user/restapi/UserVOFactory.java +++ b/src/main/java/org/olat/user/restapi/UserVOFactory.java @@ -60,16 +60,8 @@ import org.olat.user.propertyhandlers.UserPropertyHandler; */ public class UserVOFactory { - //TODO give a direct access public static final String[] keys = new String[] { "male", "female", "-" }; - /* EntityTag for Idenetiy is complex to compute. Every UserProperty is saved separately. - public static EntityTag computeEtag(Identity identity) { - int version = ((IdentityImpl)identity).getVersion(); - Long key = identity.getKey(); - return new EntityTag("Identity-" + key + "-" + version); - }*/ - public static UserVO get(Identity identity) { return get(identity, I18nModule.getDefaultLocale(), false, false, false); } @@ -93,6 +85,7 @@ public class UserVOFactory { if(identity != null) { userVO.setLogin(identity.getName()); } + userVO.setExternalId(identity.getExternalId()); userVO.setFirstName(user.getProperty(UserConstants.FIRSTNAME, null)); userVO.setLastName(user.getProperty(UserConstants.LASTNAME, null)); userVO.setEmail(user.getProperty(UserConstants.EMAIL, null)); diff --git a/src/test/java/org/olat/restapi/CoursesTest.java b/src/test/java/org/olat/restapi/CoursesTest.java index 2fdd690dd0b233f49a516ad3a15084decdedcb96..13c30aa930e9c12754ffab9ba37f0975c7cc2607 100644 --- a/src/test/java/org/olat/restapi/CoursesTest.java +++ b/src/test/java/org/olat/restapi/CoursesTest.java @@ -59,19 +59,24 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.olat.basesecurity.BaseSecurityManager; +import org.olat.basesecurity.GroupRoles; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; +import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryRelationType; import org.olat.repository.RepositoryManager; import org.olat.repository.manager.RepositoryEntryLifecycleDAO; +import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.olat.repository.model.RepositoryEntryLifecycle; import org.olat.restapi.repository.course.CoursesWebService; import org.olat.restapi.support.vo.CourseVO; import org.olat.restapi.support.vo.CourseVOes; +import org.olat.test.JunitTestHelper; import org.olat.test.OlatJerseyTestCase; import org.springframework.beans.factory.annotation.Autowired; @@ -92,6 +97,8 @@ public class CoursesTest extends OlatJerseyTestCase { private RepositoryManager repositoryManager; @Autowired private RepositoryEntryLifecycleDAO reLifecycleDao; + @Autowired + private RepositoryEntryRelationDAO repositoryEntryRelationDao; /** * SetUp is called before each test. @@ -303,11 +310,84 @@ public class CoursesTest extends OlatJerseyTestCase { assertNotNull(course); assertEquals("course3", course.getTitle()); //check repository entry - RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntry(course.getRepoEntryKey()); + RepositoryEntry re = repositoryManager.lookupRepositoryEntry(course.getRepoEntryKey()); assertNotNull(re); assertNotNull(re.getOlatResource()); } + @Test + public void testCreateEmpty_withoutAuthorCourse() throws IOException, URISyntaxException { + assertTrue(conn.login("administrator", "openolat")); + + URI uri = UriBuilder.fromUri(getContextURI()).path("repo").path("courses") + .queryParam("shortTitle", "Course without author") + .queryParam("title", "Course without author") + .queryParam("setAuthor", "false").build(); + HttpPut method = conn.createPut(uri, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + CourseVO courseVo = conn.parse(response, CourseVO.class); + Assert.assertNotNull(courseVo); + Assert.assertEquals("Course without author", courseVo.getTitle()); + + // load repository entry + RepositoryEntry re = repositoryManager.lookupRepositoryEntry(courseVo.getRepoEntryKey()); + Assert.assertNotNull(re); + Assert.assertNotNull(re.getOlatResource()); + Assert.assertEquals("Course without author", re.getDisplayname()); + + // load the course + ICourse course = CourseFactory.loadCourse(re.getOlatResource().getResourceableId()); + Assert.assertNotNull(course); + Assert.assertEquals("Course without author", course.getCourseTitle()); + Assert.assertEquals(re, course.getCourseEnvironment().getCourseGroupManager().getCourseEntry()); + + // check the list of owners + List<Identity> owners = repositoryEntryRelationDao.getMembers(re, RepositoryEntryRelationType.both, GroupRoles.owner.name()); + Assert.assertNotNull(owners); + Assert.assertTrue(owners.isEmpty()); + } + + @Test + public void testCreateEmpty_withInitialAuthor() throws IOException, URISyntaxException { + Identity adhocAuthor = JunitTestHelper.createAndPersistIdentityAsRndUser("adhoc-author"); + dbInstance.commit(); + + assertTrue(conn.login("administrator", "openolat")); + + URI uri = UriBuilder.fromUri(getContextURI()).path("repo").path("courses") + .queryParam("shortTitle", "Course without author") + .queryParam("title", "Course without author") + .queryParam("initialAuthor", adhocAuthor.getKey().toString()) + .build(); + HttpPut method = conn.createPut(uri, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + CourseVO courseVo = conn.parse(response, CourseVO.class); + Assert.assertNotNull(courseVo); + Assert.assertEquals("Course without author", courseVo.getTitle()); + + // load repository entry + RepositoryEntry re = repositoryManager.lookupRepositoryEntry(courseVo.getRepoEntryKey()); + Assert.assertNotNull(re); + Assert.assertNotNull(re.getOlatResource()); + Assert.assertEquals("Course without author", re.getDisplayname()); + + // load the course + ICourse course = CourseFactory.loadCourse(re.getOlatResource().getResourceableId()); + Assert.assertNotNull(course); + Assert.assertEquals("Course without author", course.getCourseTitle()); + Assert.assertEquals(re, course.getCourseEnvironment().getCourseGroupManager().getCourseEntry()); + + // check the list of owners + List<Identity> owners = repositoryEntryRelationDao.getMembers(re, RepositoryEntryRelationType.both, GroupRoles.owner.name()); + Assert.assertNotNull(owners); + Assert.assertEquals(1, owners.size()); + Assert.assertEquals(adhocAuthor, owners.get(0)); + } + @Test public void testImportCourse() throws IOException, URISyntaxException { URL cpUrl = CoursesTest.class.getResource("Course_with_blog.zip");