diff options
18 files changed, 170 insertions, 161 deletions
diff --git a/dozentenmodul/pom.xml b/dozentenmodul/pom.xml index cae6faf0..027520e7 100755 --- a/dozentenmodul/pom.xml +++ b/dozentenmodul/pom.xml @@ -8,7 +8,7 @@ <packaging>jar</packaging> <name>DozMod-Client</name> - <url>http://maven.apache.org</url> + <url>https://git.openslx.org/openslx-ng/tutor-module.git</url> <scm> <connection>scm:git:git://git.openslx.org/openslx-ng/tutor-module.git</connection> </scm> @@ -164,7 +164,7 @@ </dependency> <dependency> <groupId>org.openslx</groupId> - <artifactId>proxy_vole</artifactId> + <artifactId>proxy-vole</artifactId> <version>0.0.4-SNAPSHOT</version> <scope>compile</scope> </dependency> @@ -174,7 +174,7 @@ <version>[4.5.3,4.5.99]</version> <scope>compile</scope> </dependency> - <dependency> + <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>[2.0,]</version> diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/ImageListViewer.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/ImageListViewer.java index c7e7fd77..005dc602 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/ImageListViewer.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/ImageListViewer.java @@ -81,14 +81,9 @@ public class ImageListViewer extends QLabel { ImageSummaryRead image = imageTable.getModelRow(entry.getIdentifier()); if (searchFieldPattern.matcher(image.imageName).find()) return true; - if (chkSearchInDescription.isSelected()) { - String description = image.description; - if (description != null) { - if (searchFieldPattern.matcher(description).find()) - return true; - } else { - LOGGER.debug("Description is null: cannot be searched in description"); - } + if (chkSearchInDescription.isSelected() && image.description != null) { + if (searchFieldPattern.matcher(image.description).find()) + return true; } UserInfo user = UserCache.find(image.ownerId); if (user == null) diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java index f1a4d4c6..dfb6f751 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java @@ -8,12 +8,12 @@ import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; -import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; +import javax.swing.JTextArea; import javax.swing.JTextField; import org.openslx.bwlp.thrift.iface.OperatingSystem; @@ -45,7 +45,7 @@ public abstract class ImageDetailsWindowLayout extends JDialog { // private final String TAB_PERMISSIONS_TITEL = I18n.WINDOW_LAYOUT.getString("ImageDetails.Tab.permissions.title"); protected final JTextField txtTitle; - protected final JEditorPane txtDescription; + protected final JTextArea txtDescription; protected QLabel lblError; protected final PersonLabel lblOwner; @@ -108,8 +108,9 @@ public abstract class ImageDetailsWindowLayout extends JDialog { grid.nextRow(); // description - txtDescription = new JEditorPane(); - + txtDescription = new JTextArea(3, 50); + txtDescription.setLineWrap(true); + txtDescription.setWrapStyleWord(true); grid.add(new QLabel(I18n.WINDOW_LAYOUT.getString("ImageDetails.Label.description.text"))).anchor = GridBagConstraints.FIRST_LINE_START; JScrollPane jsp = new JScrollPane(txtDescription, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java index 2b134ba0..3876e7fb 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java @@ -14,12 +14,12 @@ import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; -import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTabbedPane; +import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SpinnerDateModel; import javax.swing.text.DateFormatter; @@ -56,7 +56,7 @@ public abstract class LectureDetailsWindowLayout extends JDialog { // stuff ending in '...Info' are supposed to be the read-only labels for the information tab protected final QLabel lblTitleInfo; protected final JTextField txtTitle; - protected final JEditorPane txtDescription; + protected final JTextArea txtDescription; protected final QLabel lblImageNameInfo; protected final QLabel txtImageName; protected final JButton btnLinkImage; @@ -181,7 +181,9 @@ public abstract class LectureDetailsWindowLayout extends JDialog { grdGeneral.nextRow(); // description - txtDescription = new JEditorPane(); + txtDescription = new JTextArea(); + txtDescription.setLineWrap(true); + txtDescription.setWrapStyleWord(true); grdGeneral.add(new QLabel(I18n.WINDOW_LAYOUT.getString("LectureDetails.Label.description.text"))).anchor(GridBagConstraints.FIRST_LINE_START); JScrollPane jsp = new JScrollPane(txtDescription, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageMetaDataPageLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageMetaDataPageLayout.java index 8ba73589..63089274 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageMetaDataPageLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageMetaDataPageLayout.java @@ -22,7 +22,7 @@ public abstract class ImageMetaDataPageLayout extends WizardPage { protected final QLabel lblOperatingSystem; protected final JComboBox<OperatingSystem> cboOperatingSystem; - protected final JEditorPane txtDescription; + protected final JTextArea txtDescription; protected final JCheckBox chkLicenseRestricted; protected final JCheckBox chkIsTemplate; @@ -54,7 +54,9 @@ public abstract class ImageMetaDataPageLayout extends WizardPage { // description QLabel descriptionCaption = new QLabel( I18n.PAGE_LAYOUT.getString("ImageMetaData.Label.description.text")); - txtDescription = new JEditorPane(); + txtDescription = new JTextArea(3, 50); + txtDescription.setLineWrap(true); + txtDescription.setWrapStyleWord(true); txtDescription.setMinimumSize(Gui.getScaledDimension(0, 70)); JScrollPane descPane = new JScrollPane(txtDescription, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/LectureCreationPageLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/LectureCreationPageLayout.java index eee4f533..b7608f58 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/LectureCreationPageLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/LectureCreationPageLayout.java @@ -4,11 +4,12 @@ import java.util.Calendar; import javax.swing.JScrollPane; import javax.swing.JSpinner; +import javax.swing.JTextArea; import javax.swing.JTextField; -import javax.swing.JEditorPane; import javax.swing.SpinnerDateModel; import javax.swing.text.DateFormatter; + import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.control.QDatePickerImpl; import org.openslx.dozmod.gui.control.QLabel; @@ -17,7 +18,6 @@ import org.openslx.dozmod.gui.helper.I18n; import org.openslx.dozmod.gui.wizard.Wizard; import org.openslx.dozmod.gui.wizard.WizardPage; -import java.awt.Dimension; public abstract class LectureCreationPageLayout extends WizardPage { @@ -27,7 +27,7 @@ public abstract class LectureCreationPageLayout extends WizardPage { private static final long serialVersionUID = 422592252404059239L; protected final JTextField txtName; - protected final JEditorPane txtDescription; + protected final JTextArea txtDescription; protected final QDatePickerImpl dtpStartDate; protected final QDatePickerImpl dtpEndDate; protected final JSpinner spnStartTime; @@ -51,14 +51,14 @@ public abstract class LectureCreationPageLayout extends WizardPage { grid.nextRow(); // description - txtDescription = new JEditorPane(); - txtDescription.setPreferredSize(new Dimension(600,800)); - JScrollPane descPane = new JScrollPane(txtDescription, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - txtDescription.setMinimumSize(Gui.getScaledDimension(0, 60)); - descPane.setMinimumSize(txtDescription.getMinimumSize()); + txtDescription = new JTextArea(3, 50); + txtDescription.setLineWrap(true); + txtDescription.setWrapStyleWord(true); + txtDescription.setMinimumSize(Gui.getScaledDimension(0, 70)); grid.add(new QLabel(I18n.PAGE_LAYOUT.getString("LectureCreation.Label.description.text"))); - grid.add(descPane, 2).fill(true, false).expand(true, false); + JScrollPane descPane = new JScrollPane(txtDescription, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + grid.add(descPane, 2).fill(true, true).expand(true, true); grid.nextRow(); // Start date/time diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageUploadPage.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageUploadPage.java index efed6364..9ade4587 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageUploadPage.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageUploadPage.java @@ -279,13 +279,14 @@ public class ImageUploadPage extends ImageUploadPageLayout { vmDiskFileInfo = new File(vmBaseDirectory, hdds.get(0).diskImage); } - final DiskImage diskImage; final boolean diskImageIsSnapshot; final boolean diskImageIsStandalone; - try { - diskImage = DiskImage.newInstance(vmDiskFileInfo); + final ImageFormat diskFormat; + + try (DiskImage diskImage = DiskImage.newInstance(vmDiskFileInfo)) { diskImageIsSnapshot = diskImage.isSnapshot(); diskImageIsStandalone = diskImage.isStandalone(); + diskFormat = diskImage.getFormat(); } catch (FileNotFoundException e) { setErrorMessage(I18n.PAGE.getString("ImageUpload.WizardPage.errorMessage.diskImageNotFound", vmDiskFileInfo.getName())); @@ -308,7 +309,7 @@ public class ImageUploadPage extends ImageUploadPageLayout { // check if disk image format is supported by the hypervisor's supported disk image formats final List<ImageFormat> supportedImageFormats = state.virtualizationConfig.getVirtualizer() .getSupportedImageFormats(); - if (!diskImage.getFormat().isSupportedbyVirtualizer( supportedImageFormats )) { + if (!diskFormat.isSupportedbyVirtualizer( supportedImageFormats )) { Gui.showMessageBox(I18n.PAGE.getString("ImageUpload.Message.warning.diskImageNotSupportedByHypervisor", Branding.getServiceName()), MessageType.WARNING, null, null); setErrorMessage(I18n.PAGE.getString("ImageUpload.WizardPage.errorMessage.diskImageNotSupportedByHypervisor")); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java index 988284cf..f6dfc852 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java @@ -42,7 +42,6 @@ public class ImageWrapper { // after the whole image is downloaded and persisted as a .part file, // this will be executed to unpack it. - DiskImage diskImage = null; String ext = virtualizerId; boolean imageIsCompressed = false; @@ -62,41 +61,26 @@ public class ImageWrapper { } } else { - try { - diskImage = DiskImage.newInstance(tmpDiskFile); - } catch (IOException | DiskImageException e) { - LOGGER.warn("Could not open downloaded image for analyze step", e); - } - - if (diskImage != null) { + try (DiskImage diskImage = DiskImage.newInstance(tmpDiskFile)) { ext = diskImage.getFormat().getExtension(); + imageIsCompressed = diskImage.isCompressed(); + } catch (IOException | DiskImageException e) { + LOGGER.warn("Could not open/analyze downloaded image", e); + } - try { - imageIsCompressed = diskImage.isCompressed(); - } catch (DiskImageException e) { - LOGGER.warn("Could not analyze if image is compressed", e); - } - - if (imageIsCompressed) { - - Gui.asyncMessageBox( - I18n.THRIFT.getString("ThriftActions.Message.warning.diskImageCompressed", - imageName, Branding.getServiceFAQWebsite()), MessageType.WARNING, null, - null); - } + if (imageIsCompressed) { + Gui.asyncMessageBox(I18n.THRIFT.getString("ThriftActions.Message.warning.diskImageCompressed", + imageName, Branding.getServiceFAQWebsite()), MessageType.WARNING, null, null); } File destImage = new File(destDir.getAbsolutePath(), VmWrapper.generateFilename(imageName, ext)); - destImage.delete(); - if (!tmpDiskFile.renameTo(destImage)) { destImage = tmpDiskFile; // Must be Windows... } - try { + try (DiskImage diskImage = DiskImage.newInstance(destImage)) { VmWrapper.wrapVm(destImage, imageName, virtualizerConfig, virtualizerId, osId, diskImage); - - } catch (VirtualizationConfigurationException | IOException e) { + } catch (VirtualizationConfigurationException | IOException | DiskImageException e) { Gui.asyncMessageBox(I18n.THRIFT.getString("ThriftActions.Message.warning.couldNotWrapVM"), MessageType.WARNING, LOGGER, e); } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java index e2be7a92..1e25bbe0 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java @@ -86,7 +86,7 @@ public class ProxyConfigurator { return; } - // first setup the logger of proxy_vole + // first setup the logger of proxy-vole com.btr.proxy.util.Logger.setBackend(new LogBackEnd() { public void log(Class<?> clazz, LogLevel loglevel, String msg, Object... params) { diff --git a/dozentenmodul/src/main/properties/i18n/thrift.properties b/dozentenmodul/src/main/properties/i18n/thrift.properties index 9770aef0..0ddcffef 100644 --- a/dozentenmodul/src/main/properties/i18n/thrift.properties +++ b/dozentenmodul/src/main/properties/i18n/thrift.properties @@ -2,8 +2,8 @@ GuiErrorCallback.Message.error.notAuthenticatedOrInvalidToken=Invalid session token or failed \ authentication on {0}!\nPlease restart the program. Exit now? GuiErrorCallback.thriftError.String.errMsg=(Error {0}) -GuiErrorCallback.Message.error.transportException=The communication with {0} is interrupted. \ - Calling the function {1} is failed {2}.\n\n\ +GuiErrorCallback.Message.error.transportException=The communication with {0} was interrupted. \ + Calling the function {1} has failed {2}.\n\n\ Do you want to retry the call? # ImageLocalDetailsActions diff --git a/dozentenmodul/src/main/properties/i18n/window_de_DE.properties b/dozentenmodul/src/main/properties/i18n/window_de_DE.properties index 87aeae66..97c72ab8 100644 --- a/dozentenmodul/src/main/properties/i18n/window_de_DE.properties +++ b/dozentenmodul/src/main/properties/i18n/window_de_DE.properties @@ -60,7 +60,7 @@ ImageList.MenuItem.edit.text=Detailansicht ImageList.MenuItem.delete.text=Löschen ImageList.MenuItem.download.text=Download ImageList.Message.error.hasLatestVersion=Die gewählte VM besitzt keine gültige Image-Version -ImageList.Message.info.deleteImages=Folgende images konnten nicht gelöscht werden: {0} +ImageList.Message.info.deleteImages=Folgende Images konnten nicht gelöscht werden: {0} # ImagePublishedWindow ImagePublished.Message.error.satDownload=Konnte den Download nicht starten @@ -130,17 +130,17 @@ Login.Message.error.loginTypeDefault=Keine Authentifizierungsart ausgewählt! Login.Message.error.loginFailed=Anmeldung fehlgeschlagen # SatelliteListWindow -SatelliteList.Message.error.noSatellite=Kein Satellit ausgewählt +SatelliteList.Message.error.noSatellite=Kein Satellitenserver ausgewählt # VirtConfigEditorWindow -VirtConfigEditor.Message.error.invalidInputTitle=Invalide Eingaben:\n -VirtConfigEditor.Message.error.invalidInputText=Wollen Sie trotzdem speichern? (Die invaliden Zeilen werden \ +VirtConfigEditor.Message.error.invalidInputTitle=Ungültige Eingaben:\n +VirtConfigEditor.Message.error.invalidInputText=Wollen Sie trotzdem speichern? (Die ungültigen Zeilen werden \ dabei automatisch gelöscht.) -VirtConfigEditor.Message.yesNo.safeClose=Ihre Änderungen, in diesem Fenster, werden verloren gehen, \ - wollen Sie trotzdem abbrechen? +VirtConfigEditor.Message.yesNo.safeClose=Ihre Änderungen in diesem Fenster werden verloren gehen. \ + Wollen Sie trotzdem abbrechen? # VirtDropDownConfigEditorWindow VirtDropDownConfigEditor.Message.warning.initializeComboBoxes=Sie haben beim letzten Konfigurieren \n\ - einen falschen Eintrag eingespeichert. \nDie VM wird nicht starten! + einen falschen Eintrag gespeichert. \nDie VM wird nicht starten! VirtDropDownConfigEditor.Message.yesNo.safeClose=Wollen Sie wirklich abbrechen?\n\ Ihre Änderungen werden verworfen. diff --git a/dozentenmodulserver/pom.xml b/dozentenmodulserver/pom.xml index b09b3976..6c22666f 100644 --- a/dozentenmodulserver/pom.xml +++ b/dozentenmodulserver/pom.xml @@ -9,7 +9,7 @@ <packaging>jar</packaging> <name>DozMod-Server</name> - <url>http://maven.apache.org</url> + <url>https://git.openslx.org/openslx-ng/tutor-module.git</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/RuntimeConfig.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/RuntimeConfig.java index dbdf29cc..ea450717 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/RuntimeConfig.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/RuntimeConfig.java @@ -58,7 +58,7 @@ public class RuntimeConfig { satConfig.setMaxLocationsPerLecture(4); } if (satConfig.serverSideCopy == null) { - satConfig.serverSideCopy = SscMode.OFF; + satConfig.serverSideCopy = SscMode.AUTO; } // Update if we sanitized or added anything if (!satConfig.equals(readConfig)) { @@ -101,4 +101,8 @@ public class RuntimeConfig { return cache.get().allowLoginByDefault; } + public static boolean allowStudentDownload() { + return cache.get().allowStudentDownload; + } + } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java index 1d501c7a..edf02eb4 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java @@ -88,35 +88,23 @@ public class DbImage { public static ImageDetailsRead getImageDetails(UserInfo user, String imageBaseId) throws TNotFoundException, SQLException { try (MysqlConnection connection = Database.getConnection()) { - - // if Student is trying to download only needed information is filled MysqlStatement stmt = null; - if (user.role == Role.STUDENT) - { - stmt = connection.prepareStatement("SELECT i.imagebaseid, i.latestversionid," - + " null, null, null, null, null, null, null, null," - + " null, null," - + " null, null, null, null," - + " null, null, null, null" - + " FROM imagebase i" - + " LEFT JOIN imagepermission perm ON (i.imagebaseid = perm.imagebaseid AND perm.userid = :userid)" - + " WHERE i.imagebaseid = :imagebaseid"); + // Students should only be able to request a download of an image. Therefore not all information is needed for this task. + if (user == null || user.role == Role.STUDENT) { + stmt = connection.prepareStatement("SELECT i.imagebaseid, i.latestversionid, i.virtid" + + " FROM imagebase i" + + " LEFT JOIN imagepermission perm ON (i.imagebaseid = perm.imagebaseid AND perm.userid = :userid)" + + " WHERE i.imagebaseid = :imagebaseid"); } else { stmt = connection.prepareStatement("SELECT i.imagebaseid, i.latestversionid," - + " i.displayname, i.description, i.osid, i.virtid, i.createtime, i.updatetime, i.ownerid, i.updaterid," - + " i.sharemode, i.istemplate," - + " i.canlinkdefault, i.candownloaddefault, i.caneditdefault, i.canadmindefault," - + " perm.canlink, perm.candownload, perm.canedit, perm.canadmin" - + " FROM imagebase i" - + " LEFT JOIN imagepermission perm ON (i.imagebaseid = perm.imagebaseid AND perm.userid = :userid)" - + " WHERE i.imagebaseid = :imagebaseid"); + + " i.displayname, i.description, i.osid, i.virtid, i.createtime, i.updatetime, i.ownerid, i.updaterid," + + " i.sharemode, i.istemplate," + + " i.canlinkdefault, i.candownloaddefault, i.caneditdefault, i.canadmindefault," + + " perm.canlink, perm.candownload, perm.canedit, perm.canadmin" + + " FROM imagebase i" + + " LEFT JOIN imagepermission perm ON (i.imagebaseid = perm.imagebaseid AND perm.userid = :userid)" + + " WHERE i.imagebaseid = :imagebaseid"); } - - - - // if Student is trying to download only needed information is filled - - stmt.setString("userid", user == null ? "-" : user.userId); stmt.setString("imagebaseid", imageBaseId); ResultSet rs = stmt.executeQuery(); @@ -125,14 +113,26 @@ public class DbImage { // Exists: List<String> tags = DbSoftwareTag.getImageTags(connection, imageBaseId); List<ImageVersionDetails> versions = getImageVersions(connection, imageBaseId, user); - ImagePermissions defaultPermissions = DbImagePermissions.fromResultSetDefault(rs); - ImageDetailsRead image = new ImageDetailsRead(rs.getString("imagebaseid"), - rs.getString("latestversionid"), versions, rs.getString("displayname"), - rs.getString("description"), tags, rs.getInt("osid"), rs.getString("virtid"), - rs.getLong("createtime"), rs.getLong("updatetime"), rs.getString("ownerid"), - rs.getString("updaterid"), toShareMode(rs.getString("sharemode")), - rs.getByte("istemplate") != 0, defaultPermissions); - image.setUserPermissions(DbImagePermissions.fromResultSetUser(rs)); + + ImageDetailsRead image; + if (user == null || user.role == Role.STUDENT) { + // Students should only have download permissions. + // todo evaluate if this is needed and if there is a nicer way to create ImageDetailsRead object + ImagePermissions defaultPermissions = new ImagePermissions(false, true, false, false); + image = new ImageDetailsRead(rs.getString("imagebaseid"), rs.getString("latestversionid"), + versions, "DownloadedImage", null, tags, 0, rs.getString("virtid"), 0, 0, null, null, + null, false, defaultPermissions); + image.setUserPermissions(defaultPermissions); + } else { + ImagePermissions defaultPermissions = DbImagePermissions.fromResultSetDefault(rs); + image = new ImageDetailsRead(rs.getString("imagebaseid"), rs.getString("latestversionid"), + versions, rs.getString("displayname"), rs.getString("description"), tags, + rs.getInt("osid"), rs.getString("virtid"), rs.getLong("createtime"), + rs.getLong("updatetime"), rs.getString("ownerid"), rs.getString("updaterid"), + toShareMode(rs.getString("sharemode")), rs.getByte("istemplate") != 0, + defaultPermissions); + image.setUserPermissions(DbImagePermissions.fromResultSetUser(rs)); + } User.setCombinedUserPermissions(image, user); return image; } catch (SQLException e) { @@ -273,27 +273,34 @@ public class DbImage { throws SQLException { List<ImageVersionDetails> versionList = new ArrayList<>(); MysqlStatement stmt = null; - if (user.role == Role.STUDENT) { + if (user == null || user.role == Role.STUDENT) { stmt = connection.prepareStatement("SELECT" - + " imageversionid, createtime, expiretime, filesize, null," - + " isrestricted, isvalid, isprocessed" + " FROM imageversion" - + " WHERE imagebaseid = :imagebaseid"); + + " imageversionid, createtime, expiretime, filesize," + + " isrestricted, isvalid, isprocessed" + + " FROM imageversion" + + " WHERE imagebaseid = :imagebaseid AND isrestricted = 0"); } else { stmt = connection.prepareStatement("SELECT" - + " imageversionid, createtime, expiretime, filesize, uploaderid," - + " isrestricted, isvalid, isprocessed" + " FROM imageversion" - + " WHERE imagebaseid = :imagebaseid"); - + + " imageversionid, createtime, expiretime, filesize, uploaderid," + + " isrestricted, isvalid, isprocessed" + + " FROM imageversion" + + " WHERE imagebaseid = :imagebaseid"); } stmt.setString("imagebaseid", imageBaseId); ResultSet rs = stmt.executeQuery(); + while (rs.next()) { String imageVersionId = rs.getString("imageversionid"); + String uploaderID = ""; + // Only student doesn't know the uploaderid + if (user != null && user.role != Role.STUDENT) { + uploaderID = rs.getString("uploaderid"); + } versionList.add(new ImageVersionDetails(imageVersionId, rs.getLong("createtime"), - rs.getLong("expiretime"), rs.getLong("filesize"), rs.getString("uploaderid"), + rs.getLong("expiretime"), rs.getLong("filesize"), uploaderID, rs.getByte("isrestricted") != 0, rs.getByte("isvalid") != 0, - rs.getByte("isprocessed") != 0, DbSoftwareTag.getImageVersionSoftwareList(connection, - imageVersionId))); + rs.getByte("isprocessed") != 0, + DbSoftwareTag.getImageVersionSoftwareList(connection, imageVersionId))); } stmt.close(); return versionList; @@ -383,7 +390,8 @@ public class DbImage { + " canlinkdefault = :canlink," + " candownloaddefault = :candownload, caneditdefault = :canedit," + (user != null ? " updaterid = :updaterid, updatetime = UNIX_TIMESTAMP()," : "") - + " canadmindefault = :canadmin" + " WHERE imagebaseid = :baseid"); + + " canadmindefault = :canadmin" + + " WHERE imagebaseid = :baseid"); stmt.setString("baseid", imageBaseId); stmt.setString("imagename", image.imageName); stmt.setString("description", image.description); @@ -492,7 +500,8 @@ public class DbImage { throw new TNotFoundException(); // First update version table MysqlStatement stmtVersion = connection.prepareStatement("UPDATE imageversion v SET" - + " v.isrestricted = :isrestricted" + " WHERE v.imageversionid = :versionid"); + + " v.isrestricted = :isrestricted" + + " WHERE v.imageversionid = :versionid"); stmtVersion.setString("versionid", imageVersionId); stmtVersion.setBoolean("isrestricted", image.isRestricted); if (stmtVersion.executeUpdate() != 0) { @@ -528,11 +537,13 @@ public class DbImage { try (MysqlConnection connection = Database.getConnection()) { { // Disable version in question - MysqlStatement checkStmt = connection.prepareStatement("SELECT imageversionid FROM" - + " imageversion WHERE imageversionid = :versionid AND" + MysqlStatement checkStmt = connection.prepareStatement("SELECT imageversionid" + + " FROM imageversion" + + " WHERE imageversionid = :versionid AND" + " (expiretime > UNIX_TIMESTAMP() OR isvalid <> 0)"); - MysqlStatement disableStmt = connection.prepareStatement("UPDATE imageversion SET" - + " expiretime = 1234567890, isvalid = 0" + " WHERE imageversionid = :versionid"); + MysqlStatement disableStmt = connection.prepareStatement("UPDATE imageversion" + + " SET expiretime = 1234567890, isvalid = 0" + + " WHERE imageversionid = :versionid"); affectedList = new ArrayList<>(imageVersionIds.length); for (String imageVersionId : imageVersionIds) { if (imageVersionId == null) @@ -832,7 +843,8 @@ public class DbImage { // Determine manually if anything changed, as executeQuery() always returns 1 for some reason boolean latestVersionChanged = true; do { - MysqlStatement ds = connection.prepareStatement("SELECT latestversionid FROM imagebase WHERE imagebaseid = :imagebaseid"); + MysqlStatement ds = connection.prepareStatement( + "SELECT latestversionid FROM imagebase WHERE imagebaseid = :imagebaseid"); ds.setString("imagebaseid", imageBaseId); ResultSet drs = ds.executeQuery(); if (drs.next()) { diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/IncomingDataTransfer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/IncomingDataTransfer.java index 3c663bd0..e5a9cd09 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/IncomingDataTransfer.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/IncomingDataTransfer.java @@ -4,6 +4,9 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.sql.SQLException; import java.util.List; import java.util.concurrent.ExecutorService; @@ -81,6 +84,11 @@ public class IncomingDataTransfer extends IncomingTransferBase { * connection */ private String errorMessage = null; + + /** + * Timestamp when this transfer was created + */ + private final long initTimestamp = System.currentTimeMillis(); public IncomingDataTransfer(String uploadId, UserInfo owner, ImageDetailsRead image, File destinationFile, long fileSize, List<byte[]> sha1Sums, byte[] machineDescription, @@ -210,8 +218,10 @@ public class IncomingDataTransfer extends IncomingTransferBase { */ @Override protected synchronized boolean finishIncomingTransfer() { - if (getState() != TransferState.FINISHED) + if (getState() != TransferState.FINISHED) { + LOGGER.warn("finishIncomingTransfer called in bad state " + getState()); return false; + } potentialFinishTime.set(System.currentTimeMillis()); // If owner is not set, this was a repair-transfer, which downloads directly to the existing target file. // Nothing more to do in that case. @@ -229,16 +239,16 @@ public class IncomingDataTransfer extends IncomingTransferBase { LOGGER.info("Finalizing uploaded image " + image.imageName); // Ready to go. First step: Rename temp file to something usable String ext = "img"; - try { - ext = DiskImage.newInstance(getTmpFileName()).getFormat().getExtension(); + try (DiskImage inst = DiskImage.newInstance(getTmpFileName())) { + ext = inst.getFormat().getExtension(); } catch (IOException | DiskImageException e1) { } - File destination = new File(getTmpFileName().getParent(), Formatter.vmName(owner, image.imageName, - ext)); + File destination = new File(getTmpFileName().getParent(), Formatter.vmName(initTimestamp, owner, image.imageName, + ext)).getAbsoluteFile(); // Sanity check: destination should be a sub directory of the vmStorePath String relPath = FileSystem.getRelativePath(destination, Configuration.getVmStoreBasePath()); if (relPath == null) { - LOGGER.warn(destination.getAbsolutePath() + " is not a subdir of " + LOGGER.error(destination.getAbsolutePath() + " is not a subdir of " + Configuration.getVmStoreBasePath().getAbsolutePath()); cancel(); return false; @@ -248,22 +258,32 @@ public class IncomingDataTransfer extends IncomingTransferBase { } // Execute rename - boolean ret = false; - Exception renameException = null; try { - ret = getTmpFileName().renameTo(destination); - } catch (Exception e) { - ret = false; - renameException = e; + Path d = Files.move(getTmpFileName().toPath(), destination.toPath(), StandardCopyOption.ATOMIC_MOVE); + if (d != null && d.toFile().exists()) { + destination = d.toFile(); + } + } catch (IOException e1) { + LOGGER.warn("Cannot rename", e1); + } + if (!destination.exists()) { + try { + getTmpFileName().renameTo(destination); + } catch (Exception e) { + LOGGER.warn("Cannot rename", e); + } } - if (!ret) { + if (!destination.exists()) { // Rename failed :-( - LOGGER.warn( - "Could not rename '" + getTmpFileName().getAbsolutePath() + "' to '" - + destination.getAbsolutePath() + "'", renameException); + LOGGER.warn("Could not rename '" + getTmpFileName().getAbsolutePath() + "' to '" + + destination.getAbsolutePath()); cancel(); return false; } + + if (destination.length() != getFileSize()) { + LOGGER.warn("Destination file size mismatch. Is: " + destination.length() + ", should be: " + getFileSize()); + } // Now insert meta data into DB try { @@ -278,6 +298,7 @@ public class IncomingDataTransfer extends IncomingTransferBase { } catch (SQLException e) { LOGGER.error("Error finishing upload: Inserting version to DB failed", e); // Also delete uploaded file, as there is no reference to it + LOGGER.info("Deleting file " + destination, e); FileSystem.deleteAsync(destination); cancel(); return false; @@ -314,6 +335,7 @@ public class IncomingDataTransfer extends IncomingTransferBase { public synchronized void cancel() { if (!isRepairUpload() && getTmpFileName().exists()) { super.cancel(); + LOGGER.debug("Deleting file " + getTmpFileName(), new RuntimeException()); FileSystem.deleteAsync(getTmpFileName()); } } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java index abea5433..43cdebe0 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java @@ -2,6 +2,7 @@ package org.openslx.bwlp.sat.permissions; import java.sql.SQLException; +import org.openslx.bwlp.sat.RuntimeConfig; import org.openslx.bwlp.sat.database.mappers.DbImage; import org.openslx.bwlp.sat.database.mappers.DbLecture; import org.openslx.bwlp.sat.database.mappers.DbOrganization; @@ -58,6 +59,9 @@ public class User { * @return null if user is allowed, {@link AuthorizationError} otherwise */ public static AuthorizationError canLogin(UserInfo user) { + // Student download allowed? If not, reject students right away + if (!RuntimeConfig.allowStudentDownload() && user.role == Role.STUDENT) + return AuthorizationError.ACCOUNT_SUSPENDED; LocalUser localData = LocalData.getLocalUser(user); if (localData != null) { if (localData.canLogin) diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Formatter.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Formatter.java index f13df0eb..268ceda1 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Formatter.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Formatter.java @@ -28,13 +28,14 @@ public class Formatter { /** * Generate a file name for the given VM based on owner and display name. * + * @param ts Timestamp of upload * @param user The user associated with the VM, e.g. the owner * @param imageName Name of the VM * @param ext * @return File name for the VM derived from the function's input */ - public static String vmName(UserInfo user, String imageName, String ext) { - return cleanFileName(vmNameDateFormat.print(System.currentTimeMillis()) + "_" + user.lastName + "_" + public static String vmName(long ts, UserInfo user, String imageName, String ext) { + return cleanFileName(vmNameDateFormat.print(ts) + "_" + user.lastName + "_" + imageName + "." + ext).toLowerCase(); } @@ -9,30 +9,11 @@ <packaging>pom</packaging> <name>bwSuite</name> - <url>http://git.openslx.org/tutor-module.git/</url> + <url>https://git.openslx.org/openslx-ng/tutor-module.git</url> <modules> <module>dozentenmodul</module> <module>dozentenmodulserver</module> </modules> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.1</version> - <configuration> - <source>1.7</source> - <target>1.7</target> - </configuration> - </plugin> - </plugins> - </build> - - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - </properties> - </project> |