diff --git a/src/main/java/de/bps/course/nodes/cl/_spring/buildingblockContext.xml b/src/main/java/de/bps/course/nodes/cl/_spring/buildingblockContext.xml index 43e299b2c6b72c1db1c145f5aef20e5af585ba48..d8c602b3efc9f44dd3843be552f5a57e8b5b839d 100644 --- a/src/main/java/de/bps/course/nodes/cl/_spring/buildingblockContext.xml +++ b/src/main/java/de/bps/course/nodes/cl/_spring/buildingblockContext.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> + http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cl" class="de.bps.course.nodes.cl.ChecklistCourseNodeConfiguration" scope="prototype"> <property name="enabled" value="${course.node.checklist.enabled}" /> diff --git a/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java b/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java index d1a814ae2788a1ea460f890e3642e23cad3f0b7e..32a1e596abb6eeab9d726ee708c2647a4e2a3986 100644 --- a/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java +++ b/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java @@ -297,8 +297,6 @@ public class UserDeletionManager extends BasicManager { logInfo("UserDataDeletable-Loop element=" + element); element.deleteUserData(identity, newName); } - logInfo("deleteUserProperties user=" + identity.getUser()); - UserManager.getInstance().deleteUserProperties(identity.getUser()); // Delete all authentications for certain identity List<Authentication> authentications = securityManager.getAuthentications(identity); for (Iterator<Authentication> iter = authentications.iterator(); iter.hasNext();) { @@ -344,8 +342,12 @@ public class UserDeletionManager extends BasicManager { } } + logInfo("deleteUserProperties user=" + identity.getUser()); + UserManager.getInstance().deleteUserProperties(identity.getUser(), keepUserEmailAfterDeletion); + DBFactory.getInstance().commit(); + identity = securityManager.loadIdentityByKey(identity.getKey()); //keep email only -> change login-name - if (!keepUserLoginAfterDeletion){ + if (!keepUserEmailAfterDeletion) { identity = securityManager.saveIdentityName(identity, newName, null); } diff --git a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java index 5f22f86038cf608b9b5299600122f8e69b94d593..36a935b05e3a4563c47380b85ed7dee1df9f05cb 100644 --- a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java +++ b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java @@ -99,8 +99,30 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { FileChannelWrapper in = new FileChannelWrapper(ch); MP4Demuxer demuxer1 = new MP4Demuxer(in); org.jcodec.common.model.Size size = demuxer1.getMovie().getDisplaySize(); + // Case 1: standard case, get dimension from movie int w = size.getWidth(); int h = size.getHeight(); + // Case 2: landscape movie from iOS: width and height is negative, no dunny why + if (w < 0 && h < 0) { + w = 0 - w; + h = 0 - h; + } + if (w == 0) { + // Case 3: portrait movie from iOS: movie dimensions are not set, but there + // something in the track box. + try { + // This code is the way it is just because I don't know + // how to safely read the rotation/portrait/landscape + // flag of the movie. Those mp4 guys are really + // secretive folks, did not find any documentation about + // this. Best guess. + org.jcodec.common.model.Size size2 = demuxer1.getVideoTrack().getBox().getCodedSize(); + w = size2.getHeight(); + h = size2.getWidth(); + } catch(Exception e) { + log.debug("can not get size from box " + e.getMessage()); + } + } return new Size(w, h, false); } catch (Exception | AssertionError e) { log.error("Cannot extract size of: " + media, e); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FileElement.java b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FileElement.java index 7c1442120b410e4a6b5224677b2f36234e4ef954..4092fd8fa5257bbe04fe23e285c2f13b975b09f2 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FileElement.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FileElement.java @@ -135,6 +135,15 @@ public interface FileElement extends FormMultipartItem { */ public String getUploadFileName(); + /** + * Set the filename of the uploaded file. Use this if you want the final filename + * to be something different than file name from the upload. Whenever a file is + * uploaded again, this name is replaced again by the browser provided upload file name + * + * @param the uploaded file name + */ + public void setUploadFileName(String uploadFileName); + /** * The mime type is first looked up by servletContext.getMimeType(). If no * mime type is available, the browser supplied mime type is used. diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java index 13bb290644e972e568660ec0075c37887b876f26..a74801a12275be33b6f1b954a1a76f6e1e4621dd 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java @@ -464,6 +464,12 @@ public class FileElementImpl extends FormItemImpl public String getUploadFileName() { return uploadFilename; } + + @Override + public void setUploadFileName(String uploadFileName) { + this.uploadFilename = uploadFileName; + this.uploadMimeType = WebappHelper.getMimeType(uploadFilename); + } /** * @see org.olat.core.gui.components.form.flexible.elements.FileElement#getUploadMimeType() diff --git a/src/main/java/org/olat/modules/webFeed/ui/podcast/EpisodeFormController.java b/src/main/java/org/olat/modules/webFeed/ui/podcast/EpisodeFormController.java index ce2aecd920ff6c33a9c15db7060b505c2c219b4f..ccb04522550caeb49718ae10b32f794e04f79b14 100644 --- a/src/main/java/org/olat/modules/webFeed/ui/podcast/EpisodeFormController.java +++ b/src/main/java/org/olat/modules/webFeed/ui/podcast/EpisodeFormController.java @@ -22,6 +22,8 @@ package org.olat.modules.webFeed.ui.podcast; import java.io.File; import java.util.Date; +import org.olat.core.commons.services.image.Size; +import org.olat.core.commons.services.video.MovieService; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -42,12 +44,15 @@ import org.olat.core.util.FileUtils; import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.core.util.WebappHelper; +import org.olat.core.util.vfs.LocalFileImpl; import org.olat.core.util.vfs.Quota; import org.olat.core.util.vfs.VFSContainer; +import org.olat.core.util.vfs.VFSLeaf; import org.olat.core.util.vfs.callbacks.FullAccessWithQuotaCallback; import org.olat.modules.webFeed.managers.FeedManager; import org.olat.modules.webFeed.models.Feed; import org.olat.modules.webFeed.models.Item; +import org.springframework.beans.factory.annotation.Autowired; /** * Provides a form for editing episode data (title, description, file ...) @@ -75,6 +80,9 @@ public class EpisodeFormController extends FormBasicController { private FileElement file; private FormLink cancelButton; + @Autowired + private MovieService movieService; + /** * @param ureq * @param control @@ -151,8 +159,23 @@ public class EpisodeFormController extends FormBasicController { file.clearError(); if (file.isUploadSuccess()) { - String newFilename = file.getUploadFileName(); - boolean isValidFileType = newFilename.toLowerCase().matches(MIME_TYPES_ALLOWED); + String newFilename = file.getUploadFileName().toLowerCase(); + VFSLeaf movie = new LocalFileImpl(file.getUploadFile()); + // remove spaces + newFilename = newFilename.replaceAll(" ", "_"); + file.setUploadFileName(newFilename); + + if (newFilename.endsWith("mov") || newFilename.endsWith("m4v")) { + // Check if it actually is a mp4 file, if so rename file to + // mp4 to make later processes work smoothly. MOV is used + // when uploading a video from an iOS device. + if (movieService.isMP4(movie, newFilename)) { + newFilename = newFilename.substring(0, newFilename.length() - 3) + "mp4"; + file.setUploadFileName(newFilename); + } + + } + boolean isValidFileType = newFilename.matches(MIME_TYPES_ALLOWED); boolean isFilenameValid = validateFilename(newFilename); if (!isValidFileType || !isFilenameValid) { if(!isValidFileType) { @@ -160,6 +183,17 @@ public class EpisodeFormController extends FormBasicController { } else if (!isFilenameValid) { file.setErrorKey("podcastfile.name.notvalid", null); } + } else { + // try to autodetect width and height for movies, prefill for user if possible + Size size = movieService.getSize(movie, FileUtils.getFileSuffix(newFilename)); + if (size != null) { + if (size.getWidth() > 1) { + widthEl.setValue(size.getWidth() + ""); + } + if (size.getHeight() > 1) { + heightEl.setValue(size.getHeight() + ""); + } + } } } } diff --git a/src/main/java/org/olat/user/UserManager.java b/src/main/java/org/olat/user/UserManager.java index 9aa14e10455301b54831307fb7afcb7fcf9fcf9e..514185a7babfbb99e714e5fa3fe6ab0fd21b48a4 100644 --- a/src/main/java/org/olat/user/UserManager.java +++ b/src/main/java/org/olat/user/UserManager.java @@ -198,7 +198,7 @@ public abstract class UserManager extends BasicManager { * Delete all user-properties which are deletable. * @param user */ - public abstract void deleteUserProperties(User user); + public abstract User deleteUserProperties(User user, boolean keepUserEmail); public List<UserPropertyHandler> getUserPropertyHandlersFor(String usageIdentifyer, boolean isAdministrativeUser) { return userPropertiesConfig.getUserPropertyHandlersFor(usageIdentifyer, isAdministrativeUser); diff --git a/src/main/java/org/olat/user/UserManagerImpl.java b/src/main/java/org/olat/user/UserManagerImpl.java index 2c1a83a788c478e8a1c004ccb68da2df7d57d0e6..abdb33b3f7ff34ba175fdb5b1eb4d5736122de57 100644 --- a/src/main/java/org/olat/user/UserManagerImpl.java +++ b/src/main/java/org/olat/user/UserManagerImpl.java @@ -420,7 +420,7 @@ public class UserManagerImpl extends UserManager { * @param user */ @Override - public void deleteUserProperties(User user) { + public User deleteUserProperties(User user, boolean keepUserEmail) { // prevent stale objects, reload first user = loadUserByKey(user.getKey()); // loop over user fields and remove them form the database if they are @@ -428,13 +428,15 @@ public class UserManagerImpl extends UserManager { List<UserPropertyHandler> propertyHandlers = userPropertiesConfig.getAllUserPropertyHandlers(); for (UserPropertyHandler propertyHandler : propertyHandlers) { String fieldName = propertyHandler.getName(); - if (propertyHandler.isDeletable()) { + if (propertyHandler.isDeletable() + && !(keepUserEmail && UserConstants.EMAIL.equals(propertyHandler.getName()))) { user.setProperty(fieldName, null); } } // persist changes - updateUser(user); + User updatedUser = updateUser(user); if(isLogDebugEnabled()) logDebug("Delete all user-attributtes for user=" + user); + return updatedUser; } @Override diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml index 1497a44acfd786f7c3bd396f57f6d0c6d04ace60..702279e689a679b51b83aaacb14507ba21561c0f 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml +++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml @@ -151,7 +151,7 @@ <bean id="userPropertyInstitutionalUserIdentifier" class="org.olat.user.propertyhandlers.Generic127CharTextPropertyHandler"> <property name="name" value="institutionalUserIdentifier" /> <property name="group" value="institute" /> - <property name="deletable" value="false" /> + <property name="deletable" value="true" /> </bean> <bean id="userPropertyInstitutionalEmail" class="org.olat.user.propertyhandlers.EmailProperty"> diff --git a/src/test/java/org/olat/admin/user/delete/service/UserDeletionManagerTest.java b/src/test/java/org/olat/admin/user/delete/service/UserDeletionManagerTest.java index 95fc1af5677d80b9077879ca1f6b3e1a0b1ddb51..de6a226c8bb3963fa216fb0e5ea0992eb6aa14a1 100644 --- a/src/test/java/org/olat/admin/user/delete/service/UserDeletionManagerTest.java +++ b/src/test/java/org/olat/admin/user/delete/service/UserDeletionManagerTest.java @@ -31,15 +31,20 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.BaseSecurityModule; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.id.Identity; +import org.olat.core.id.User; +import org.olat.core.id.UserConstants; +import org.olat.core.util.StringHelper; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.portfolio.manager.EPFrontendManager; @@ -50,6 +55,7 @@ import org.olat.portfolio.model.structel.PortfolioStructure; import org.olat.portfolio.model.structel.PortfolioStructureMap; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; +import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; /** @@ -62,6 +68,8 @@ public class UserDeletionManagerTest extends OlatTestCase { @Autowired private DB dbInstance; @Autowired + private UserManager userManager; + @Autowired private BaseSecurity securityManager; @Autowired private EPFrontendManager epFrontendManager; @@ -74,8 +82,14 @@ public class UserDeletionManagerTest extends OlatTestCase { @Test public void testDeleteIdentity() { - Identity identity = JunitTestHelper.createAndPersistIdentityAsUser("anIdentityToDelete"); - dbInstance.commit(); + String username = "id-to-del-" + UUID.randomUUID(); + User user = userManager.createUser("first" + username, "last" + username, username + "@frentix.com"); + user.setProperty(UserConstants.COUNTRY, ""); + user.setProperty(UserConstants.CITY, "Basel"); + user.setProperty(UserConstants.INSTITUTIONALNAME, "Del-23"); + user.setProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, "Del-24"); + Identity identity = securityManager.createAndPersistIdentityAndUser(username, null, user, BaseSecurityModule.getDefaultAuthProviderIdentifier(), username, "secret"); + dbInstance.commitAndCloseSession(); // add some stuff //a default map @@ -116,6 +130,12 @@ public class UserDeletionManagerTest extends OlatTestCase { //check membership of group boolean isMember = businessGroupService.isIdentityInBusinessGroup(deletedIdentity, group); Assert.assertFalse(isMember); + + User deletedUser = deletedIdentity.getUser(); + String institutionalName = deletedUser.getProperty(UserConstants.INSTITUTIONALNAME, null); + Assert.assertFalse(StringHelper.containsNonWhitespace(institutionalName)); + String institutionalId = deletedUser.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, null); + Assert.assertFalse(StringHelper.containsNonWhitespace(institutionalId)); } @Test