Skip to content
Snippets Groups Projects
Commit a927d79a authored by srosse's avatar srosse
Browse files

OO-316: implement a method to deploy a course

parent 368a8e0e
No related branches found
No related tags found
No related merge requests found
...@@ -587,6 +587,10 @@ public class CourseFactory extends BasicManager { ...@@ -587,6 +587,10 @@ public class CourseFactory extends BasicManager {
* @param exportedCourseZIPFile * @param exportedCourseZIPFile
*/ */
public static RepositoryEntry deployCourseFromZIP(File exportedCourseZIPFile, int access) { public static RepositoryEntry deployCourseFromZIP(File exportedCourseZIPFile, int access) {
return deployCourseFromZIP(exportedCourseZIPFile, "administrator", null, access);
}
public static RepositoryEntry deployCourseFromZIP(File exportedCourseZIPFile, String initialAuthor, String softKey, int access) {
// create the course instance // create the course instance
OLATResource newCourseResource = olatResourceManager.createOLATResourceInstance(CourseModule.class); OLATResource newCourseResource = olatResourceManager.createOLATResourceInstance(CourseModule.class);
ICourse course = CourseFactory.importCourseFromZip(newCourseResource, exportedCourseZIPFile); ICourse course = CourseFactory.importCourseFromZip(newCourseResource, exportedCourseZIPFile);
...@@ -600,7 +604,9 @@ public class CourseFactory extends BasicManager { ...@@ -600,7 +604,9 @@ public class CourseFactory extends BasicManager {
// create the repository entry // create the repository entry
RepositoryEntry re = repositoryManager.createRepositoryEntryInstance("administrator"); RepositoryEntry re = repositoryManager.createRepositoryEntryInstance("administrator");
RepositoryEntryImportExport importExport = new RepositoryEntryImportExport(courseExportData); RepositoryEntryImportExport importExport = new RepositoryEntryImportExport(courseExportData);
String softKey = importExport.getSoftkey(); if(!StringHelper.containsNonWhitespace(softKey)) {
softKey = importExport.getSoftkey();
}
RepositoryEntry existingEntry = repositoryManager.lookupRepositoryEntryBySoftkey(softKey, false); RepositoryEntry existingEntry = repositoryManager.lookupRepositoryEntryBySoftkey(softKey, false);
if (existingEntry != null) { if (existingEntry != null) {
Tracing.logInfo("RepositoryEntry with softkey " + softKey + " already exists. Course will not be deployed.", CourseFactory.class); Tracing.logInfo("RepositoryEntry with softkey " + softKey + " already exists. Course will not be deployed.", CourseFactory.class);
......
...@@ -58,6 +58,7 @@ import org.olat.basesecurity.BaseSecurityManager; ...@@ -58,6 +58,7 @@ import org.olat.basesecurity.BaseSecurityManager;
import org.olat.basesecurity.Constants; import org.olat.basesecurity.Constants;
import org.olat.basesecurity.SecurityGroup; import org.olat.basesecurity.SecurityGroup;
import org.olat.core.id.Identity; import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles; import org.olat.core.id.Roles;
import org.olat.core.logging.OLog; import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing; import org.olat.core.logging.Tracing;
...@@ -316,66 +317,71 @@ public class RepositoryEntriesResource { ...@@ -316,66 +317,71 @@ public class RepositoryEntriesResource {
try { try {
FileResourceManager frm = FileResourceManager.getInstance(); FileResourceManager frm = FileResourceManager.getInstance();
FileResource newResource = frm.addFileResource(fResource, fResource.getName()); FileResource newResource = frm.addFileResource(fResource, fResource.getName());
return importResource(identity, newResource, resourcename, displayname, softkey);
} catch(Exception e) {
log.error("Fail to import a resource", e);
throw new WebApplicationException(e);
}
}
public static RepositoryEntry importResource(Identity identity, OLATResourceable newResource, String resourcename, String displayname,
String softkey) {
RepositoryEntry addedEntry = RepositoryManager.getInstance().createRepositoryEntryInstance(identity.getName()); RepositoryEntry addedEntry = RepositoryManager.getInstance().createRepositoryEntryInstance(identity.getName());
addedEntry.setCanDownload(false); addedEntry.setCanDownload(false);
addedEntry.setCanLaunch(true); addedEntry.setCanLaunch(true);
if(StringHelper.containsNonWhitespace(resourcename)) { if(StringHelper.containsNonWhitespace(resourcename)) {
addedEntry.setResourcename(resourcename); addedEntry.setResourcename(resourcename);
} }
if(StringHelper.containsNonWhitespace(displayname)) { if(StringHelper.containsNonWhitespace(displayname)) {
addedEntry.setDisplayname(displayname); addedEntry.setDisplayname(displayname);
} }
if(StringHelper.containsNonWhitespace(softkey)) { if(StringHelper.containsNonWhitespace(softkey)) {
addedEntry.setSoftkey(softkey); addedEntry.setSoftkey(softkey);
} }
// Do set access for owner at the end, because unfinished course should be // Do set access for owner at the end, because unfinished course should be
// invisible // invisible
// addedEntry.setAccess(RepositoryEntry.ACC_OWNERS); // addedEntry.setAccess(RepositoryEntry.ACC_OWNERS);
addedEntry.setAccess(0);// Access for nobody addedEntry.setAccess(0);// Access for nobody
// Set the resource on the repository entry and save the entry. // Set the resource on the repository entry and save the entry.
RepositoryManager rm = RepositoryManager.getInstance(); RepositoryManager rm = RepositoryManager.getInstance();
OLATResource ores = OLATResourceManager.getInstance().findOrPersistResourceable(newResource); OLATResource ores = OLATResourceManager.getInstance().findOrPersistResourceable(newResource);
addedEntry.setOlatResource(ores); addedEntry.setOlatResource(ores);
BaseSecurity securityManager = BaseSecurityManager.getInstance(); BaseSecurity securityManager = BaseSecurityManager.getInstance();
// create security group // create security group
SecurityGroup newGroup = securityManager.createAndPersistSecurityGroup(); SecurityGroup newGroup = securityManager.createAndPersistSecurityGroup();
// member of this group may modify member's membership // member of this group may modify member's membership
securityManager.createAndPersistPolicy(newGroup, Constants.PERMISSION_ACCESS, newGroup); securityManager.createAndPersistPolicy(newGroup, Constants.PERMISSION_ACCESS, newGroup);
// members of this group are always authors also // members of this group are always authors also
securityManager.createAndPersistPolicy(newGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_AUTHOR); securityManager.createAndPersistPolicy(newGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_AUTHOR);
securityManager.addIdentityToSecurityGroup(identity, newGroup); securityManager.addIdentityToSecurityGroup(identity, newGroup);
addedEntry.setOwnerGroup(newGroup); addedEntry.setOwnerGroup(newGroup);
//fxdiff VCRP-1,2: access control of resources //fxdiff VCRP-1,2: access control of resources
// security group for tutors / coaches // security group for tutors / coaches
SecurityGroup tutorGroup = securityManager.createAndPersistSecurityGroup(); SecurityGroup tutorGroup = securityManager.createAndPersistSecurityGroup();
// member of this group may modify member's membership // member of this group may modify member's membership
securityManager.createAndPersistPolicy(tutorGroup, Constants.PERMISSION_ACCESS, addedEntry.getOlatResource()); securityManager.createAndPersistPolicy(tutorGroup, Constants.PERMISSION_ACCESS, addedEntry.getOlatResource());
// members of this group are always tutors also // members of this group are always tutors also
securityManager.createAndPersistPolicy(tutorGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_TUTOR); securityManager.createAndPersistPolicy(tutorGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_TUTOR);
addedEntry.setTutorGroup(tutorGroup); addedEntry.setTutorGroup(tutorGroup);
// security group for participants // security group for participants
SecurityGroup participantGroup = securityManager.createAndPersistSecurityGroup(); SecurityGroup participantGroup = securityManager.createAndPersistSecurityGroup();
// member of this group may modify member's membership // member of this group may modify member's membership
securityManager.createAndPersistPolicy(participantGroup, Constants.PERMISSION_ACCESS, addedEntry.getOlatResource()); securityManager.createAndPersistPolicy(participantGroup, Constants.PERMISSION_ACCESS, addedEntry.getOlatResource());
// members of this group are always participants also // members of this group are always participants also
securityManager.createAndPersistPolicy(participantGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_PARTICIPANT); securityManager.createAndPersistPolicy(participantGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_PARTICIPANT);
addedEntry.setParticipantGroup(participantGroup); addedEntry.setParticipantGroup(participantGroup);
// Do set access for owner at the end, because unfinished course should be // Do set access for owner at the end, because unfinished course should be
// invisible // invisible
addedEntry.setAccess(RepositoryEntry.ACC_OWNERS); addedEntry.setAccess(RepositoryEntry.ACC_OWNERS);
rm.saveRepositoryEntry(addedEntry); rm.saveRepositoryEntry(addedEntry);
return addedEntry; return addedEntry;
} catch (Exception e) {
log.error("Fail to import a resource", e);
throw new WebApplicationException(e);
}
} }
private File getTmpFile(String suffix) { private File getTmpFile(String suffix) {
......
...@@ -24,12 +24,16 @@ import static org.olat.restapi.security.RestSecurityHelper.getRoles; ...@@ -24,12 +24,16 @@ import static org.olat.restapi.security.RestSecurityHelper.getRoles;
import static org.olat.restapi.security.RestSecurityHelper.getUserRequest; import static org.olat.restapi.security.RestSecurityHelper.getUserRequest;
import static org.olat.restapi.security.RestSecurityHelper.isAuthor; import static org.olat.restapi.security.RestSecurityHelper.isAuthor;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
...@@ -52,8 +56,11 @@ import org.olat.core.id.OLATResourceable; ...@@ -52,8 +56,11 @@ import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles; import org.olat.core.id.Roles;
import org.olat.core.logging.OLog; import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing; import org.olat.core.logging.Tracing;
import org.olat.core.util.CodeHelper;
import org.olat.core.util.FileUtils;
import org.olat.core.util.Formatter; import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.coordinate.LockResult; import org.olat.core.util.coordinate.LockResult;
import org.olat.core.util.resource.OresHelper; import org.olat.core.util.resource.OresHelper;
import org.olat.course.CourseFactory; import org.olat.course.CourseFactory;
...@@ -70,7 +77,9 @@ import org.olat.repository.handlers.RepositoryHandler; ...@@ -70,7 +77,9 @@ import org.olat.repository.handlers.RepositoryHandler;
import org.olat.repository.handlers.RepositoryHandlerFactory; import org.olat.repository.handlers.RepositoryHandlerFactory;
import org.olat.resource.OLATResource; import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager; import org.olat.resource.OLATResourceManager;
import org.olat.restapi.security.RestSecurityHelper;
import org.olat.restapi.support.MediaTypeVariants; import org.olat.restapi.support.MediaTypeVariants;
import org.olat.restapi.support.MultipartReader;
import org.olat.restapi.support.ObjectFactory; import org.olat.restapi.support.ObjectFactory;
import org.olat.restapi.support.vo.CourseConfigVO; import org.olat.restapi.support.vo.CourseConfigVO;
import org.olat.restapi.support.vo.CourseVO; import org.olat.restapi.support.vo.CourseVO;
...@@ -203,6 +212,57 @@ public class CoursesWebService { ...@@ -203,6 +212,57 @@ public class CoursesWebService {
return Response.ok(vo).build(); return Response.ok(vo).build();
} }
/**
*
*
*
* @param request
* @param access
* @return
*/
@POST
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Consumes({MediaType.MULTIPART_FORM_DATA})
public Response importCourse(@Context HttpServletRequest request) {
if(!isAuthor(request)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
Identity identity = RestSecurityHelper.getUserRequest(request).getIdentity();
File tmpFile = null;
try {
MultipartReader partsReader = new MultipartReader(request);
tmpFile = partsReader.getFile();
long length = tmpFile.length();
if(length > 0) {
Long accessRaw = partsReader.getLongValue("access");
int access = accessRaw != null ? accessRaw.intValue() : RepositoryEntry.ACC_OWNERS;
String softKey = partsReader.getValue("softkey");
ICourse course = importCourse(identity, tmpFile, softKey, access);
CourseVO vo = ObjectFactory.get(course);
return Response.ok(vo).build();
}
return Response.serverError().status(Status.NO_CONTENT).build();
} catch (Exception e) {
log.error("Error while importing a file",e);
} finally {
if(tmpFile != null && tmpFile.exists()) {
tmpFile.delete();
}
}
CourseVO vo = null;
return Response.ok(vo).build();
}
public static ICourse importCourse(Identity identity, File fCourseImportZIP, String softKey, int access) {
RepositoryEntry re = CourseFactory.deployCourseFromZIP(fCourseImportZIP, identity.getName(), softKey, access);
ICourse course = CourseFactory.loadCourse(re.getOlatResource());
return course;
}
public static ICourse copyCourse(Long copyFrom, UserRequest ureq, String name, String longTitle, CourseConfigVO courseConfigVO) { public static ICourse copyCourse(Long copyFrom, UserRequest ureq, String name, String longTitle, CourseConfigVO courseConfigVO) {
String shortTitle = name; String shortTitle = name;
//String learningObjectives = name + " (Example of creating a new course)"; //String learningObjectives = name + " (Example of creating a new course)";
......
/**
* <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>
* 12.10.2011 by frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.restapi.support;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
/**
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public class MultipartReader {
private static final OLog log = Tracing.createLoggerFor(MultipartReader.class);
private String filename;
private String contentType;
private File file;
private Map<String, String> fields = new HashMap<String, String>();
public MultipartReader(HttpServletRequest request) {
long uploadLimit = -1l;
apache(request, uploadLimit);
}
private final void apache(HttpServletRequest request, long uploadLimit) {
ServletFileUpload uploadParser = new ServletFileUpload();
uploadParser.setSizeMax((uploadLimit * 1024l) + 512000l);
// Parse the request
try {
FileItemIterator iter = uploadParser.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String itemName = item.getFieldName();
InputStream itemStream = item.openStream();
if (item.isFormField()) {
String value = Streams.asString(itemStream, "UTF-8");
fields.put(itemName, value);
} else {
// File item, store it to temp location
filename = item.getName();
contentType = item.getContentType();
file = new File(System.getProperty("java.io.tmpdir"), "upload-" + UUID.randomUUID().toString().replace("-", ""));
try {
save(itemStream, file);
} catch (Exception e) {
log.error("", e);
}
}
}
} catch (Exception e) {
log.error("", e);
}
}
public String getFilename() {
return filename;
}
public String getContentType() {
return contentType;
}
public String getText() {
return fields.get("text");
}
public String getValue(String key) {
String value = fields.get(key);
return value;
}
public Long getLongValue(String key) {
String value = fields.get(key);
if (value == null) { return null; }
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return null;
}
}
public File getFile() {
return file;
}
private void save(InputStream source, File targetFile)
throws IOException {
InputStream in = new BufferedInputStream(source);
OutputStream out = new FileOutputStream(targetFile);
byte[] buffer = new byte[4096];
int c;
while ((c = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, c);
}
out.flush();
out.close();
in.close();
}
public void close() {
if (file != null) {
file.delete();
}
fields.clear();
}
}
...@@ -31,18 +31,26 @@ import static org.junit.Assert.assertEquals; ...@@ -31,18 +31,26 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL;
import java.util.List; import java.util.List;
import java.util.UUID;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference; import org.codehaus.jackson.type.TypeReference;
import org.junit.After; import org.junit.After;
...@@ -166,6 +174,45 @@ public class CoursesTest extends OlatJerseyTestCase { ...@@ -166,6 +174,45 @@ public class CoursesTest extends OlatJerseyTestCase {
assertNotNull(re.getOwnerGroup()); assertNotNull(re.getOwnerGroup());
} }
@Test
public void testImportCourse() throws IOException, URISyntaxException {
URL cpUrl = CoursesTest.class.getResource("Very_small_course.zip");
assertNotNull(cpUrl);
File cp = new File(cpUrl.toURI());
assertTrue(conn.login("administrator", "openolat"));
URI request = UriBuilder.fromUri(getContextURI()).path("repo/courses").build();
HttpPost method = conn.createPost(request, MediaType.APPLICATION_JSON, true);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("file", new FileBody(cp));
entity.addPart("filename", new StringBody("Very_small_course.zip"));
entity.addPart("resourcename", new StringBody("Very small course"));
entity.addPart("displayname", new StringBody("Very small course"));
entity.addPart("access", new StringBody("3"));
String softKey = UUID.randomUUID().toString().replace("-", "").substring(0, 30);
entity.addPart("softkey", new StringBody(softKey));
method.setEntity(entity);
HttpResponse response = conn.execute(method);
assertTrue(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201);
InputStream body = response.getEntity().getContent();
CourseVO vo = parse(body, CourseVO.class);
assertNotNull(vo);
assertNotNull(vo.getRepoEntryKey());
assertNotNull(vo.getKey());
Long repoKey = vo.getRepoEntryKey();
RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntry(repoKey);
assertNotNull(re);
assertNotNull(re.getOwnerGroup());
assertNotNull(re.getOlatResource());
assertEquals("Very small course", re.getDisplayname());
assertEquals(softKey, re.getSoftkey());
}
@Test @Test
public void testGetCourseInfos() throws IOException, URISyntaxException { public void testGetCourseInfos() throws IOException, URISyntaxException {
boolean loggedIN = conn.login("administrator", "openolat"); boolean loggedIN = conn.login("administrator", "openolat");
......
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment