diff options
| author | Stephan Schwaer | 2015-06-26 16:06:16 +0200 |
|---|---|---|
| committer | Stephan Schwaer | 2015-06-26 16:06:16 +0200 |
| commit | 744238941b639c69d4b727b5b67eb8075ee88263 (patch) | |
| tree | 788560e8b79371dc807382fe8fc69ccf87a7965c /dozentenmodulserver/src/main/java | |
| parent | Added disclaimer, main window and vmware info windows. Fixed some layout. (diff) | |
| parent | [server] Fnished image-related methods so far, started implementing lecture-r... (diff) | |
| download | tutor-module-744238941b639c69d4b727b5b67eb8075ee88263.tar.gz tutor-module-744238941b639c69d4b727b5b67eb8075ee88263.tar.xz tutor-module-744238941b639c69d4b727b5b67eb8075ee88263.zip | |
Merge branch 'v1.1' of git.openslx.org:openslx-ng/tutor-module into v1.1
Diffstat (limited to 'dozentenmodulserver/src/main/java')
15 files changed, 908 insertions, 56 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/Paginator.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Paginator.java new file mode 100644 index 00000000..285d7aa3 --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Paginator.java @@ -0,0 +1,11 @@ +package org.openslx.bwlp.sat.database; + +public class Paginator { + + public static final int PER_PAGE = 200; + + public static String limitStatement(int page) { + return " LIMIT " + (page * PER_PAGE) + ", " + PER_PAGE; + } + +} 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..1fb19121 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; @@ -44,6 +47,7 @@ public class DbImage { */ public static List<ImageSummaryRead> getAllVisible(UserInfo user, List<String> tagSearch) throws SQLException { + // TODO: Implement tag search functionality try (MysqlConnection connection = Database.getConnection()) { MysqlStatement stmt = connection.prepareStatement("SELECT" + " i.imagebaseid, i.currentversionid, i.latestversionid, i.displayname," @@ -169,6 +173,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.executeUpdate(); + 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 +292,54 @@ public class DbImage { return ShareMode.valueOf(string); } + /** + * Update meta data of a specific image version. + * + * @param user user doing the edit + * @param imageVersionId UUID of image version + * @param image meta data to set + * @throws SQLException + */ + 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.executeUpdate(); + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbImage.updateImageVersion()", e); + throw e; + } + } + + /** + * Mark given image for deletion. The image is marked for deletion by + * setting the expire timestamp to the current date, and by setting the + * image disabled and invalid. Next time the cleanup task runs, the image + * will be deleted. + * + * @param imageVersionId UUID of image version to delete + * @throws SQLException + */ + public static void markForDeletion(String imageVersionId) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("UPDATE imageversion SET" + + " expiretime = UNIX_TIMESTAMP() - 1, isenabled = 0, isvalid = 0" + + " WHERE imageversionid = :versionid"); + stmt.setString("versionid", imageVersionId); + stmt.executeUpdate(); + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbImage.markForDeletion()", e); + throw e; + } + } + } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImagePermissions.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImagePermissions.java index 9f089b42..7f8bf33f 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImagePermissions.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImagePermissions.java @@ -101,4 +101,31 @@ public class DbImagePermissions { } } + public static void writeForImageBase(String imageBaseId, Map<String, ImagePermissions> permissions) + throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("DELETE FROM imagepermission" + + " WHERE imagebaseid = :baseid"); + stmt.setString("imagebaseid", imageBaseId); + stmt.executeUpdate(); + stmt = connection.prepareStatement("INSERT INTO imagepermission" + + " (imagebaseid, userid, canlink, candownload, canedit, canadmin)" + + " VALUES (:baseid, :userid, :canlink, :candownload, :canedit, :canadmin)"); + stmt.setString("baseid", imageBaseId); + for (Map.Entry<String, ImagePermissions> entry : permissions.entrySet()) { + ImagePermissions perm = entry.getValue(); + stmt.setString("userid", entry.getKey()); + stmt.setBoolean("canlink", perm.link); + stmt.setBoolean("candownload", perm.download); + stmt.setBoolean("canedit", perm.edit); + stmt.setBoolean("canadmin", perm.admin); + stmt.executeUpdate(); + } + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbImagePermissions.writeForImageBase()", e); + throw e; + } + } + } 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 new file mode 100644 index 00000000..7f2fa4c5 --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java @@ -0,0 +1,137 @@ +package org.openslx.bwlp.sat.database.mappers; + +import java.sql.ResultSet; +import java.sql.SQLException; +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.sat.util.Json; +import org.openslx.bwlp.thrift.iface.LecturePermissions; +import org.openslx.bwlp.thrift.iface.LectureSummary; +import org.openslx.bwlp.thrift.iface.LectureWrite; +import org.openslx.bwlp.thrift.iface.TNotFoundException; +import org.openslx.bwlp.thrift.iface.UserInfo; + +public class DbLecture { + + private static final Logger LOGGER = Logger.getLogger(DbLecture.class); + + public static String create(UserInfo user, LectureWrite lecture) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("INSERT INTO lecture" + + " (lectureid, displayname, description, imageversionid, autoupdate," + + " isenabled, starttime, endtime, createtime, updatetime," + + " ownerid, updaterid, runscript, nics, netrules, isexam," + + " hasinternetaccess, caneditdefault, canadmindefault)" + + " VALUES " + + " (:lectureid, '<defunct>', '<defunct>', :imageversionid, 0," + + " 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()," + + " :userid, :userid, NULL, NULL, NULL, 0, 0, 0, 0)"); + String lectureId = UUID.randomUUID().toString(); + stmt.setString("lectureid", lectureId); + stmt.setString("imageversionid", lecture.imageVersionId); + stmt.setString("userid", user.userId); + stmt.executeUpdate(); + update(connection, user, lectureId, lecture); + connection.commit(); + return lectureId; + } catch (SQLException e) { + LOGGER.error("Query failed in DbLecture.create()", e); + throw e; + } + } + + public static void setOwner(UserInfo user, String lectureId, String newOwnerId) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("UPDATE lecture" + + " SET ownerid = :ownerid, updaterid = :userid, updatetime = UNIX_TIMESTAMP()" + + " WHERE lectureid = :lectureid"); + stmt.setString("ownerid", newOwnerId); + stmt.setString("userid", user.userId); + stmt.setString("lectureid", lectureId); + stmt.executeUpdate(); + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbLecture.setOwner()", e); + throw e; + } + } + + public static void update(UserInfo user, String lectureId, LectureWrite lecture) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + update(connection, user, lectureId, lecture); + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbLecture.update()", e); + throw e; + } + } + + private static void update(MysqlConnection connection, UserInfo user, String lectureId, + LectureWrite lecture) throws SQLException { + String nicsJson = Json.serialize(lecture.nics); + String netruleJson = Json.serialize(lecture.networkExceptions); + MysqlStatement stmt = connection.prepareStatement("UPDATE lecture SET " + + " displayname = :displayname, description = :description, imageversionid = :imageversionid," + + " autoupdate = :autoupdate, isenabled = :isenabled, starttime = :starttime," + + " endtime = :endtime, createtime = :createtime, updatetime = :updatetime," + + " updaterid = :updaterid, runscript = :runscript, nics = :nics," + + " netrules = :netrules, isexam = :isexam, hasinternetaccess = :hasinternetaccess," + + " caneditdefault = :caneditdefault, canadmindefault = :canadmindefault" + + " WHERE lectureid = :lectureid"); + stmt.setString("lectureid", lectureId); + stmt.setString("displayname", lecture.lectureName); + stmt.setString("description", lecture.description); + stmt.setString("imageversionid", lecture.imageVersionId); + stmt.setBoolean("autoupdate", lecture.autoUpdate); + stmt.setBoolean("isenabled", lecture.isEnabled); + stmt.setLong("starttime", lecture.startTime); + stmt.setLong("endtime", lecture.endTime); + stmt.setString("updaterid", user.userId); + stmt.setString("runscript", lecture.runscript); + stmt.setString("nics", nicsJson); + stmt.setString("netrules", netruleJson); + stmt.setBoolean("isexam", lecture.isExam); + stmt.setBoolean("hasinternetaccess", lecture.hasInternetAccess); + stmt.setBoolean("caneditdefault", lecture.defaultPermissions.edit); + stmt.setBoolean("canadmindefault", lecture.defaultPermissions.admin); + stmt.executeUpdate(); + } + + public static LectureSummary getLectureSummary(UserInfo user, String lectureId) throws SQLException, + TNotFoundException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("SELECT" + + " l.lectureid, l.displayname AS lecturename, l.imageversionid, l.isenabled," + + " l.starttime, l.endtime, l.lastused, l.usecount, l.ownerid, l.updaterid," + + " l.isexam, l.hasinternetaccess, l.caneditdefault, l.canadmindefault," + + " perm.canedit, perm.canadmin" + + " LEFT JOIN lecturepermission perm ON (perm.lectureid = l.lectureid AND perm.userid = :userid)" + + " WHERE lectureid = :lectureid"); + stmt.setString("lectureid", lectureId); + stmt.setString("userid", user.userId); + ResultSet rs = stmt.executeQuery(); + if (!rs.next()) + throw new TNotFoundException(); + return resultSetToSummary(rs); + } catch (SQLException e) { + LOGGER.error("Query failed in DbLecture.getLectureSummary()", e); + throw e; + } + } + + private static LectureSummary resultSetToSummary(ResultSet rs) throws SQLException { + LecturePermissions defaultPermissions = DbLecturePermissions.fromResultSetDefault(rs); + LectureSummary entry = new LectureSummary(rs.getString("lectureid"), rs.getString("lecturename"), + rs.getString("imageversionid"), null, rs.getBoolean("isenabled"), rs.getLong("starttime"), + rs.getLong("endtime"), rs.getLong("lastused"), rs.getInt("usecount"), + rs.getString("ownerid"), rs.getString("updaterid"), rs.getBoolean("isexam"), + rs.getBoolean("hasinternetaccess"), defaultPermissions, false); + entry.userPermissions = DbLecturePermissions.fromResultSetUser(rs); + return entry; + } + +} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecturePermissions.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecturePermissions.java new file mode 100644 index 00000000..e8bd8a07 --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecturePermissions.java @@ -0,0 +1,63 @@ +package org.openslx.bwlp.sat.database.mappers; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.openslx.bwlp.thrift.iface.LecturePermissions; + +public class DbLecturePermissions { + + /** + * Build an instance of {@link LecturePermissions} by reading the given + * columns from the given {@link ResultSet}. If there are no permissions + * given in the ResultSet, <code>null</code> is returned. + * + * @param rs the {@link ResultSet} to read from + * @param canLink Name of the column to read the "can link" permission from + * @param canDownload Name of the column to read the "can download" + * permission from + * @param canEdit Name of the column to read the "can edit" permission from + * @param canAdmin Name of the column to read the "can admin" permission + * from + * @return instance of {@link LecturePermissions}, or <code>null</code> + * @throws SQLException + */ + private static LecturePermissions fromResultSet(ResultSet rs, String canEdit, String canAdmin) + throws SQLException { + boolean edit = rs.getBoolean(canEdit); + if (rs.wasNull()) + return null; + return new LecturePermissions(edit, rs.getBoolean(canAdmin)); + } + + /** + * Build an instance of {@link LecturePermissions} by reading the + * columns <code>canlink</code>, <code>candownload</code>, + * <code>canedit</code>, <code>canadmin</code> from the given + * {@link ResultSet}. If there are no permissions + * given in the ResultSet, <code>null</code> is returned. + * + * @param rs the {@link ResultSet} to read from + * @return instance of {@link LecturePermissions}, or <code>null</code> + * @throws SQLException + */ + public static LecturePermissions fromResultSetUser(ResultSet rs) throws SQLException { + return fromResultSet(rs, "canedit", "canadmin"); + } + + /** + * Build an instance of {@link LecturePermissions} by reading the + * columns <code>canlinkdefault</code>, <code>candownloaddefault</code>, + * <code>caneditdefault</code>, <code>canadmindefault</code> from the given + * {@link ResultSet}. If there are no permissions + * given in the ResultSet, <code>null</code> is returned. + * + * @param rs the {@link ResultSet} to read from + * @return instance of {@link LecturePermissions}, or <code>null</code> + * @throws SQLException + */ + public static LecturePermissions fromResultSetDefault(ResultSet rs) throws SQLException { + return fromResultSet(rs, "caneditdefault", "canadmindefault"); + } + +} 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..451b3217 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,17 +9,17 @@ 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.Paginator; +import org.openslx.bwlp.sat.database.models.LocalUser; import org.openslx.bwlp.thrift.iface.UserInfo; public class DbUser { private static final Logger LOGGER = Logger.getLogger(DbUser.class); - private static final int PER_PAGE = 200; - /** * Get all users, starting at page <code>page</code>. - * This function will return a maximum of {@link #PER_PAGE}(200) results, so + * This function will return a maximum of {@link #PER_PAGE} results, so * you might need to call this method several times. * * @param page Page to return. The first page is page 0. @@ -29,10 +29,9 @@ public class DbUser { public static List<UserInfo> getAll(int page) throws SQLException { if (page < 0) return new ArrayList<>(1); - final int offset = page * 200; try (MysqlConnection connection = Database.getConnection()) { MysqlStatement stmt = connection.prepareStatement("SELECT userid, firstname, lastname, email, organizationid" - + " FROM user ORDER BY userid ASC LIMIT " + offset + ", " + PER_PAGE); + + " FROM user ORDER BY userid ASC " + Paginator.limitStatement(page)); ResultSet rs = stmt.executeQuery(); List<UserInfo> list = new ArrayList<>(); while (rs.next()) { @@ -46,4 +45,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..2ffd281a 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,27 +1,39 @@ package org.openslx.bwlp.sat.permissions; import java.sql.SQLException; +import java.util.Map; +import org.apache.log4j.Logger; import org.openslx.bwlp.sat.database.mappers.DbImage; +import org.openslx.bwlp.sat.database.mappers.DbLecture; +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; +import org.openslx.bwlp.thrift.iface.LecturePermissions; +import org.openslx.bwlp.thrift.iface.LectureSummary; import org.openslx.bwlp.thrift.iface.Role; 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 { + private static final Logger LOGGER = Logger.getLogger(User.class); + + 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 +47,117 @@ public class User { if (checkPerm == Permission.ADMIN) return perm.admin; } - return isSuperUser(ui); + return false; + } + + private static boolean canActionLecture(UserInfo user, Permission checkPerm, + LecturePermissions... lecturePermissions) { + if (checkPerm == Permission.DOWNLOAD || checkPerm == Permission.LINK) { + LOGGER.warn("Invalid permission check for lecture: " + checkPerm, new RuntimeException( + "Here's your stack trace")); + return false; + } + for (LecturePermissions perm : lecturePermissions) { + if (perm == null) + continue; + if (checkPerm == Permission.EDIT) + return perm.edit; + if (checkPerm == Permission.ADMIN) + return perm.admin; + } + 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; + } + + /** + * 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; } - public static boolean isSuperUser(UserInfo ui) { - // TODO: for superuser override, read from DB + /** + * 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 +170,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); } /** @@ -121,11 +242,37 @@ public class User { public static void hasImageVersionPermissionOrFail(UserInfo user, String imageVersionId, Permission permission) throws TAuthorizationException, TInternalServerError, TNotFoundException { if (!hasImageVersionPermission(user, imageVersionId, permission)) { - throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "Required permission: " + throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "Required image permission: " + permission.toString()); } } + public static boolean hasLecturePermission(UserInfo user, String lectureId, Permission permission) + throws TInternalServerError, TNotFoundException { + if (user.role != Role.TUTOR) + return false; + // Check general permissions + LectureSummary lecture; + try { + lecture = DbLecture.getLectureSummary(user, lectureId); + } catch (SQLException e) { + throw new TInternalServerError(); + } + // Owner has all permissions + if (lecture.ownerId.equals(user.userId)) + return true; + return canActionLecture(user, permission, lecture.userPermissions, lecture.defaultPermissions) + || isSuperUser(user); + } + + public static void hasLecturePermissionOrFail(UserInfo user, String lectureId, Permission permission) + throws TAuthorizationException, TInternalServerError, TNotFoundException { + if (!hasLecturePermission(user, lectureId, permission)) { + throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, + "Required lecture permission: " + permission.toString()); + } + } + /** * Checks whether the given user is allowed to create new images. * @@ -142,4 +289,20 @@ public class User { "No permission to create new image"); } + /** + * Checks whether the given user is allowed to create new lectures. + * + * @param user {@link UserInfo} instance representing the user in question + * @return true or false + */ + public static boolean canCreateLecture(UserInfo user) { + return user.role == Role.TUTOR; + } + + public static void canCreateLectureOrFail(UserInfo user) throws TAuthorizationException { + if (!canCreateLecture(user)) + throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, + "No permission to create new lecture"); + } + } 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..cab355a7 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,8 +6,10 @@ 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.DbLecture; import org.openslx.bwlp.sat.database.mappers.DbUser; import org.openslx.bwlp.sat.fileserv.ActiveUpload; import org.openslx.bwlp.sat.fileserv.FileServer; @@ -16,7 +18,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 +33,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 +153,70 @@ 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; + try { + DbImage.markForDeletion(imageVersionId); + } catch (SQLException e) { + throw new TInternalServerError(); + } } @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; + try { + DbImagePermissions.writeForImageBase(imageBaseId, permissions); + } catch (SQLException e) { + throw new TInternalServerError(); + } } @Override @@ -205,16 +232,39 @@ public class ServerHandler implements SatelliteServer.Iface { } @Override - public String createLecture(String userToken, LectureWrite lecture) throws TAuthorizationException { - // TODO Auto-generated method stub - return null; + 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 boolean updateLecture(String userToken, String lectureId, LectureWrite lecture) - throws TAuthorizationException, TNotFoundException { - // TODO Auto-generated method stub - return false; + public String createLecture(String userToken, LectureWrite lecture) throws TAuthorizationException, + TInternalServerError { + UserInfo user = SessionManager.getOrFail(userToken); + User.canCreateLectureOrFail(user); + try { + return DbLecture.create(user, lecture); + } catch (SQLException e) { + throw new TInternalServerError(); + } + } + + @Override + public void updateLecture(String userToken, String lectureId, LectureWrite lecture) + throws TAuthorizationException, TNotFoundException, TInternalServerError { + UserInfo user = SessionManager.getOrFail(userToken); + User.hasLecturePermissionOrFail(user, lectureId, Permission.EDIT); + try { + DbLecture.update(user, lectureId, lecture); + } catch (SQLException e) { + throw new TInternalServerError(); + } } @Override @@ -238,17 +288,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 +307,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/Json.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Json.java new file mode 100644 index 00000000..fe43793a --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Json.java @@ -0,0 +1,35 @@ +package org.openslx.bwlp.sat.util; + +import com.google.gson.Gson; + +public class Json { + + /** + * Global static instance. The Gson object is thread-safe. + */ + private static final Gson gson = new Gson(); + + /** + * Deserialize the given json string to an instance of T. + * This will deserialize all fields, except transient ones. + * + * @param data JSON formatted data + * @param classOfData class to instantiate + * @return instanceof T + */ + public static <T> T deserialize(String data, Class<T> classOfData) { + return gson.fromJson(data, classOfData); + } + + /** + * Serialize the given POJO. All fields except transient ones will be + * serialized. + * + * @param object some object to serialize + * @return JSON formatted represenatation of <code>object</code> + */ + public static String serialize(Object object) { + return gson.toJson(object); + } + +} 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(); + } + } |
