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.thrift.cache.OrganizationList; import org.openslx.bwlp.sat.util.Sanitizer; 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.ShareMode; import org.openslx.bwlp.thrift.iface.TAuthorizationException; import org.openslx.bwlp.thrift.iface.TInvocationException; import org.openslx.bwlp.thrift.iface.TNotFoundException; 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 != null && user.role == Role.TUTOR; } public static boolean isStudent(UserInfo user) { return user != null && user.role == Role.STUDENT; } /** * Check if given user is a local super user. * * @param user * @return */ public static boolean isSuperUser(UserInfo user) { LocalUser localData = 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 null if user is allowed, {@link AuthorizationError} otherwise */ public static AuthorizationError canLogin(UserInfo user) { LocalUser localData = LocalData.getLocalUser(user); if (localData != null) { if (localData.canLogin) return null; // User locally known, use user-specific permission return AuthorizationError.ACCOUNT_SUSPENDED; } // User unknown, check per-organization login permission LocalOrganization local = LocalData.getLocalOrganization(user.organizationId); if (local == null && OrganizationList.find(user.organizationId) == null) return AuthorizationError.INVALID_ORGANIZATION; // Organization known an allowed to login if (local != null && local.canLogin) return null; // 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 null; } else { return AuthorizationError.ORGANIZATION_SUSPENDED; } } catch (SQLException e) { // Ignore } return AuthorizationError.GENERIC_ERROR; } /** * Checks whether the given user is allowed to create new images. * Throws {@link TAuthorizationException} if permission is not granted. * * @param user {@link UserInfo} instance representing the user in question */ public static void canCreateImageOrFail(UserInfo user) throws TAuthorizationException { if (!isTutor(user)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to create new image"); } /** * Is given user allowed to edit/update the image identified by the given * image base id? Throws {@link TAuthorizationException} if permission is * not granted. * * @param user * @param imageBaseId * @throws TNotFoundException * @throws TInvocationException * @throws TAuthorizationException */ public static void canEditBaseImageOrFail(UserInfo user, String imageBaseId) throws TInvocationException, TNotFoundException, TAuthorizationException { ImageSummaryRead image = getImageFromBaseId(user, imageBaseId); if (!image.userPermissions.edit) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to edit this image"); } } /** * Is given user allowed to edit/update the image identified by the given * image version id? Throws {@link TAuthorizationException} if permission is * not granted. * * @param user * @param imageVersionId * @throws TNotFoundException * @throws TInvocationException * @throws TAuthorizationException */ public static void canEditImageVersionOrFail(UserInfo user, String imageVersionId) throws TInvocationException, TNotFoundException, TAuthorizationException { try { canEditBaseImageOrFail(user, DbImage.getBaseIdForVersionId(imageVersionId)); } catch (SQLException e) { throw new TInvocationException(); } } /** * Is given user allowed to delete the image identified by the given * image version id? Throws {@link TAuthorizationException} if permission is * not granted. * * @param user * @param imageVersionId * @throws TAuthorizationException * @throws TNotFoundException * @throws TInvocationException */ public static void canDeleteImageVersionOrFail(UserInfo user, String imageVersionId) throws TInvocationException, TNotFoundException, TAuthorizationException { ImageDetailsRead imageDetails; try { imageDetails = DbImage.getImageDetails(user, DbImage.getBaseIdForVersionId(imageVersionId)); } catch (SQLException e) { throw new TInvocationException(); } // Do not allow deleting remote images if share mode is set to "auto download" and // the version to delete is the latest if (imageDetails.shareMode == ShareMode.DOWNLOAD && imageDetails.latestVersionId.equals(imageVersionId)) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "Cannot delete latest version of image if auto-download is enabled"); } // Check user permissions if (imageDetails.userPermissions.admin) 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 canDeleteImageOrFail(ImageDetailsRead imageDetails) throws TAuthorizationException { // Check user permissions if (imageDetails.userPermissions.admin) return; throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to delete this image"); } public static void canDownloadImageVersionOrFail(UserInfo user, String imageBaseId, String imageVersionId) throws TAuthorizationException, TNotFoundException, TInvocationException { ImageDetailsRead image; try { if (imageBaseId == null) { imageBaseId = DbImage.getBaseIdForVersionId(imageVersionId); } image = DbImage.getImageDetails(user, imageBaseId); } catch (SQLException e) { throw new TInvocationException(); } if (image.userPermissions.download) { if (isTutor(user)) return; // 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. * * @param user {@link UserInfo} instance representing the user in question */ public static void canCreateLectureOrFail(UserInfo user) throws TAuthorizationException { if (!isTutor(user)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to create new lecture"); } /** * Checks whether the given user can edit the permission list of the image * identified by the given image base id. * * @param user * @param imageBaseId * @return * @throws TInvocationException * @throws TNotFoundException */ public static boolean canEditImagePermissions(UserInfo user, String imageBaseId) throws TInvocationException, TNotFoundException { ImageSummaryRead image = getImageFromBaseId(user, imageBaseId); return image.userPermissions.admin; } /** * 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 TInvocationException * @throws TNotFoundException * @throws TAuthorizationException if permission is not granted. */ public static void canEditImagePermissionsOrFail(UserInfo user, String imageBaseId) throws TAuthorizationException, TInvocationException, TNotFoundException { if (!canEditImagePermissions(user, imageBaseId)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to edit this image's permissions"); } public static void canChangeImageOwnerOrFail(UserInfo user, String imageBaseId) throws TAuthorizationException, TInvocationException, 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 ImageSummaryRead image = getImageFromBaseId(user, imageBaseId); if (!image.userPermissions.admin) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to change image owner"); } } public static void canEditLectureOrFail(UserInfo user, String lectureId) throws TInvocationException, TNotFoundException, TAuthorizationException { canEditLectureOrFail(user, getLectureFromId(user, lectureId)); } public static void canEditLectureOrFail(UserInfo user, LectureSummary lecture) throws TAuthorizationException { if (!lecture.userPermissions.edit) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to edit this image"); } } public static boolean canEditLecturePermissions(UserInfo user, String lectureId) throws TNotFoundException, TInvocationException { LectureSummary lecture = getLectureFromId(user, lectureId); return lecture.userPermissions.admin; } public static void canEditLecturePermissionsOrFail(UserInfo user, String lectureId) throws TAuthorizationException, TNotFoundException, TInvocationException { if (!canEditLecturePermissions(user, lectureId)) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to edit permissions"); } } public static void canChangeLectureOwnerOrFail(UserInfo user, LectureSummary lecture) throws TAuthorizationException, TNotFoundException, TInvocationException { // 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 (!lecture.userPermissions.admin) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to change lecture owner"); } } public static void canLinkToImageOrFail(UserInfo user, String imageVersionId) throws TNotFoundException, TInvocationException, TAuthorizationException { if (imageVersionId == null) return; ImageSummaryRead image = getImageFromVersionId(user, imageVersionId); if (!image.userPermissions.link) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to link to this image"); } } public static boolean canListImages(UserInfo user) throws TAuthorizationException { return isTutor(user); } public static void canListImagesOrFail(UserInfo user) throws TAuthorizationException { if (!canListImages(user)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to see list of images"); } public static void canSeeImageDetailsOrFail(UserInfo user) throws TAuthorizationException { if (!isTutor(user)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to see image details"); } public static void canSeeLectureDetailsOrFail(UserInfo user) throws TAuthorizationException { if (!isTutor(user)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to see lecture details"); } public static void canDeleteLectureOrFail(UserInfo user, String lectureId) throws TAuthorizationException, TInvocationException, TNotFoundException { LectureSummary lecture = getLectureFromId(user, lectureId); if (!lecture.userPermissions.admin) { throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "No permission to delete this lecture"); } } public static void canChangeImageExpireDateOrFail(UserInfo user) throws TAuthorizationException { if (!isSuperUser(user)) throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "Only the super user can change the expire date of images"); } public static void canUploadToMasterOrFail(UserInfo user, ImageSummaryRead imgBase) throws TAuthorizationException { if (isSuperUser(user)) return; if (imgBase.userPermissions.admin) return; throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "You need to be image admin to upload to master server"); } public static void canTriggerReplicationOrFail(UserInfo user, String imageVersionId) throws TAuthorizationException, TInvocationException { if (isTutor(user)) { ImageSummaryRead image; try { image = getImageFromVersionId(user, imageVersionId); } catch (TNotFoundException e) { // If the image is not known locally, allow replication return; } // If it's a remote image, or if the user has edit permissions, allow if (image.shareMode == ShareMode.DOWNLOAD || image.shareMode == ShareMode.FROZEN || image.userPermissions.edit) return; throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "You cannot trigger downloading an image to the satellite server that is not in replication mode"); } throw new TAuthorizationException(AuthorizationError.NO_PERMISSION, "Only tutors can trigger image replication"); } 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); } 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; } lecture.userPermissions = Sanitizer.handleLecturePermissions(lecture.userPermissions); } public static void setCombinedUserPermissions(LectureSummary 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; } lecture.userPermissions = Sanitizer.handleLecturePermissions(lecture.userPermissions); } 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; } } else { userPerms = Sanitizer.handleImagePermissions(userPerms); } return userPerms; } 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, TInvocationException { try { return DbImage.getImageSummary(user, imageBaseId); } catch (SQLException e) { throw new TInvocationException(); } } private static ImageSummaryRead getImageFromVersionId(UserInfo user, String imageVersionId) throws TNotFoundException, TInvocationException { try { return DbImage.getImageSummary(user, DbImage.getBaseIdForVersionId(imageVersionId)); } catch (SQLException e) { throw new TInvocationException(); } } private static LectureSummary getLectureFromId(UserInfo user, String lectureId) throws TNotFoundException, TInvocationException { try { return DbLecture.getLectureSummary(user, lectureId); } catch (SQLException e) { throw new TInvocationException(); } } }