summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Bauer2017-09-06 13:48:33 +0200
committerJonathan Bauer2017-09-06 13:48:33 +0200
commite310fa0738149f20b9de6b173d3d175857b0c748 (patch)
tree5857811d25cc53c51590cc0158ec84e049a3ed88
parent[client] Update apache httpclient, pass custom client to ecp-client-lean (diff)
downloadtutor-module-e310fa0738149f20b9de6b173d3d175857b0c748.tar.gz
tutor-module-e310fa0738149f20b9de6b173d3d175857b0c748.tar.xz
tutor-module-e310fa0738149f20b9de6b173d3d175857b0c748.zip
[client/server] network share feature [WIP]
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java330
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/NetshareTable.java47
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java53
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java17
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/thrift/Sorters.java16
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/util/FormatHelper.java22
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/SupportedFeatures.java1
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java8
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbNetshare.java61
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java44
10 files changed, 584 insertions, 15 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java
new file mode 100644
index 00000000..ac10e2bb
--- /dev/null
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java
@@ -0,0 +1,330 @@
+package org.openslx.dozmod.gui.control;
+
+import java.awt.BorderLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EventListener;
+import java.util.EventObject;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+
+import org.apache.log4j.Logger;
+import org.openslx.bwlp.thrift.iface.NetShare;
+import org.openslx.bwlp.thrift.iface.NetShareAuth;
+import org.openslx.dozmod.gui.control.ComboBox.ComboBoxRenderer;
+import org.openslx.dozmod.gui.control.table.NetshareTable;
+import org.openslx.dozmod.gui.control.table.QScrollPane;
+import org.openslx.dozmod.gui.helper.GridManager;
+import org.openslx.dozmod.util.FormatHelper;
+
+/**
+ * Widget for netrules configuration of lectures
+ */
+public class NetshareConfigurator extends NetshareConfiguratorLayout {
+
+ private static final long serialVersionUID = -3336605759245603655L;
+ private final static Logger LOGGER = Logger.getLogger(NetshareConfigurator.class);
+
+ private List<NetShare> tblNetshareData = null;
+
+ public NetshareConfigurator() {
+ super();
+ tblNetshare.getModel().addTableModelListener(new TableModelListener() {
+ @Override
+ public void tableChanged(TableModelEvent e) {
+ fireNetshareConfigurationChangeEvent(new NetshareConfigurationChangeEvent(NetshareConfigurator.this));
+ }
+ });
+
+ // combobox for share authentication types
+ cboNetshareAuth.setModel(new DefaultComboBoxModel<NetShareAuth>(NetShareAuth.values()));
+ cboNetshareAuth.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ NetShareAuth selectedAuth = cboNetshareAuth.getItemAt(cboNetshareAuth.getSelectedIndex());
+ boolean activate = selectedAuth == NetShareAuth.SPECIAL_USER;
+ // username field is needed to either special or guest user
+ tfUsername.setEnabled(activate || selectedAuth == NetShareAuth.GUEST_USER);
+ lblUsername.setEnabled(activate || selectedAuth == NetShareAuth.GUEST_USER);
+ tfPassword.setEnabled(activate);
+ lblPassword.setEnabled(activate);
+ chkShowPass.setEnabled(activate);
+ }
+ });
+
+ tfUsername.setEnabled(false);
+ lblUsername.setEnabled(false);
+ tfPassword.setEnabled(false);
+ lblPassword.setEnabled(false);
+ chkShowPass.setEnabled(false);
+ btnAdd.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // check if we are editing an existing share entry or
+ // creating a new one, check for input either way
+ NetShare input = new NetShare();
+ NetShareAuth inputNetShareAuth = cboNetshareAuth.getItemAt(cboNetshareAuth.getSelectedIndex());
+ if (inputNetShareAuth == null) {
+ LOGGER.error("Could not get the network share auth type from the combobox!");
+ return;
+ }
+ input.auth = inputNetShareAuth;
+ input.path = tfSharePath.getText();
+ if (input.path == null || input.path.isEmpty()) {
+ LOGGER.error("Missing/empty network share URI!");
+ return;
+ }
+ switch (inputNetShareAuth) {
+ case GUEST_USER:
+ // guest mode requires guest account but not password
+ input.username = tfUsername.getText();
+ break;
+ case LOGIN_USER:
+ break;
+ case SPECIAL_USER:
+ // save given username/password
+ input.username = tfUsername.getText();
+ char[] inputPassword = tfPassword.getPassword();
+ input.password = new String(inputPassword);
+ Arrays.fill(inputPassword, '0');
+ break;
+ default:
+ input = null;
+ break;
+ }
+ if (input == null) {
+ LOGGER.debug("Input bad, aborting.");
+ return;
+ }
+
+ // now decide whether to create a new entry or update existing one
+ if (tblNetshare.getSelectedItem() != null) {
+ // editing existing one, delete it from the internal data
+ if (!tblNetshareData.remove(tblNetshare.getSelectedItem())) {
+ LOGGER.debug("Failed to remove selected share for replacement!");
+ return;
+ }
+ }
+ // either we delete the existing share from the data or we are
+ // creating a new one, either way add it to the list and update
+ // the table, if its not present already
+ if (tblNetshareData.contains(input)) {
+ LOGGER.error("Network share already in the list, aborting.");
+ return;
+ }
+ tblNetshareData.add(input);
+ tblNetshare.getModel().setData(tblNetshareData);
+ }
+ }
+ );
+
+ btnDel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // try to delete the selected share
+ NetShare selection = tblNetshare.getSelectedItem();
+ if (selection == null) {
+ return;
+ }
+ try {
+ if (!tblNetshareData.remove(selection)) {
+ // false if it was not found
+ LOGGER.error("Could not remove non-existant network share '" + selection.toString()
+ + "' from the table data: " + tblNetshareData.toString());
+ return;
+ }
+ // refresh table data
+ tblNetshare.getModel().setData(tblNetshareData);
+ } catch (Exception ex) {
+ LOGGER.debug("Failed to remove " + selection.toString() + " from the table data.", ex);
+ return;
+ }
+ }
+ });
+
+ chkShowPass.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getStateChange() != ItemEvent.SELECTED) {
+ tfPassword.setEchoChar('*');
+ } else {
+ tfPassword.setEchoChar((char) 0);
+ }
+ }
+ });
+
+ tblNetshare.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ NetShare item = tblNetshare.getSelectedItem();
+ // ugly block-wise sets, but only one test needed compared to
+ // doing lots of item != null ? ... : ...
+ if (item != null) {
+ // share from the list is selected: fill bottom form and change "Add" to "Apply"
+ btnDel.setEnabled(true);
+ tfSharePath.setText(item.path);
+ tfUsername.setText(item.username);
+ tfPassword.setText(item.password);
+ cboNetshareAuth.setSelectedItem(item.auth);
+ btnAdd.setText("Ändern");
+ } else {
+ btnDel.setEnabled(false);
+ tfSharePath.setText(null);
+ tfUsername.setText(null);
+ tfPassword.setText(null);
+ cboNetshareAuth.setSelectedItem(null);
+ btnAdd.setText("Hinzufügen");
+ }
+ }
+ });
+ }
+
+ public List<NetShare> getState() {
+ return tblNetshareData;
+ }
+
+ public boolean setState(List<NetShare> data) {
+ if (data == null)
+ return false;
+ if (tblNetshareData == null) {
+ tblNetshareData = new ArrayList<>();
+ }
+ tblNetshareData = data;
+ tblNetshare.getModel().setData(tblNetshareData);
+ return true;
+ }
+
+ protected EventListenerList listenerList = new EventListenerList();
+
+ public class NetshareConfigurationChangeEvent extends EventObject {
+
+ private static final long serialVersionUID = -511509960878320591L;
+
+ public NetshareConfigurationChangeEvent(Object source) {
+ super(source);
+ }
+ }
+
+ public interface NetshareConfigurationChangeEventListener extends EventListener {
+ public void stateChanged(NetshareConfigurationChangeEvent event);
+ }
+
+ public void addNetshareConfigurationChangeEventListener(NetshareConfigurationChangeEventListener listener) {
+ listenerList.add(NetshareConfigurationChangeEventListener.class, listener);
+ }
+
+ public void removeNetshareConfigurationChangeEventListener(NetshareConfigurationChangeEventListener listener) {
+ listenerList.remove(NetshareConfigurationChangeEventListener.class, listener);
+ }
+
+ void fireNetshareConfigurationChangeEvent(NetshareConfigurationChangeEvent evt) {
+ Object[] listeners = listenerList.getListenerList();
+ for (int i = 0; i < listeners.length; i++) {
+ if (listeners[i] == NetshareConfigurationChangeEventListener.class) {
+ ((NetshareConfigurationChangeEventListener) listeners[i + 1]).stateChanged(evt);
+ }
+ }
+ }
+}
+
+/**
+ * Internal layout class for this widget
+ */
+class NetshareConfiguratorLayout extends JPanel {
+
+ private static final long serialVersionUID = 6479525981542743622L;
+
+ private final static String txtNetshareDesc = "Hier können Sie Netzlaufwerke angeben,"
+ + " die automatisch beim Start der Veranstaltung eingebunden werden sollen.";
+ protected QLabel lblShareAuth, lblSharePath, lblUsername, lblPassword;
+
+ protected NetshareTable tblNetshare = new NetshareTable();
+ protected JTextField tfSharePath, tfUsername;
+ protected JPasswordField tfPassword;
+ protected JButton btnAdd, btnDel;
+ protected JCheckBox chkShowPass;
+ protected ComboBox<NetShareAuth> cboNetshareAuth = new ComboBox<>(new ComboBoxRenderer<NetShareAuth>() {
+ @Override
+ public String renderItem(NetShareAuth item) {
+ if (item == null)
+ return null;
+ return FormatHelper.netShareAuthName(item);
+ }
+ });
+
+
+
+ public NetshareConfiguratorLayout() {
+ GridManager grid = new GridManager(this, 5, true, new Insets(3, 3, 3, 3));
+ // top info panel
+ grid.add(new WordWrapLabel(txtNetshareDesc), 5).fill(true, false).expand(true, false);
+ grid.nextRow();
+ // middle netshare list
+ grid.add(new QScrollPane(tblNetshare), 5).fill(true, true).expand(true, true);
+ grid.nextRow();
+ JPanel pnlButtonDelete = new JPanel();
+ pnlButtonDelete.setLayout(new BoxLayout(pnlButtonDelete, BoxLayout.LINE_AXIS));
+ btnDel = new JButton("Entfernen");
+ pnlButtonDelete.add(Box.createGlue());
+ pnlButtonDelete.add(btnDel, BorderLayout.LINE_END);
+ grid.add(pnlButtonDelete, 5).fill(true, false).expand(true, false);
+ grid.nextRow();
+ JPanel pnlNewShare = new JPanel();
+ GridManager gridNewShare = new GridManager(pnlNewShare, 5, true);
+ pnlNewShare.setBorder(BorderFactory.createTitledBorder("Neues Netzlaufwerk"));
+ // bottom form to add a new share
+ lblShareAuth = new QLabel("Authentifizierung");
+ gridNewShare.add(lblShareAuth);
+ gridNewShare.add(cboNetshareAuth, 4).fill(true, false).expand(true, false); // User (optional)
+ gridNewShare.nextRow();
+ lblSharePath = new QLabel("URI");
+ gridNewShare.add(lblSharePath);
+ tfSharePath = new JTextField();
+ gridNewShare.add(tfSharePath, 4).fill(true, false).expand(true, false); // User (optional)
+ gridNewShare.nextRow();
+ lblUsername = new QLabel("Username");
+ gridNewShare.add(lblUsername);
+ tfUsername = new JTextField();
+ gridNewShare.add(tfUsername, 1).fill(true, false).expand(true, false); // Password (optional)
+ lblPassword = new QLabel("Passwort:");
+ gridNewShare.add(lblPassword);
+ tfPassword = new JPasswordField();
+ gridNewShare.add(tfPassword, 2).fill(true, false).expand(true, false); // Password (optional)
+ gridNewShare.nextRow();
+ chkShowPass = new JCheckBox("Passwort anzeigen");
+ JPanel pnlHidePass = new JPanel();
+ pnlHidePass.setLayout(new BoxLayout(pnlHidePass, BoxLayout.LINE_AXIS));
+ pnlHidePass.add(Box.createGlue());
+ pnlHidePass.add(chkShowPass, BorderLayout.LINE_END);
+ gridNewShare.add(pnlHidePass, 5).fill(true, false).expand(true, false);
+ gridNewShare.nextRow();
+ grid.add(pnlNewShare, 5).fill(true, false).expand(true, false);
+ grid.nextRow();
+ // bottom panels for right-aligned button...
+ JPanel pnlButtonAdd = new JPanel();
+ pnlButtonAdd.setLayout(new BoxLayout(pnlButtonAdd, BoxLayout.LINE_AXIS));
+ btnAdd = new JButton("Hinzufügen");
+ pnlButtonAdd.add(Box.createGlue());
+ pnlButtonAdd.add(btnAdd, BorderLayout.LINE_END);
+ grid.add(pnlButtonAdd, 5).fill(true, false).expand(true, false);
+ grid.finish(false);
+ }
+}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/NetshareTable.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/NetshareTable.java
new file mode 100644
index 00000000..7ebde4eb
--- /dev/null
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/NetshareTable.java
@@ -0,0 +1,47 @@
+package org.openslx.dozmod.gui.control.table;
+
+import org.openslx.bwlp.thrift.iface.NetShare;
+import org.openslx.dozmod.thrift.Sorters;
+import org.openslx.dozmod.util.FormatHelper;
+
+@SuppressWarnings("serial")
+public class NetshareTable extends ListTable<NetShare> {
+
+ public static final ListTableColumn COL_PATH = new ListTableColumn("Pfad");
+ public static final ListTableColumn COL_TYPE = new ListTableColumn("Typ", Sorters.netShareAuth);
+ public static final ListTableColumn COL_USER = new ListTableColumn("Username");
+ public static final ListTableColumn COL_PASSWORD = new ListTableColumn("Passwort");
+
+ public NetshareTable() {
+ super(COL_PATH, COL_TYPE, COL_USER, COL_PASSWORD);
+ }
+
+ @Override
+ protected Object getValueAtInternal(NetShare item, ListTableColumn columnIndex) {
+ if (columnIndex == COL_PATH)
+ return item.path;
+ if (columnIndex == COL_TYPE)
+ return FormatHelper.netShareAuthName(item.auth);
+ if (columnIndex == COL_USER)
+ return item.username;
+ if (columnIndex == COL_PASSWORD)
+ return item.password;
+ //TODO others!
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ public Object modelValueToDisplayFormat(Object object, ListTableColumn column) {
+ if (column == COL_PATH)
+ return (String) object;
+ if (column == COL_TYPE)
+ return object.toString();
+ if (column == COL_USER)
+ return (String) object;
+ if (column == COL_PASSWORD) {
+ String pass = (String) object;
+ return pass != null ? pass.replaceAll(".", "*") : "";
+ }
+ throw new IndexOutOfBoundsException();
+ }
+}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java
index 2918428f..be65ad04 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java
@@ -37,6 +37,7 @@ import org.openslx.bwlp.thrift.iface.LecturePermissions;
import org.openslx.bwlp.thrift.iface.LectureRead;
import org.openslx.bwlp.thrift.iface.LectureWrite;
import org.openslx.bwlp.thrift.iface.NetRule;
+import org.openslx.bwlp.thrift.iface.NetShare;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.MainWindow;
@@ -44,6 +45,8 @@ import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEvent;
import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEventListener;
import org.openslx.dozmod.gui.control.LectureCustomPermissionManager.UserChangeEvent;
import org.openslx.dozmod.gui.control.LectureCustomPermissionManager.UserChangeEventListener;
+import org.openslx.dozmod.gui.control.NetshareConfigurator.NetshareConfigurationChangeEvent;
+import org.openslx.dozmod.gui.control.NetshareConfigurator.NetshareConfigurationChangeEventListener;
import org.openslx.dozmod.gui.control.RunscriptConfigurator.RunscriptConfigurationChangeEvent;
import org.openslx.dozmod.gui.control.RunscriptConfigurator.RunscriptConfigurationChangeEventListener;
import org.openslx.dozmod.gui.helper.DateTimeHelper;
@@ -140,6 +143,8 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
private List<NetRule> originalNetrules = null;
private String currentRunscript = null;
private String originalRunscript = null;
+ private List<NetShare> currentNetshares = null;
+ private List<NetShare> originalNetshares = null;
/**
* Constructor
@@ -287,6 +292,12 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
}
});
+ ctlNetshareConfigurator.addNetshareConfigurationChangeEventListener(new NetshareConfigurationChangeEventListener() {
+ @Override
+ public void stateChanged(NetshareConfigurationChangeEvent event) {
+ reactToChange();
+ }
+ });
// Comboboxes
final ItemListener comboItemListener = new ItemListener() {
@Override
@@ -381,12 +392,16 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
txtImageName.setText(image.getImageName());
lblImageNameInfo.setText(image.getImageName());
}
+
// remember original netrules and runscript
originalNetrules = lecture.networkExceptions != null ? lecture.networkExceptions : new ArrayList<NetRule>();
originalRunscript = lecture.runscript != null ? lecture.runscript : new String("");
+ originalNetshares = lecture.networkShares != null ? new ArrayList<NetShare>(lecture.networkShares) : new ArrayList<NetShare>();
currentNetrules = originalNetrules;
currentRunscript = originalRunscript;
+ currentNetshares = originalNetshares;
+
// remember default permissions
if (lecture.defaultPermissions != null) {
@@ -415,7 +430,8 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
// init advanced info
ctlRunscriptConfigurator.setState(lecture.runscript);
-
+ ctlNetshareConfigurator.setState(lecture.networkShares);
+
txtTitle.setText(lecture.getLectureName());
lblTitleInfo.setText(lecture.getLectureName());
txtDescription.setText(lecture.getDescription());
@@ -602,17 +618,29 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
Date start = DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime);
Date end = DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime);
if (!isPeriodValid(start, end, false) && dateHasChanged()) {
+ pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Allgemein"));
lblError.setText("Ungültiger Zeitraum!");
return false;
}
// runscript stuff
String newState = ctlRunscriptConfigurator.getState();
if (newState == null) {
- // marker for error, switch to tab
+ // script extension was missing from the user input.
+ // feedback happens in the configurator, just switch to the tab.
+ pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Startskript"));
return false;
} else {
currentRunscript = newState;
}
+
+ // netshare stuff
+ List<NetShare> newNetshareList = ctlNetshareConfigurator.getState();
+ if (newNetshareList == null) {
+ // the network share list was never queried if this returns null
+ return false;
+ } else {
+ currentNetshares = newNetshareList;
+ }
// done with mandatory checks, remove error message
lblError.setText(null);
@@ -632,8 +660,8 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
|| (locationInfo != null && lecture.limitToLocations != locationInfo.limitToLocations)
|| (currentNetrules != null && !currentNetrules.equals(originalNetrules))
|| (currentRunscript != null && !currentRunscript.equals(originalRunscript))
+ || (currentNetshares != null && !currentNetshares.equals(originalNetshares))
|| imageLinkChanged;
-
return changed;
}
@@ -661,16 +689,10 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
lecture.imageVersionId = chkAutoUpdate.isSelected() ? image.latestVersionId
: cboVersions.getItemAt(cboVersions.getSelectedIndex()).versionId;
}
- // goto to advanced tab and check (by getting) the state of the textAreas
- currentRunscript = ctlRunscriptConfigurator.getState();
- if (currentRunscript == null) {
- // getState() will return null only if it couldn't parse the rules
- // which means that the user got informed about what was invalid
- // So we just return here until the parsing works.
- pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Startskript"));
- return false;
- }
- metadataChanged |= (currentNetrules != lecture.networkExceptions || currentRunscript != lecture.runscript);
+
+ metadataChanged |= (currentNetrules != lecture.networkExceptions
+ || currentRunscript != lecture.runscript
+ || currentNetshares != lecture.networkShares);
// now check if we need to push a new LectureWrite
if (metadataChanged) {
// first build the LectureWrite from the GUI fields
@@ -683,6 +705,8 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
// TODO: coming "false" is Location related
false, chkHasUsbAccess.isSelected());
metadata.setNetworkExceptions(currentNetrules);
+ metadata.setNetworkShares(currentNetshares);
+
// now trigger the actual action
try {
ThriftManager.getSatClient().updateLecture(Session.getSatelliteToken(),
@@ -770,6 +794,9 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements
if (pnlTabs.indexOfTab("Startskript") != -1) {
pnlTabs.setEnabledAt(pnlTabs.indexOfTab("Startskript"), editable);
}
+ if (pnlTabs.indexOfTab("Netwerk-Shares") != -1) {
+ pnlTabs.setEnabledAt(pnlTabs.indexOfTab("Netzwerk-Shares"), true);
+ }
btnChangeOwner.setEnabled(LecturePerms.canAdmin(lecture));
btnDownloadImage.setEnabled(ImagePerms.canDownload(image));
}
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 fbf04ad1..56c00db1 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
@@ -35,6 +35,7 @@ import org.openslx.dozmod.gui.control.ComboBox;
import org.openslx.dozmod.gui.control.ComboBox.ComboBoxRenderer;
import org.openslx.dozmod.gui.control.LectureCustomPermissionManager;
import org.openslx.dozmod.gui.control.LocationSelector;
+import org.openslx.dozmod.gui.control.NetshareConfigurator;
import org.openslx.dozmod.gui.control.PersonLabel;
import org.openslx.dozmod.gui.control.QDatePickerImpl;
import org.openslx.dozmod.gui.control.QLabel;
@@ -45,6 +46,7 @@ import org.openslx.dozmod.thrift.Session;
import org.openslx.dozmod.thrift.cache.MetaDataCache;
import org.openslx.dozmod.util.DateLabelFormatter;
import org.openslx.dozmod.util.FormatHelper;
+import org.openslx.sat.thrift.version.Feature;
import org.openslx.thrifthelper.Comparators;
@SuppressWarnings("serial")
@@ -94,6 +96,7 @@ public abstract class LectureDetailsWindowLayout extends JDialog {
protected final LectureCustomPermissionManager ctlPermissionManager;
protected final LocationSelector ctlLocationSelector;
protected final RunscriptConfigurator ctlRunscriptConfigurator;
+ protected final NetshareConfigurator ctlNetshareConfigurator;
private static final Properties pickerStrings = new Properties();
@@ -105,6 +108,7 @@ public abstract class LectureDetailsWindowLayout extends JDialog {
protected JPanel pnlTabPermissions;
protected JPanel pnlTabLocations;
protected JPanel pnlTabRunscript;
+ private JPanel pnlTabNetshare;
static {
pickerStrings.put("text.today", "Heute");
@@ -367,6 +371,16 @@ public abstract class LectureDetailsWindowLayout extends JDialog {
grdAdvanced.add(ctlRunscriptConfigurator).fill(true, true).expand(true, true);
grdAdvanced.finish(false);
+ /* *******************************************************************************
+ *
+ * Tab "Network-Shares"
+ *
+ ********************************************************************************/
+ ctlNetshareConfigurator = new NetshareConfigurator();
+ pnlTabNetshare = new JPanel();
+ GridManager grdNetshare = new GridManager(pnlTabNetshare, 1, false);
+ grdNetshare.add(ctlNetshareConfigurator).fill(true, true).expand(true, true);
+ grdNetshare.finish(false);
/* *******************************************************************************
*
* Main panel containing the tabs
@@ -386,6 +400,9 @@ public abstract class LectureDetailsWindowLayout extends JDialog {
pnlTabs.addTab("Startskript", pnlTabRunscript);
}
pnlTabs.addTab("Berechtigungen", pnlTabPermissions);
+ if (Session.hasFeature(Feature.NETWORK_SHARES)) {
+ pnlTabs.addTab("Netzwerk-Shares", pnlTabNetshare);
+ }
add(pnlTabs, BorderLayout.CENTER);
// usage counter + button panel on the bottom
JPanel buttonPanel = new JPanel();
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/Sorters.java b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/Sorters.java
index 291bf381..e1a6d877 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/Sorters.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/Sorters.java
@@ -3,6 +3,7 @@ package org.openslx.dozmod.thrift;
import java.util.Comparator;
import org.openslx.bwlp.thrift.iface.Location;
+import org.openslx.bwlp.thrift.iface.NetShareAuth;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Organization;
import org.openslx.bwlp.thrift.iface.UserInfo;
@@ -83,4 +84,19 @@ public class Sorters {
}
};
+ public static final Comparator<NetShareAuth> netShareAuth = new Comparator<NetShareAuth>() {
+ @Override
+ public int compare(NetShareAuth o1, NetShareAuth o2) {
+ // just need a sorter, doesn't really matter how to sort them
+ if (o1 == null) {
+ if (o2 == null)
+ return 0;
+ return -1;
+ } else if (o2 == null) {
+ return 1;
+ }
+ return o1.compareTo(o2);
+ }
+ };
+
}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/FormatHelper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/FormatHelper.java
index 6f129931..11ad277a 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/FormatHelper.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/FormatHelper.java
@@ -3,6 +3,7 @@ package org.openslx.dozmod.util;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.openslx.bwlp.thrift.iface.Location;
+import org.openslx.bwlp.thrift.iface.NetShareAuth;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Organization;
import org.openslx.bwlp.thrift.iface.UserInfo;
@@ -165,4 +166,25 @@ public class FormatHelper {
return "Unknown";
return org.getDisplayName();
}
+
+ /**
+ * Format the given network share authentication type.
+ *
+ * @param NetShareAuth a {@link NetShareAuth} instance
+ * @return Display name for that authentication type, string "unknown" otherwise
+ */
+ public static String netShareAuthName(NetShareAuth auth) {
+ if (auth == null)
+ return "Unknown";
+ switch (auth) {
+ case LOGIN_USER:
+ return "Angemeldeter Nutzer";
+ case GUEST_USER:
+ return "Gast Nutzer";
+ case SPECIAL_USER:
+ return "Spezifischer Nutzer";
+ default:
+ return auth.toString();
+ }
+ }
}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/SupportedFeatures.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/SupportedFeatures.java
index 73d1a788..203f3de1 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/SupportedFeatures.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/SupportedFeatures.java
@@ -8,6 +8,7 @@ public class SupportedFeatures {
static {
registerFeature(Feature.EXTEND_EXPIRED_VM);
+ registerFeature(Feature.NETWORK_SHARES);
}
public static String getFeatureString() {
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java
index ff160917..58c7bdb2 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java
@@ -24,6 +24,7 @@ import org.openslx.bwlp.thrift.iface.LectureRead;
import org.openslx.bwlp.thrift.iface.LectureSummary;
import org.openslx.bwlp.thrift.iface.LectureWrite;
import org.openslx.bwlp.thrift.iface.NetRule;
+import org.openslx.bwlp.thrift.iface.NetShare;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.util.Json;
@@ -39,6 +40,7 @@ public class DbLecture {
static {
Json.registerThriftClass(NetRule.class);
+ Json.registerThriftClass(NetShare.class);
}
private static void setWriteFields(MysqlStatement stmt, String lectureId, LectureWrite lecture,
@@ -117,6 +119,7 @@ public class DbLecture {
stmt.setString("ownerid", user.userId);
stmt.executeUpdate();
writeLocations(connection, lectureId, lecture.locationIds);
+ DbNetshare.writeNetworkShares(connection, lectureId, lecture.networkShares);
connection.commit();
return lectureId;
} catch (SQLException e) {
@@ -138,6 +141,7 @@ public class DbLecture {
+ " WHERE lectureid = :lectureid");
setWriteFields(stmt, lectureId, lecture, user);
writeLocations(connection, lectureId, lecture.locationIds);
+ DbNetshare.writeNetworkShares(connection, lectureId, lecture.networkShares);
stmt.executeUpdate();
}
@@ -274,10 +278,11 @@ public class DbLecture {
+ " l.autoupdate, l.isenabled, l.starttime, l.endtime, l.lastused, l.usecount, l.createtime,"
+ " l.updatetime, l.ownerid, l.updaterid, l.runscript, l.nics, l.netrules, l.isexam,"
+ " l.isprivate, l.islocationprivate, l.hasinternetaccess, l.hasusbaccess,"
- + " l.caneditdefault, l.canadmindefault, p.canedit, p.canadmin"
+ + " l.caneditdefault, l.canadmindefault, p.canedit, p.canadmin, n.sharedata"
+ " FROM lecture l "
+ " LEFT JOIN imageversion i USING (imageversionid)"
+ " LEFT JOIN lecturepermission p ON (l.lectureid = p.lectureid AND p.userid = :userid)"
+ + " LEFT JOIN networkshare n ON (l.lectureid = n.lectureid)"
+ " WHERE l.lectureid = :lectureid LIMIT 1");
stmt.setString("userid", user == null ? "" : user.userId);
stmt.setString("lectureid", lectureId);
@@ -323,6 +328,7 @@ public class DbLecture {
lecture.setUserPermissions(DbLecturePermissions.fromResultSetUser(rs));
User.setCombinedUserPermissions(lecture, user);
lecture.setLocationIds(DbLocation.getLectureLocations(connection, lectureId));
+ lecture.setNetworkShares(DbNetshare.getLectureNetshares(connection, lectureId));
return lecture;
} catch (SQLException e) {
LOGGER.error("Query failed in DbLecture.getLectureDetails()", e);
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbNetshare.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbNetshare.java
new file mode 100644
index 00000000..af8b3fdc
--- /dev/null
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbNetshare.java
@@ -0,0 +1,61 @@
+package org.openslx.bwlp.sat.database.mappers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.openslx.bwlp.sat.database.Database;
+import org.openslx.bwlp.sat.database.MysqlConnection;
+import org.openslx.bwlp.sat.database.MysqlStatement;
+import org.openslx.bwlp.thrift.iface.NetShare;
+import org.openslx.util.Json;
+
+public class DbNetshare {
+
+ private static final Logger LOGGER = Logger.getLogger(DbNetshare.class);
+
+ public static void writeNetworkShares(MysqlConnection connection, String lectureId, List<NetShare> shares)
+ throws SQLException {
+ if (shares == null || shares.isEmpty() || lectureId == null || lectureId.isEmpty()) {
+ return;
+ }
+ MysqlStatement delStmt = connection.prepareStatement("DELETE FROM networkshare WHERE lectureid = :lectureid");
+ delStmt.setString("lectureid", lectureId);
+ delStmt.executeUpdate();
+
+ MysqlStatement addStmt = connection
+ .prepareStatement("INSERT IGNORE INTO networkshare (shareid, lectureid, shareuid, sharedata)"
+ + " VALUES (DEFAULT, :lectureid, NULL, :sharedata)");
+ addStmt.setString("lectureid", lectureId);
+ for (NetShare share : shares) {
+ String netshareJson = Json.serialize(share);
+ addStmt.setString("sharedata", netshareJson);
+ addStmt.executeUpdate();
+ }
+ }
+
+ public static List<NetShare> getLectureNetshares(String lectureId) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ return getLectureNetshares(connection, lectureId);
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbLecture.getLectureDetails()", e);
+ throw e;
+ }
+ }
+
+ public static List<NetShare> getLectureNetshares(MysqlConnection connection, String lectureId) throws SQLException {
+ List<NetShare> list = new ArrayList<>();
+ MysqlStatement netsharestmt = connection
+ .prepareStatement("SELECT sharedata FROM networkshare WHERE lectureid = :lectureid");
+ netsharestmt.setString("lectureid", lectureId);
+ ResultSet rs = netsharestmt.executeQuery();
+ while (rs.next()) {
+ // TODO get the shares saved on slx-admin, if any shareuid aren't null
+ list.add(Json.deserializeThrift(rs.getString("sharedata"), NetShare.class));
+ }
+ return list;
+ }
+
+}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java
index e369f162..111578d3 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java
@@ -3,14 +3,18 @@ package org.openslx.bwlp.sat.web;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.SQLException;
+import java.util.List;
import java.util.Map;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.log4j.Logger;
import org.openslx.bwlp.sat.database.mappers.DbLecture;
+import org.openslx.bwlp.sat.database.mappers.DbNetshare;
import org.openslx.bwlp.sat.fileserv.FileServer;
import org.openslx.bwlp.thrift.iface.LectureRead;
import org.openslx.bwlp.thrift.iface.NetRule;
+import org.openslx.bwlp.thrift.iface.NetShare;
+import org.openslx.bwlp.thrift.iface.NetShareAuth;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.util.Json;
import org.openslx.util.vm.VmMetaData;
@@ -94,6 +98,8 @@ public class WebServer extends NanoHTTPD {
return serveLectureStart(parts[2]);
if (parts[3].equals("netrules"))
return serveLectureNetRules(parts[2]);
+ if (parts[3].equals("netshares"))
+ return serveLectureNetshares(parts[2]);
if (parts[3].equals("runscript"))
return serveLectureScript(parts[2]);
}
@@ -188,6 +194,43 @@ public class WebServer extends NanoHTTPD {
lecture.runscript);
}
+ private Response serveLectureNetshares(String lectureId) {
+ List<NetShare> list = null;
+ try {
+ list = DbNetshare.getLectureNetshares(lectureId);
+ // TODO handling not found necessary?
+ } catch (SQLException e) {
+ return internalServerError();
+ }
+ // TODO format expected from the client-side to
+ // handle different types of login. Currently:
+ // * no username nor password => use credentials of logged in user
+ // * username set, no password => guest mode
+ // * username and password set => user-specificed credentials
+ StringBuilder sb = new StringBuilder();
+ if (!list.isEmpty()) {
+ for (NetShare share : list) {
+ sb.append(share.path);
+ if (share.auth == NetShareAuth.LOGIN_USER) {
+ // nothing to do
+ }
+ if (share.auth == NetShareAuth.GUEST_USER) {
+ sb.append(' ');
+ sb.append(share.username);
+ }
+ if (share.auth == NetShareAuth.SPECIAL_USER) {
+ sb.append(' ');
+ sb.append(share.username);
+ sb.append(' ');
+ sb.append(share.password); // TODO fixme
+ }
+ sb.append("\n");
+ }
+ }
+ return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/plain; charset=utf-8",
+ sb.toString());
+ }
+
/**
* Return full list of lectures matching given location(s).
*
@@ -229,5 +272,4 @@ public class WebServer extends NanoHTTPD {
}
return new NanoHTTPD.Response(NanoHTTPD.Response.Status.BAD_REQUEST, "text/plain", message);
}
-
}