diff options
| author | Simon Rettberg | 2015-06-23 19:10:48 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2015-06-23 19:10:48 +0200 |
| commit | 8ad025dd99468f71d2fa5c49e0bcf359b055ec97 (patch) | |
| tree | 6208ff7d598116e36b21882e5a018a99d2506103 /dozentenmodulserver/src | |
| parent | fix bwLehrpool logo not beeing read from the resources (diff) | |
| download | tutor-module-8ad025dd99468f71d2fa5c49e0bcf359b055ec97.tar.gz tutor-module-8ad025dd99468f71d2fa5c49e0bcf359b055ec97.tar.xz tutor-module-8ad025dd99468f71d2fa5c49e0bcf359b055ec97.zip | |
[server] More methods implemented
Diffstat (limited to 'dozentenmodulserver/src')
10 files changed, 506 insertions, 44 deletions
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(); + } + } |
