diff options
author | Simon Rettberg | 2015-08-10 18:34:03 +0200 |
---|---|---|
committer | Simon Rettberg | 2015-08-10 18:34:03 +0200 |
commit | d7f38f8df8e9f049233ef5878eca8ca416bc210e (patch) | |
tree | 286333d2dac603a4f4e88988aed23e8fe751ec93 /dozentenmodulserver | |
parent | [client] improved an error message (diff) | |
download | tutor-module-d7f38f8df8e9f049233ef5878eca8ca416bc210e.tar.gz tutor-module-d7f38f8df8e9f049233ef5878eca8ca416bc210e.tar.xz tutor-module-d7f38f8df8e9f049233ef5878eca8ca416bc210e.zip |
[server] Overhaul permission checking, precalc user permissions, implement download
Diffstat (limited to 'dozentenmodulserver')
8 files changed, 340 insertions, 206 deletions
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 f9a22429..74a3eb96 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 @@ -11,6 +11,8 @@ 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.LocalImageVersion; +import org.openslx.bwlp.sat.permissions.User; import org.openslx.bwlp.thrift.iface.ImageBaseWrite; import org.openslx.bwlp.thrift.iface.ImageDetailsRead; import org.openslx.bwlp.thrift.iface.ImagePermissions; @@ -58,7 +60,7 @@ public class DbImage { ResultSet rs = stmt.executeQuery(); List<ImageSummaryRead> list = new ArrayList<>(100); while (rs.next()) { - list.add(resultSetToSummary(rs)); + list.add(resultSetToSummary(user, rs)); } return list; } catch (SQLException e) { @@ -93,6 +95,7 @@ public class DbImage { rs.getLong("createtime"), rs.getLong("updatetime"), rs.getString("ownerid"), rs.getString("updaterid"), toShareMode(rs.getString("sharemode")), rs.getByte("istemplate") != 0, defaultPermissions); + User.setCombinedUserPermissions(image, user); return image; } catch (SQLException e) { LOGGER.error("Query failed in DbImage.getImageDetails()", e); @@ -100,6 +103,23 @@ public class DbImage { } } + public static LocalImageVersion getLocalImageData(String imageVersionId) throws TNotFoundException, + SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("SELECT imageversionid, imagebaseid, filepath, filesize" + + " FROM imageversion WHERE imageversionid = :versionid LIMIT 1"); + stmt.setString("versionid", imageVersionId); + ResultSet rs = stmt.executeQuery(); + if (!rs.next()) + throw new TNotFoundException(); + return new LocalImageVersion(rs.getString("imageversionid"), rs.getString("imagebaseid"), + rs.getString("filepath"), rs.getLong("filesize")); + } catch (SQLException e) { + LOGGER.error("Query failed in DbImage.getLocalImageData()", e); + throw e; + } + } + /** * Private helper to create an {@link ImageSummaryRead} instance from a * {@link ResultSet} @@ -108,7 +128,7 @@ public class DbImage { * @return * @throws SQLException */ - private static ImageSummaryRead resultSetToSummary(ResultSet rs) throws SQLException { + private static ImageSummaryRead resultSetToSummary(UserInfo user, ResultSet rs) throws SQLException { ImagePermissions defaultPermissions = DbImagePermissions.fromResultSetDefault(rs); ImageSummaryRead entry = new ImageSummaryRead(rs.getString("imagebaseid"), rs.getString("latestversionid"), rs.getString("displayname"), rs.getInt("osid"), @@ -118,6 +138,7 @@ public class DbImage { rs.getByte("isrestricted") != 0, rs.getByte("isvalid") != 0, rs.getByte("isprocessed") != 0, rs.getByte("istemplate") != 0, defaultPermissions); entry.userPermissions = DbImagePermissions.fromResultSetUser(rs); + User.setCombinedUserPermissions(entry, user); return entry; } @@ -160,7 +181,7 @@ public class DbImage { if (!rs.next()) { throw new TNotFoundException(); } - return resultSetToSummary(rs); + return resultSetToSummary(user, rs); } private static List<ImageVersionDetails> getImageVersions(MysqlConnection connection, String imageBaseId) @@ -268,8 +289,9 @@ public class DbImage { * @param imageVersionId * @return * @throws SQLException + * @throws TNotFoundException */ - public static String getBaseIdForVersionId(String imageVersionId) throws SQLException { + public static String getBaseIdForVersionId(String imageVersionId) throws SQLException, TNotFoundException { try (MysqlConnection connection = Database.getConnection()) { return getBaseIdForVersionId(connection, imageVersionId); } catch (SQLException e) { @@ -280,20 +302,20 @@ public class DbImage { /** * Get the UUID of the image base belonging to the given image version UUID. - * Returns <code>null</code> if the UUID does not exist. * * @param imageVersionId * @return * @throws SQLException + * @throws TNotFoundException version id is unknown */ protected static String getBaseIdForVersionId(MysqlConnection connection, String imageVersionId) - throws SQLException { + throws SQLException, TNotFoundException { MysqlStatement stmt = connection.prepareStatement("SELECT imagebaseid FROM imageversion" + " WHERE imageversionid = :imageversionid LIMIT 1"); stmt.setString("imageversionid", imageVersionId); ResultSet rs = stmt.executeQuery(); if (!rs.next()) - return null; + throw new TNotFoundException(); return rs.getString("imagebaseid"); } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalImageVersion.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalImageVersion.java new file mode 100644 index 00000000..91c5acac --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/models/LocalImageVersion.java @@ -0,0 +1,20 @@ +package org.openslx.bwlp.sat.database.models; + +public class LocalImageVersion { + + public final String imageVersionId; + + public final String imageBaseId; + + public final String filePath; + + public final long fileSize; + + public LocalImageVersion(String imageVersionId, String imageBaseId, String filePath, long fileSize) { + this.imageVersionId = imageVersionId; + this.imageBaseId = imageBaseId; + this.filePath = filePath; + this.fileSize = fileSize; + } + +} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveDownload.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveDownload.java new file mode 100644 index 00000000..7180fe3d --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveDownload.java @@ -0,0 +1,86 @@ +package org.openslx.bwlp.sat.fileserv; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadPoolExecutor; + +import org.apache.log4j.Logger; +import org.openslx.bwlp.sat.util.Constants; +import org.openslx.bwlp.thrift.iface.TransferState; +import org.openslx.filetransfer.Uploader; + +public class ActiveDownload { + + private static final Logger LOGGER = Logger.getLogger(ActiveDownload.class); + + /** + * How many concurrent connections per upload + */ + private static final int MAX_CONNECTIONS = Math.max(Constants.MAX_DOWNLOADS / 4, 1); + + /** + * Self reference for inner classes. + */ + private final ActiveDownload activeDownload = this; + + /** + * This is a download, so we have uploaders + */ + private List<Uploader> uploads = new ArrayList<>(); + + private final File sourceFile; + + private final long fileSize; + + private final String transferId; + + /** + * TransferState of this upload + */ + private TransferState state = TransferState.IDLE; + + public ActiveDownload(String uuid, File file) { + this.transferId = uuid; + this.sourceFile = file; + this.fileSize = file.length(); + } + + /** + * Add another connection for this file transfer. Currently only one + * connection is allowed, but this might change in the future. + * + * @param connection + * @return true if the connection is accepted, false if it should be + * discarded + */ + public synchronized boolean addConnection(final Uploader connection, ThreadPoolExecutor pool) { + synchronized (uploads) { + if (uploads.size() > MAX_CONNECTIONS) + return false; + uploads.add(connection); + } + try { + pool.execute(new Runnable() { + @Override + public void run() { + connection.upload(sourceFile.getAbsolutePath()); + } + }); + } catch (Exception e) { + LOGGER.warn("threadpool rejected the incoming file transfer", e); + return false; + } + return true; + } + + public boolean isComplete() { + // TODO Auto-generated method stub + return false; + } + + public String getId() { + return transferId; + } + +} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java index e7841ccd..d03f79de 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java @@ -161,6 +161,7 @@ public class ActiveUpload implements HashCheckCallback { if (downloads.size() >= MAX_CONNECTIONS) return false; downloads.add(connection); + // TODO: Remove when finished or executor rejects... } try { pool.execute(new Runnable() { diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java index 16369745..d1136c2b 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java @@ -14,6 +14,8 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; +import org.openslx.bwlp.sat.database.models.LocalImageVersion; +import org.openslx.bwlp.sat.util.Configuration; import org.openslx.bwlp.sat.util.Constants; import org.openslx.bwlp.sat.util.Formatter; import org.openslx.bwlp.thrift.iface.ImageDetailsRead; @@ -41,6 +43,11 @@ public class FileServer implements IncomingEvent { */ private final Map<String, ActiveUpload> uploads = new ConcurrentHashMap<>(); + /** + * All currently running downloads, indexed by token + */ + private final Map<String, ActiveDownload> downloads = new ConcurrentHashMap<>(); + private static final FileServer globalInstance = new FileServer(); private FileServer() { @@ -133,4 +140,34 @@ public class FileServer implements IncomingEvent { return 0; // TODO } + public ActiveDownload createNewUserDownload(LocalImageVersion localImageData) + throws TTransferRejectedException { + Iterator<ActiveDownload> it = downloads.values().iterator(); + int activeDownloads = 0; + while (it.hasNext()) { + ActiveDownload download = it.next(); + if (download.isComplete()) { + // TODO: Check age (short timeout) and remove + continue; + } else { + // Check age (long timeout) and remove + } + activeDownloads++; + } + if (activeDownloads > Constants.MAX_DOWNLOADS) + throw new TTransferRejectedException("Server busy. Too many running downloads."); + // Determine src file and go + File srcFile = new File(Configuration.getCurrentVmStorePath(), localImageData.filePath); + if (!srcFile.canRead()) { + LOGGER.warn("Rejecting download of VID " + localImageData.imageVersionId + ": Missing " + + srcFile.getName()); + // TODO: Mark as invalid in DB + throw new TTransferRejectedException("File missing on server"); + } + String key = UUID.randomUUID().toString(); + ActiveDownload transfer = new ActiveDownload(key, srcFile); + downloads.put(key, transfer); + return transfer; + } + } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/PermCheck.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/PermCheck.java deleted file mode 100644 index 6b4af039..00000000 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/PermCheck.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.openslx.bwlp.sat.permissions; - -import java.sql.SQLException; - -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.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.TAuthorizationException; -import org.openslx.bwlp.thrift.iface.TInternalServerError; -import org.openslx.bwlp.thrift.iface.TNotFoundException; -import org.openslx.bwlp.thrift.iface.UserInfo; - -public class PermCheck { - - public static enum Permission { - LINK, - DOWNLOAD, - EDIT, - ADMIN - } - - private static final Logger LOGGER = Logger.getLogger(Permission.class); - - protected static boolean canActionImage(UserInfo user, Permission checkPerm, - ImagePermissions... imagePermissions) { - for (ImagePermissions perm : imagePermissions) { - if (perm == null) - continue; - if (checkPerm == Permission.LINK) - return perm.link; - if (checkPerm == Permission.DOWNLOAD) - return perm.download; - if (checkPerm == Permission.EDIT) - return perm.edit; - if (checkPerm == Permission.ADMIN) - return perm.admin; - } - return false; - } - - protected 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; - } - - /** - * Check if the given user has the given permission for the image identified - * by the given image base id. - * - * @param user - * @param imageBaseId - * @param permission - * @throws TInternalServerError - * @throws TNotFoundException - */ - protected static boolean hasImageBasePermission(UserInfo user, String imageBaseId, Permission permission) - throws TInternalServerError, TNotFoundException { - // 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) - || User.isSuperUser(user); - } - - /** - * Check if the given user has the given permission for the image identified - * by the given image base id. - * - * @param user - * @param imageBaseId - * @param permission - * @throws TAuthorizationException - * @throws TInternalServerError - * @throws TNotFoundException - */ - protected static void hasImageBasePermissionOrFail(UserInfo user, String imageBaseId, Permission permission) - throws TAuthorizationException, TInternalServerError, TNotFoundException { - if (!hasImageBasePermission(user, imageBaseId, permission)) { - throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "Required permission: " - + permission.toString()); - } - } - - /** - * Check if the given user has the given permission for the image identified - * by the given image version id. - * - * @param user - * @param imageVersionId - * @param permission - * @throws TInternalServerError - * @throws TNotFoundException - */ - protected static boolean hasImageVersionPermission(UserInfo user, String imageVersionId, - Permission permission) throws TInternalServerError, TNotFoundException { - try { - String imageBaseId = DbImage.getBaseIdForVersionId(imageVersionId); - if (imageBaseId == null) - throw new TNotFoundException(); - return hasImageBasePermission(user, imageBaseId, permission); - } catch (SQLException e) { - throw new TInternalServerError(); - } - } - - /** - * Check if the given user has the given permission for the image identified - * by the given image version id. - * - * @param user - * @param imageVersionId - * @param permission - * @throws TAuthorizationException - * @throws TInternalServerError - * @throws TNotFoundException - */ - protected 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 image permission: " - + permission.toString()); - } - } - - protected static boolean hasLecturePermission(UserInfo user, String lectureId, Permission permission) - throws TInternalServerError, TNotFoundException { - // 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) - || User.isSuperUser(user); - } - - protected 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()); - } - } - - -} 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 4096deae..fba1126d 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 @@ -3,13 +3,18 @@ package org.openslx.bwlp.sat.permissions; import java.sql.SQLException; 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.models.LocalOrganization; import org.openslx.bwlp.sat.database.models.LocalUser; -import org.openslx.bwlp.sat.permissions.PermCheck.Permission; import org.openslx.bwlp.thrift.iface.AuthorizationError; 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.LecturePermissions; +import org.openslx.bwlp.thrift.iface.LectureRead; +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; @@ -18,6 +23,12 @@ import org.openslx.bwlp.thrift.iface.UserInfo; public class User { + private static final ImagePermissions imageSu = new ImagePermissions(true, true, true, true); + + private static final LecturePermissions lectureSu = new LecturePermissions(true, true); + + private static final LecturePermissions lectureNothing = new LecturePermissions(false, false); + public static boolean isTutor(UserInfo user) { return user.role == Role.TUTOR; } @@ -96,7 +107,8 @@ public class User { */ public static void canEditBaseImageOrFail(UserInfo user, String imageBaseId) throws TInternalServerError, TNotFoundException, TAuthorizationException { - if (!isTutor(user) || !PermCheck.hasImageBasePermission(user, imageBaseId, Permission.EDIT)) { + ImageSummaryRead image = getImageFromBaseId(user, imageBaseId); + if (!image.userPermissions.edit) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to edit this image"); } @@ -141,22 +153,42 @@ public class User { } catch (SQLException e) { throw new TInternalServerError(); } - // User owns the base image - allow - if (imageDetails.ownerId.equals(user.userId)) - return; - // User is image admin - allow - if (PermCheck.canActionImage(user, Permission.ADMIN, imageDetails.userPermissions, - imageDetails.defaultPermissions)) + // Check user permissions + if (imageDetails.userPermissions.admin) return; - // User uploaded the image version in question - allow - for (ImageVersionDetails version : imageDetails.versions) { - if (version.uploaderId.equals(user.userId)) - return; + // User uploaded the image version in question and has edit permissions - allow + if (imageDetails.userPermissions.edit) { + for (ImageVersionDetails version : imageDetails.versions) { + if (version.versionId.equals(imageVersionId) && version.uploaderId.equals(user.userId)) + return; + } } throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to delete this image version"); } + public static void canDownloadImageVersionOrFail(UserInfo user, String imageVersionId) + throws TAuthorizationException, TNotFoundException, TInternalServerError { + ImageDetailsRead image; + try { + image = DbImage.getImageDetails(user, DbImage.getBaseIdForVersionId(imageVersionId)); + } catch (SQLException e) { + throw new TInternalServerError(); + } + if (user != null && user.role != Role.STUDENT) { + if (image.userPermissions.download) + return; + } else { + // User is unknown role or student, check version's restricted flag + for (ImageVersionDetails version : image.versions) { + if (!version.isRestricted && version.versionId.equals(imageVersionId)) + return; + } + } + throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, + "No permission to download this image version"); + } + /** * Checks whether the given user is allowed to create new lectures. * Throws {@link TAuthorizationException} if permission is not granted. @@ -170,8 +202,8 @@ public class User { } /** - * Checks whether the given user can edit the image identified by the given - * image base id + * Checks whether the given user can edit the permission list of the image + * identified by the given image base id. * * @param user * @param imageBaseId @@ -181,18 +213,19 @@ public class User { */ public static boolean canEditImagePermissions(UserInfo user, String imageBaseId) throws TInternalServerError, TNotFoundException { - return isTutor(user) && PermCheck.hasImageBasePermission(user, imageBaseId, Permission.ADMIN); + ImageSummaryRead image = getImageFromBaseId(user, imageBaseId); + return image.userPermissions.admin; } /** - * Checks whether the given user can edit the image identified by the given - * image base id. - * Throws {@link TAuthorizationException} if permission is not granted. + * Checks whether the given user can edit the permission list of the image + * identified by the given image base id. * * @param user * @param imageBaseId * @throws TInternalServerError * @throws TNotFoundException + * @throws TAuthorizationException if permission is not granted. */ public static void canEditImagePermissionsOrFail(UserInfo user, String imageBaseId) throws TAuthorizationException, TInternalServerError, TNotFoundException { @@ -205,7 +238,8 @@ public class User { throws TAuthorizationException, TInternalServerError, TNotFoundException { // TODO: Who should be allowed to change the owner? Any admin, or just the owner? // Currently it's every admin, but this is open for discussion - if (!isTutor(user) || PermCheck.hasImageBasePermission(user, imageBaseId, Permission.ADMIN)) { + ImageSummaryRead image = getImageFromBaseId(user, imageBaseId); + if (!image.userPermissions.admin) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to change image owner"); } @@ -213,7 +247,8 @@ public class User { public static void canEditLectureOrFail(UserInfo user, String lectureId) throws TInternalServerError, TNotFoundException, TAuthorizationException { - if (!isTutor(user) || !PermCheck.hasLecturePermission(user, lectureId, Permission.EDIT)) { + LectureSummary lecture = getLectureFromId(user, lectureId); + if (!lecture.userPermissions.edit) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to edit this image"); } @@ -239,10 +274,109 @@ public class User { public static void canDeleteLectureOrFail(UserInfo user, String lectureId) throws TAuthorizationException, TInternalServerError, TNotFoundException { - if (!isTutor(user) || !PermCheck.hasLecturePermission(user, lectureId, Permission.ADMIN)) { + LectureSummary lecture = getLectureFromId(user, lectureId); + if (!lecture.userPermissions.admin) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to delete this lecture"); } } + public static void setCombinedUserPermissions(ImageSummaryRead image, UserInfo user) { + if (hasAllImagePermissions(user, image.ownerId)) { + image.userPermissions = imageSu; + return; + } + image.userPermissions = calculateUserImagePermissions(user, image.userPermissions, + image.defaultPermissions); + } + + public static void setCombinedUserPermissions(ImageDetailsRead image, UserInfo user) { + if (hasAllImagePermissions(user, image.ownerId)) { + image.userPermissions = imageSu; + return; + } + image.userPermissions = calculateUserImagePermissions(user, image.userPermissions, + image.defaultPermissions); + } + + private static boolean hasAllImagePermissions(UserInfo user, String imageOwnerId) { + if (user != null && user.role == Role.TUTOR) { + // Check for owner + if (user.userId.equals(imageOwnerId)) { + return true; + } + // Check for super user + LocalUser localUser = LocalData.getLocalUser(user); + if (localUser != null && localUser.isSuperUser) { + return true; + } + } + return false; + } + + private static ImagePermissions calculateUserImagePermissions(UserInfo user, ImagePermissions userPerms, + ImagePermissions defPerms) { + // Standard combining logic + if (userPerms == null) + userPerms = defPerms; + // Reduce student's permissions to be safe + if (user == null || user.role == Role.STUDENT) { + if (userPerms.link || userPerms.admin || userPerms.edit) { + if (userPerms == defPerms) { + userPerms = new ImagePermissions(defPerms); + } + userPerms.link = false; + userPerms.edit = false; + userPerms.admin = false; + } + } + return userPerms; + } + + public static void setCombinedUserPermissions(LectureRead lecture, UserInfo user) { + if (user == null || user.role == Role.STUDENT) { + lecture.userPermissions = lectureNothing; + return; + } + if (hasAllLecturePermissions(user, lecture.ownerId)) { + lecture.userPermissions = lectureSu; + return; + } + if (lecture.userPermissions == null) { + lecture.userPermissions = lecture.defaultPermissions; + } + } + + private static boolean hasAllLecturePermissions(UserInfo user, String lectureOwnerId) { + if (user != null && user.role == Role.TUTOR) { + // Check for owner + if (user.userId.equals(lectureOwnerId)) { + return true; + } + // Check for super user + LocalUser localUser = LocalData.getLocalUser(user); + if (localUser != null && localUser.isSuperUser) { + return true; + } + } + return false; + } + + private static ImageSummaryRead getImageFromBaseId(UserInfo user, String imageBaseId) + throws TNotFoundException, TInternalServerError { + try { + return DbImage.getImageSummary(user, imageBaseId); + } catch (SQLException e) { + throw new TInternalServerError(); + } + } + + private static LectureSummary getLectureFromId(UserInfo user, String lectureId) + throws TNotFoundException, TInternalServerError { + try { + return DbLecture.getLectureSummary(user, lectureId); + } catch (SQLException e) { + throw new TInternalServerError(); + } + } } 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 20df580d..4392a249 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 @@ -12,6 +12,7 @@ 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.ActiveDownload; import org.openslx.bwlp.sat.fileserv.ActiveUpload; import org.openslx.bwlp.sat.fileserv.FileServer; import org.openslx.bwlp.sat.permissions.User; @@ -124,9 +125,17 @@ public class ServerHandler implements SatelliteServer.Iface { @Override public TransferInformation requestDownload(String userToken, String imageVersionId) - throws TAuthorizationException { - // TODO Auto-generated method stub - return null; + throws TAuthorizationException, TInternalServerError, TNotFoundException, + TTransferRejectedException { + UserInfo user = SessionManager.getOrFail(userToken); + User.canDownloadImageVersionOrFail(user, imageVersionId); + ActiveDownload transfer; + try { + transfer = fileServer.createNewUserDownload(DbImage.getLocalImageData(imageVersionId)); + } catch (SQLException e) { + throw new TInternalServerError(); + } + return new TransferInformation(transfer.getId(), fileServer.getPlainPort(), fileServer.getSslPort()); } @Override |