summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2015-06-23 19:10:48 +0200
committerSimon Rettberg2015-06-23 19:10:48 +0200
commit8ad025dd99468f71d2fa5c49e0bcf359b055ec97 (patch)
tree6208ff7d598116e36b21882e5a018a99d2506103
parentfix bwLehrpool logo not beeing read from the resources (diff)
downloadtutor-module-8ad025dd99468f71d2fa5c49e0bcf359b055ec97.tar.gz
tutor-module-8ad025dd99468f71d2fa5c49e0bcf359b055ec97.tar.xz
tutor-module-8ad025dd99468f71d2fa5c49e0bcf359b055ec97.zip
[server] More methods implemented
-rw-r--r--dozentenmodulserver/setup/sat-01-schema.sql9
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlStatement.java18
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java102
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOrganization.java79
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbUser.java52
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalOrganization.java11
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalUser.java15
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java111
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java78
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java66
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Util.java18
11 files changed, 511 insertions, 48 deletions
diff --git a/dozentenmodulserver/setup/sat-01-schema.sql b/dozentenmodulserver/setup/sat-01-schema.sql
index 3dbf5317..e6de9010 100644
--- a/dozentenmodulserver/setup/sat-01-schema.sql
+++ b/dozentenmodulserver/setup/sat-01-schema.sql
@@ -51,9 +51,9 @@ CREATE TABLE IF NOT EXISTS `imagebase` (
`currentversionid` char(36) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL COMMENT 'Reference to current version of this image. This is redundant as it can be determined from the imageversion table, but the query to get all images with their current version would be very slow then, which is not what we want, as it is fired quite often.',
`latestversionid` char(36) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL,
`displayname` varchar(100) NOT NULL,
- `description` text NOT NULL,
- `osid` int(11) NOT NULL,
- `virtid` varchar(10) NOT NULL,
+ `description` TEXT NULL DEFAULT NULL,
+ `osid` INT NULL DEFAULT NULL,
+ `virtid` VARCHAR(10) NULL DEFAULT NULL,
`createtime` bigint(20) NOT NULL,
`updatetime` bigint(20) NOT NULL,
`ownerid` char(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
@@ -227,7 +227,8 @@ CREATE TABLE IF NOT EXISTS `organization` (
`organizationid` char(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`displayname` varchar(255) NOT NULL,
`canlogin` tinyint(1) NOT NULL DEFAULT '0',
- PRIMARY KEY (`organizationid`)
+ PRIMARY KEY (`organizationid`),
+ KEY `loginkey` (`canlogin`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `os_x_virt` (
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlStatement.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlStatement.java
index 3d5f9065..620ee2e4 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlStatement.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlStatement.java
@@ -113,7 +113,7 @@ public class MysqlStatement implements Closeable {
* @param value parameter value
* @throws SQLException if an error occurred
* @throws IllegalArgumentException if the parameter does not exist
- * @see PreparedStatement#setInt(int, int)
+ * @see PreparedStatement#setLong(int, long)
*/
public void setLong(String name, long value) throws SQLException {
List<Integer> indexes = getIndexes(name);
@@ -123,6 +123,22 @@ public class MysqlStatement implements Closeable {
}
/**
+ * Sets a parameter.
+ *
+ * @param name parameter name
+ * @param value parameter value
+ * @throws SQLException if an error occurred
+ * @throws IllegalArgumentException if the parameter does not exist
+ * @see PreparedStatement#setBoolean(int, boolean)
+ */
+ public void setBoolean(String name, boolean value) throws SQLException {
+ List<Integer> indexes = getIndexes(name);
+ for (Integer index : indexes) {
+ statement.setBoolean(index, value);
+ }
+ }
+
+ /**
* Executes the statement.
*
* @return true if the first result is a {@link ResultSet}
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 51daed49..4dae8039 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
@@ -4,15 +4,18 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
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.ImageBaseWrite;
import org.openslx.bwlp.thrift.iface.ImageDetailsRead;
import org.openslx.bwlp.thrift.iface.ImagePermissions;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
import org.openslx.bwlp.thrift.iface.ImageVersionDetails;
+import org.openslx.bwlp.thrift.iface.ImageVersionWrite;
import org.openslx.bwlp.thrift.iface.ShareMode;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.bwlp.thrift.iface.UserInfo;
@@ -169,6 +172,86 @@ public class DbImage {
}
/**
+ * Create new row in the imagebase table.
+ *
+ * @param user the user the image will belong to
+ * @param imageName name of the image to be created
+ * @return UUID of the newly created image
+ * @throws SQLException
+ */
+ public static String createImage(UserInfo user, String imageName) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("INSERT INTO imagebase"
+ + " (imagebaseid, displayname, createtime, updatetime, ownerid, updaterid, sharemode,"
+ + " istemplate, canlinkdefault, candownloaddefault, caneditdefault, canadmindefault)"
+ + " VALUES"
+ + " (:baseid, :name, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), :userid, :userid, 'LOCAL',"
+ + " 0, 0, 0, 0, 0)");
+ String imageUuid = UUID.randomUUID().toString();
+ stmt.setString("baseid", imageUuid);
+ stmt.setString("name", imageName);
+ stmt.setString("userid", user.userId);
+ stmt.executeUpdate();
+ connection.commit();
+ return imageUuid;
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbImage.createImage()", e);
+ throw e;
+ }
+ }
+
+ public static void updateImageMetadata(UserInfo user, String imageBaseId, ImageBaseWrite image)
+ throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ /*
+ 1: string imageName,
+ 2: string description,
+ 3: i32 osId,
+ 4: bool isTemplate,
+ 5: ImagePermissions defaultPermissions,
+ 6: ShareMode shareMode,
+ 7: optional UUID ownerId,
+ */
+ MysqlStatement stmt = connection.prepareStatement("UPDATE imagebase"
+ + " SET displayname = :imagename, description = :description,"
+ + " osid = :osid, virtid = :virtid, istemplate = :istemplate, canlinkdefault = :canlink,"
+ + " candownloaddefault = :candownload, caneditdefault = :canedit,"
+ + " updaterid = :updaterid, updatetime = UNIX_TIMESTAMP(),"
+ + " canadmindefault = :canadmin" + " WHERE imagebaseid = :baseid");
+ stmt.setString("baseid", imageBaseId);
+ stmt.setString("imagename", image.imageName);
+ stmt.setString("description", image.description);
+ stmt.setInt("osid", image.osId);
+ stmt.setString("virtid", image.virtId);
+ stmt.setBoolean("istemplate", image.isTemplate);
+ stmt.setBoolean("canlink", image.defaultPermissions.link);
+ stmt.setBoolean("candownload", image.defaultPermissions.download);
+ stmt.setBoolean("canedit", image.defaultPermissions.edit);
+ stmt.setBoolean("canadmin", image.defaultPermissions.admin);
+ stmt.setString("updaterid", user.userId);
+ stmt.executeUpdate();
+ connection.commit();
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbImage.updateImageMetadata()", e);
+ throw e;
+ }
+ }
+
+ public static void setImageOwner(String imageBaseId, String newOwnerId) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("UPDATE imagebase"
+ + " SET ownerid = :ownerid WHERE imagebaseid = :baseid");
+ stmt.setString("ownerid", newOwnerId);
+ stmt.setString("baseid", imageBaseId);
+ stmt.executeQuery();
+ connection.commit();
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbImage.setImageOwner()", e);
+ throw e;
+ }
+ }
+
+ /**
* Get the UUID of the image base belonging to the given image version UUID.
* Returns <code>null</code> if the UUID does not exist.
*
@@ -208,4 +291,23 @@ public class DbImage {
return ShareMode.valueOf(string);
}
+ public static void updateImageVersion(UserInfo user, String imageVersionId, ImageVersionWrite image)
+ throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("UPDATE imageversion v, imagebase b SET"
+ + " v.isenabled = :isenabled, v.isrestricted = :isrestricted,"
+ + " b.updaterid = :userid, b.updatetime = UNIX_TIMESTAMP()"
+ + " WHERE v.imageversionid = :versionid AND v.imagebaseid = b.imagebaseid");
+ stmt.setString("versionid", imageVersionId);
+ stmt.setString("userid", user.userId);
+ stmt.setBoolean("isenabled", image.isEnabled);
+ stmt.setBoolean("isrestricted", image.isRestricted);
+ stmt.executeQuery();
+ connection.commit();
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbImage.updateImageVersion()", e);
+ throw e;
+ }
+ }
+
}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOrganization.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOrganization.java
index cc401af9..8c0cf79a 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOrganization.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOrganization.java
@@ -1,18 +1,29 @@
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.sat.database.models.LocalOrganization;
import org.openslx.bwlp.thrift.iface.Organization;
public class DbOrganization {
private static final Logger LOGGER = Logger.getLogger(DbOrganization.class);
+ /**
+ * Store the given list of organizations (coming from the master server) to
+ * the database, or update the meta data of the organizations, if already
+ * existent.
+ *
+ * @param organizations
+ * @return
+ */
public static boolean storeOrganizations(List<Organization> organizations) {
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("INSERT INTO organization"
@@ -31,4 +42,72 @@ public class DbOrganization {
}
}
+ /**
+ * Get local-only data for the given organization. Local-only data is not
+ * supplied by the master server and might differ between satellites.
+ *
+ * @param organizationId
+ * @return
+ * @throws SQLException
+ */
+ public static LocalOrganization getLocalData(String organizationId) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("SELECT canlogin FROM organization"
+ + " WHERE organizationid = :organizationid");
+ stmt.setString("organizationid", organizationId);
+ ResultSet rs = stmt.executeQuery();
+ if (!rs.next())
+ return null;
+ return new LocalOrganization(rs.getBoolean("canlogin"));
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbOrganization.getLocalData()", e);
+ throw e;
+ }
+ }
+
+ /**
+ * Get list of organizations where users are allowed to login to the local
+ * satellite.
+ *
+ * @return
+ * @throws SQLException
+ */
+ public static List<Organization> getLoginAllowedOrganizations() throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("SELECT organizationid, displayname"
+ + " FROM organization WHERE canlogin = 1");
+ ResultSet rs = stmt.executeQuery();
+ List<Organization> list = new ArrayList<>();
+ while (rs.next()) {
+ list.add(new Organization(rs.getString("organizationid"), rs.getString("displayname"), null,
+ null));
+ }
+ return list;
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbOrganization.getLoginAllowedOrganizations()", e);
+ throw e;
+ }
+ }
+
+ /**
+ * Change the "canlogin" flag of the given organization.
+ *
+ * @param organizationId
+ * @param canlogin
+ * @throws SQLException
+ */
+ public static void setCanLogin(String organizationId, boolean canlogin) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("UPDATE organization"
+ + " SET canlogin = :canlogin WHERE organizationid = :organizationid");
+ stmt.setString("organizationid", organizationId);
+ stmt.setBoolean("canlogin", canlogin);
+ stmt.executeUpdate();
+ connection.commit();
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbOrganization.setCanLogin()", e);
+ throw e;
+ }
+ }
+
}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbUser.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbUser.java
index 6106fab5..d7cabe47 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbUser.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbUser.java
@@ -9,6 +9,7 @@ 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.sat.database.models.LocalUser;
import org.openslx.bwlp.thrift.iface.UserInfo;
public class DbUser {
@@ -46,4 +47,55 @@ public class DbUser {
}
}
+ /**
+ * Get local-only information for given user.
+ *
+ * @param user {@link UserInfo} instance representing the user
+ * @return {@link LocalUser} instance matching the given user, or null if
+ * not found
+ * @throws SQLException
+ */
+ public static LocalUser getLocalData(UserInfo user) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("SELECT lastlogin, canlogin, issuperuser"
+ + " FROM user WHERE userid = :userid LIMIT 1");
+ stmt.setString("userid", user.userId);
+ ResultSet rs = stmt.executeQuery();
+ if (!rs.next())
+ return null;
+ return new LocalUser(rs.getLong("lastlogin"), rs.getBoolean("canlogin"),
+ rs.getBoolean("issuperuser"));
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbUser.getLocalData()", e);
+ throw e;
+ }
+ }
+
+ /**
+ * Insert given user into db (if not already existent), otherwise just
+ * update the "lastlogin" field.
+ *
+ * @param ui {@link UserInfo}
+ * @throws SQLException
+ */
+ public static void writeUserOnLogin(UserInfo ui) throws SQLException {
+ try (MysqlConnection connection = Database.getConnection()) {
+ MysqlStatement stmt = connection.prepareStatement("INSERT INTO user"
+ + " (userid, firstname, lastname, email, organizationid, lastlogin, canlogin, issuperuser)"
+ + " VALUES"
+ + " (:userid, :firstname, :lastname, :email, :organizationid, UNIX_TIMESTAMP(), 1, 0)"
+ + " ON DUPLICATE KEY UPDATE lastlogin = UNIX_TIMESTAMP()");
+ stmt.setString("userid", ui.userId);
+ stmt.setString("firstname", ui.firstName);
+ stmt.setString("lastname", ui.lastName);
+ stmt.setString("email", ui.eMail);
+ stmt.setString("organizationid", ui.organizationId);
+ stmt.executeUpdate();
+ connection.commit();
+ } catch (SQLException e) {
+ LOGGER.error("Query failed in DbUser.writeUserOnLogin()", e);
+ throw e;
+ }
+ }
+
}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalOrganization.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalOrganization.java
new file mode 100644
index 00000000..36165fad
--- /dev/null
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalOrganization.java
@@ -0,0 +1,11 @@
+package org.openslx.bwlp.sat.database.models;
+
+public class LocalOrganization {
+
+ public final boolean canLogin;
+
+ public LocalOrganization(boolean canLogin) {
+ this.canLogin = canLogin;
+ }
+
+}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalUser.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalUser.java
new file mode 100644
index 00000000..e0040a96
--- /dev/null
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalUser.java
@@ -0,0 +1,15 @@
+package org.openslx.bwlp.sat.database.models;
+
+public class LocalUser {
+
+ public final long lastLogin;
+ public final boolean canLogin;
+ public final boolean isSuperUser;
+
+ public LocalUser(long lastLogin, boolean canLogin, boolean isSuperUser) {
+ this.lastLogin = lastLogin;
+ this.canLogin = canLogin;
+ this.isSuperUser = isSuperUser;
+ }
+
+}
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 51041df9..fc3241a9 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
@@ -1,8 +1,13 @@
package org.openslx.bwlp.sat.permissions;
import java.sql.SQLException;
+import java.util.Map;
import org.openslx.bwlp.sat.database.mappers.DbImage;
+import org.openslx.bwlp.sat.database.mappers.DbOrganization;
+import org.openslx.bwlp.sat.database.mappers.DbUser;
+import org.openslx.bwlp.sat.database.models.LocalOrganization;
+import org.openslx.bwlp.sat.database.models.LocalUser;
import org.openslx.bwlp.thrift.iface.AuthorizationError;
import org.openslx.bwlp.thrift.iface.ImagePermissions;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
@@ -11,17 +16,18 @@ import org.openslx.bwlp.thrift.iface.TAuthorizationException;
import org.openslx.bwlp.thrift.iface.TInternalServerError;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.bwlp.thrift.iface.UserInfo;
+import org.openslx.util.TimeoutHashMap;
public class User {
- public enum Permission {
+ public static enum Permission {
LINK,
DOWNLOAD,
EDIT,
ADMIN
}
- private static boolean canActionImage(UserInfo ui, Permission checkPerm,
+ private static boolean canActionImage(UserInfo user, Permission checkPerm,
ImagePermissions... imagePermissions) {
for (ImagePermissions perm : imagePermissions) {
if (perm == null)
@@ -35,14 +41,99 @@ public class User {
if (checkPerm == Permission.ADMIN)
return perm.admin;
}
- return isSuperUser(ui);
+ return false;
+ }
+
+ /**
+ * Cache local user data, might be called quite often.
+ */
+ private static final Map<String, LocalUser> localUserCache = new TimeoutHashMap<>(60000);
+
+ private static LocalUser getLocalUser(UserInfo user) {
+ synchronized (localUserCache) {
+ LocalUser local = localUserCache.get(user.userId);
+ if (local != null)
+ return local;
+ }
+ LocalUser localData;
+ try {
+ localData = DbUser.getLocalData(user);
+ } catch (SQLException e) {
+ return null;
+ }
+ if (localData == null)
+ return null;
+ synchronized (localUserCache) {
+ localUserCache.put(user.userId, localData);
+ }
+ return localData;
}
- public static boolean isSuperUser(UserInfo ui) {
- // TODO: for superuser override, read from DB
+ /**
+ * Cache local organization data, might be called quite often.
+ */
+ private static final Map<String, LocalOrganization> localOrganizationCache = new TimeoutHashMap<>(60000);
+
+ private static LocalOrganization getLocalOrganization(String organizationId) {
+ synchronized (localOrganizationCache) {
+ LocalOrganization local = localOrganizationCache.get(organizationId);
+ if (local != null)
+ return local;
+ }
+ LocalOrganization localData;
+ try {
+ localData = DbOrganization.getLocalData(organizationId);
+ } catch (SQLException e) {
+ return null;
+ }
+ if (localData == null)
+ return null;
+ synchronized (localOrganizationCache) {
+ localOrganizationCache.put(organizationId, localData);
+ }
+ return localData;
+ }
+
+ /**
+ * Check if given user is a local super user.
+ *
+ * @param user
+ * @return
+ */
+ public static boolean isSuperUser(UserInfo user) {
+ LocalUser localData = getLocalUser(user);
+ return localData != null && localData.isSuperUser;
+ }
+
+ /**
+ * Check if given user is allowed to login to this satellite.
+ *
+ * @param user user to check login permission for
+ * @return true if user is allowed to login to this satellite
+ */
+ public static boolean canLogin(UserInfo user) {
+ LocalUser localData = getLocalUser(user);
+ if (localData != null)
+ return localData.canLogin; // User locally known, use user-specific permission
+ LocalOrganization local = getLocalOrganization(user.organizationId);
+ // User unknown, check per-organization login permission
+ if (local == null)
+ return false;
+ if (local.canLogin)
+ return true;
+ // Special case: If user is not allowed to login, check if there are no allowed
+ // organizations yet. If so, automatically allow the organization of this user.
+ try {
+ if (DbOrganization.getLoginAllowedOrganizations().isEmpty()) {
+ DbOrganization.setCanLogin(user.organizationId, true);
+ return true;
+ }
+ } catch (SQLException e) {
+ // Ignore
+ }
return false;
}
-
+
/**
* Check if the given user has the given permission for the image identified
* by the given image base id.
@@ -55,15 +146,21 @@ public class User {
*/
public static boolean hasImageBasePermission(UserInfo user, String imageBaseId, Permission permission)
throws TInternalServerError, TNotFoundException {
+ // Students can download only, so return false right away if we're not checking for download
+ if (user.role == Role.STUDENT && permission != Permission.DOWNLOAD)
+ return false;
+ // Check general permissions
ImageSummaryRead localImage;
try {
localImage = DbImage.getImageSummary(user, imageBaseId);
} catch (SQLException e) {
throw new TInternalServerError();
}
+ // Owner has all permissions
if (localImage.ownerId.equals(user.userId))
return true;
- return canActionImage(user, permission, localImage.userPermissions, localImage.defaultPermissions);
+ return canActionImage(user, permission, localImage.userPermissions, localImage.defaultPermissions)
+ || isSuperUser(user);
}
/**
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java
index 7e743e14..d4440793 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
+import org.apache.thrift.TException;
import org.openslx.bwlp.sat.database.mappers.DbImage;
import org.openslx.bwlp.sat.database.mappers.DbImagePermissions;
import org.openslx.bwlp.sat.database.mappers.DbUser;
@@ -16,7 +17,9 @@ import org.openslx.bwlp.sat.permissions.User.Permission;
import org.openslx.bwlp.sat.thrift.cache.OperatingSystemList;
import org.openslx.bwlp.sat.thrift.cache.OrganizationList;
import org.openslx.bwlp.sat.thrift.cache.VirtualizerList;
+import org.openslx.bwlp.sat.util.Util;
import org.openslx.bwlp.thrift.iface.ImageBaseWrite;
+import org.openslx.bwlp.thrift.iface.ImageDataError;
import org.openslx.bwlp.thrift.iface.ImageDetailsRead;
import org.openslx.bwlp.thrift.iface.ImagePermissions;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
@@ -29,6 +32,7 @@ import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Organization;
import org.openslx.bwlp.thrift.iface.SatelliteServer;
import org.openslx.bwlp.thrift.iface.TAuthorizationException;
+import org.openslx.bwlp.thrift.iface.TImageDataException;
import org.openslx.bwlp.thrift.iface.TInternalServerError;
import org.openslx.bwlp.thrift.iface.TInvalidTokenException;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
@@ -148,48 +152,62 @@ public class ServerHandler implements SatelliteServer.Iface {
}
@Override
- public boolean createImage(String userToken, String imageName) throws TAuthorizationException {
+ public String createImage(String userToken, String imageName) throws TAuthorizationException,
+ TImageDataException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canCreateImageOrFail(user);
- // TODO: Create image
- return true;
+ if (!Util.isPrintable(imageName) || Util.isEmptyString(imageName))
+ throw new TImageDataException(ImageDataError.INVALID_DATA, "Invalid or empty name");
+ try {
+ return DbImage.createImage(user, imageName);
+ } catch (SQLException e) {
+ throw new TInternalServerError();
+ }
}
@Override
- public boolean updateImageBase(String userToken, String imageBaseId, ImageBaseWrite image)
- throws TAuthorizationException, TInternalServerError, TNotFoundException {
+ public void updateImageBase(String userToken, String imageBaseId, ImageBaseWrite image)
+ throws TAuthorizationException, TInternalServerError, TNotFoundException, TImageDataException {
UserInfo user = SessionManager.getOrFail(userToken);
User.hasImageBasePermissionOrFail(user, imageBaseId, Permission.EDIT);
- // TODO: Permissions cleared; Now update image base data
- return false;
+ if (!Util.isPrintable(image.imageName) || Util.isEmptyString(image.imageName))
+ throw new TImageDataException(ImageDataError.INVALID_DATA, "Invalid or empty name");
+ // TODO: Should other fields be validated? Most fields should be protected by fk constraints,
+ // but the user would only get a generic error, with no hint at the actual problem.
+ try {
+ DbImage.updateImageMetadata(user, imageBaseId, image);
+ } catch (SQLException e) {
+ throw new TInternalServerError();
+ }
}
@Override
- public boolean updateImageVersion(String userToken, String imageVersionId, ImageVersionWrite image)
+ public void updateImageVersion(String userToken, String imageVersionId, ImageVersionWrite image)
throws TAuthorizationException, TInternalServerError, TNotFoundException {
UserInfo user = SessionManager.getOrFail(userToken);
User.hasImageVersionPermissionOrFail(user, imageVersionId, Permission.EDIT);
- // TODO: Permissions cleared; Now update image version data
- return false;
+ try {
+ DbImage.updateImageVersion(user, imageVersionId, image);
+ } catch (SQLException e) {
+ throw new TInternalServerError();
+ }
}
@Override
- public boolean deleteImageVersion(String userToken, String imageVersionId)
- throws TAuthorizationException, TNotFoundException, TInternalServerError {
+ public void deleteImageVersion(String userToken, String imageVersionId) throws TAuthorizationException,
+ TNotFoundException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.hasImageVersionPermissionOrFail(user, imageVersionId, Permission.ADMIN);
// TODO: Permissions cleared; Now mark image for deletion (set expire time in the past...)
- return false;
}
@Override
- public boolean writeImagePermissions(String userToken, String imageBaseId,
+ public void writeImagePermissions(String userToken, String imageBaseId,
Map<String, ImagePermissions> permissions) throws TAuthorizationException, TNotFoundException,
TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.hasImageBasePermissionOrFail(user, imageBaseId, Permission.ADMIN);
- // TODO: Permissions cleared; Now update image base data
- return false;
+ // TODO: Permissions cleared; Now write image permissions
}
@Override
@@ -205,16 +223,27 @@ public class ServerHandler implements SatelliteServer.Iface {
}
@Override
+ public void setImageOwner(String userToken, String imageBaseId, String newOwnerId)
+ throws TAuthorizationException, TNotFoundException, TInternalServerError, TException {
+ UserInfo user = SessionManager.getOrFail(userToken);
+ User.hasImageBasePermissionOrFail(user, imageBaseId, Permission.ADMIN);
+ try {
+ DbImage.setImageOwner(imageBaseId, newOwnerId);
+ } catch (SQLException e) {
+ throw new TInternalServerError();
+ }
+ }
+
+ @Override
public String createLecture(String userToken, LectureWrite lecture) throws TAuthorizationException {
// TODO Auto-generated method stub
return null;
}
@Override
- public boolean updateLecture(String userToken, String lectureId, LectureWrite lecture)
+ public void updateLecture(String userToken, String lectureId, LectureWrite lecture)
throws TAuthorizationException, TNotFoundException {
// TODO Auto-generated method stub
- return false;
}
@Override
@@ -238,17 +267,15 @@ public class ServerHandler implements SatelliteServer.Iface {
}
@Override
- public boolean deleteLecture(String userToken, String lectureId) throws TAuthorizationException,
+ public void deleteLecture(String userToken, String lectureId) throws TAuthorizationException,
TNotFoundException {
// TODO Auto-generated method stub
- return false;
}
@Override
- public boolean writeLecturePermissions(String userToken, String lectureId,
+ public void writeLecturePermissions(String userToken, String lectureId,
Map<String, LecturePermissions> permissions) throws TAuthorizationException, TNotFoundException {
// TODO Auto-generated method stub
- return false;
}
@Override
@@ -259,6 +286,13 @@ public class ServerHandler implements SatelliteServer.Iface {
}
@Override
+ public void setLectureOwner(String userToken, String lectureId, String newOwnerId)
+ throws TAuthorizationException, TNotFoundException, TInternalServerError, TException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
public List<UserInfo> getUserList(String userToken, int page) throws TAuthorizationException,
TInternalServerError {
try {
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java
index bf444a20..3fdadfb1 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java
@@ -1,12 +1,19 @@
package org.openslx.bwlp.sat.thrift;
+import java.sql.SQLException;
+import java.util.Iterator;
import java.util.Map;
+import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
+import org.openslx.bwlp.sat.database.mappers.DbUser;
+import org.openslx.bwlp.sat.permissions.User;
+import org.openslx.bwlp.sat.util.QuickTimer;
import org.openslx.bwlp.thrift.iface.AuthorizationError;
import org.openslx.bwlp.thrift.iface.TAuthorizationException;
+import org.openslx.bwlp.thrift.iface.TInvalidTokenException;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.thrifthelper.ThriftManager;
@@ -31,10 +38,29 @@ public class SessionManager {
public void touch(long now) {
this.validUntil = now + SESSION_TIMEOUT;
}
+
+ public boolean isTooOld(long now) {
+ return validUntil < now;
+ }
}
// saves the current tokens and the mapped userdata, returning from the server
- private static Map<String, Entry> tokenManager = new ConcurrentHashMap<>();
+ private static final Map<String, Entry> tokenManager = new ConcurrentHashMap<>();
+
+ static {
+ // Clean cached session periodically
+ QuickTimer.scheduleAtFixedDelay(new TimerTask() {
+ @Override
+ public void run() {
+ final long now = System.currentTimeMillis();
+ for (Iterator<Entry> it = tokenManager.values().iterator(); it.hasNext();) {
+ Entry e = it.next();
+ if (e == null || e.isTooOld(now))
+ it.remove();
+ }
+ }
+ }, 60000, 1200600);
+ }
/**
* Get the user corresponding to the given token.
@@ -61,17 +87,16 @@ public class SessionManager {
*/
public static UserInfo get(String token) {
Entry e = tokenManager.get(token);
- if (e != null) {
- // User session already cached
- final long now = System.currentTimeMillis();
- if (e.validUntil < now) {
- tokenManager.remove(token);
- return getRemote(token);
- }
- e.touch(now);
- return e.user;
+ if (e == null)
+ return getRemote(token);
+ // User session already cached
+ final long now = System.currentTimeMillis();
+ if (e.isTooOld(now)) {
+ tokenManager.remove(token);
+ return getRemote(token);
}
- return getRemote(token);
+ e.touch(now);
+ return e.user;
}
/**
@@ -83,19 +108,32 @@ public class SessionManager {
tokenManager.remove(token);
}
+ /**
+ * Get {@link UserInfo} from master server.
+ *
+ * @param token token of user to get
+ * @return
+ */
private static UserInfo getRemote(String token) {
UserInfo ui = null;
try {
ui = ThriftManager.getMasterClient().getUserFromToken(token);
+ } catch (TInvalidTokenException ite) {
+ return null; // Token not known to master server
} catch (Exception e) {
LOGGER.warn("Could not reach master server to query for user token of a client!", e);
}
- if (ui == null)
+ // Valid reply, check if user is allowed to communicate with this satellite server
+ if (!User.canLogin(ui))
+ return null;
+ // Is valid, insert/update db record
+ try {
+ DbUser.writeUserOnLogin(ui);
+ } catch (SQLException e) {
return null;
+ }
tokenManager.put(token, new Entry(ui));
return ui;
}
- // TODO: Clean map of old entries periodically
-
}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Util.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Util.java
index 338ed325..7e3c825a 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Util.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Util.java
@@ -1,6 +1,7 @@
package org.openslx.bwlp.sat.util;
import java.io.Closeable;
+import java.util.regex.Pattern;
public class Util {
@@ -42,4 +43,21 @@ public class Util {
}
}
+ private static Pattern stringChecker = Pattern.compile("[\\p{C}\\p{Zl}\\p{Zp}]");
+ private static Pattern nonSpaceMatcher = Pattern.compile("[^\\p{C}\\p{Z}]");
+
+ /**
+ * Whether the given string contains only printable characters.
+ *
+ * @param string {@link String} to check
+ * @return
+ */
+ public static boolean isPrintable(String string) {
+ return !stringChecker.matcher(string).find();
+ }
+
+ public static boolean isEmptyString(String string) {
+ return !nonSpaceMatcher.matcher(string).find();
+ }
+
}