package org.openslx.bwlp.sat.thrift;
import java.nio.ByteBuffer;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.openslx.bwlp.sat.database.Paginator;
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;
import org.openslx.bwlp.sat.permissions.User;
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.AuthorizationError;
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;
import org.openslx.bwlp.thrift.iface.ImageVersionWrite;
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.LectureWrite;
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.ShareMode;
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;
import org.openslx.bwlp.thrift.iface.TTransferRejectedException;
import org.openslx.bwlp.thrift.iface.TransferInformation;
import org.openslx.bwlp.thrift.iface.TransferStatus;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.bwlp.thrift.iface.Virtualizer;
import org.openslx.sat.thrift.version.Version;
public class ServerHandler implements SatelliteServer.Iface {
private static final Logger LOGGER = Logger.getLogger(ServerHandler.class);
private static final FileServer fileServer = FileServer.instance();
@Override
public long getVersion() {
return Version.VERSION;
}
@Override
public int getPageSize() throws TException {
return Paginator.PER_PAGE;
}
/*
* File Transfer
*/
@Override
public TransferInformation requestImageVersionUpload(String userToken, String imageBaseId, long fileSize,
List<ByteBuffer> blockHashes) throws TTransferRejectedException, TAuthorizationException,
TInternalServerError, TNotFoundException {
UserInfo user = SessionManager.getOrFail(userToken);
User.canEditBaseImageOrFail(user, imageBaseId);
String transferId = fileServer.createNewUserUpload(user, fileSize, blockHashes);
return new TransferInformation(transferId, fileServer.getPlainPort(), fileServer.getSslPort());
}
@Override
public void cancelUpload(String uploadToken) {
ActiveUpload upload = fileServer.getUploadByToken(uploadToken);
if (upload != null)
upload.cancel();
}
@Override
public TransferStatus queryUploadStatus(String uploadToken) throws TInvalidTokenException {
// TODO Auto-generated method stub
return null;
}
@Override
public TransferInformation requestDownload(String userToken, String imageVersionId)
throws TAuthorizationException {
// TODO Auto-generated method stub
return null;
}
@Override
public void cancelDownload(String downloadToken) {
// TODO Auto-generated method stub
}
/*
* Authentication/Validation
*/
@Override
public void isAuthenticated(String userToken) throws TAuthorizationException, TInternalServerError {
SessionManager.ensureAuthenticated(userToken);
}
@Override
public void invalidateSession(String userToken) {
SessionManager.remove(userToken);
}
/*
* Query basic information which doesn't require authentication
*/
@Override
public List<OperatingSystem> getOperatingSystems() {
return OperatingSystemList.get();
}
@Override
public List<Virtualizer> getVirtualizers() {
return VirtualizerList.get();
}
@Override
public List<Organization> getAllOrganizations() {
return OrganizationList.get();
}
/*
* Everything below required at least a valid session
*/
@Override
public List<ImageSummaryRead> getImageList(String userToken, List<String> tagSearch, int page)
throws TAuthorizationException, TInternalServerError {
//UserInfo user = SessionManager.getOrFail(userToken);
//User.canListImagesOrFail(user);
UserInfo user = new UserInfo("bla", "bla", "bla", "bla", "bla");
try {
return DbImage.getAllVisible(user, tagSearch, page);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public ImageDetailsRead getImageDetails(String userToken, String imageBaseId)
throws TAuthorizationException, TNotFoundException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canSeeImageDetailsOrFail(user);
try {
return DbImage.getImageDetails(user, imageBaseId);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public String createImage(String userToken, String imageName) throws TAuthorizationException,
TImageDataException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canCreateImageOrFail(user);
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 void updateImageBase(String userToken, String imageBaseId, ImageBaseWrite newData)
throws TAuthorizationException, TInternalServerError, TNotFoundException, TImageDataException {
UserInfo user = SessionManager.getOrFail(userToken);
User.canEditBaseImageOrFail(user, imageBaseId);
// Check image name for invalid characters
if (!Util.isPrintable(newData.imageName) || Util.isEmptyString(newData.imageName))
throw new TImageDataException(ImageDataError.INVALID_DATA, "Invalid or empty name");
// Check if image is marked for replication. If so, only allow changing the syncmode to FROZEN/DOWNLOAD
try {
ImageSummaryRead imageSummary = DbImage.getImageSummary(user, imageBaseId);
if (imageSummary.shareMode == ShareMode.DOWNLOAD || imageSummary.shareMode == ShareMode.FROZEN) {
if (newData.shareMode != ShareMode.DOWNLOAD && newData.shareMode != ShareMode.FROZEN) {
throw new TImageDataException(ImageDataError.INVALID_SHARE_MODE,
"Cannot change share mode from remote to local");
} else {
// Share mode is valid and changed, but ignore all other fields
DbImage.setShareMode(imageBaseId, newData);
return;
}
} else {
// Likewise, if share mode is local or publish, don't allow changing to FROZEN/DOWNLOAD
if (newData.shareMode != ShareMode.LOCAL && newData.shareMode != ShareMode.PUBLISH) {
throw new TImageDataException(ImageDataError.INVALID_SHARE_MODE,
"Cannot change share mode from local to remote");
}
}
// 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.
DbImage.updateImageMetadata(user, imageBaseId, newData);
} catch (SQLException e1) {
throw new TInternalServerError();
}
}
@Override
public void updateImageVersion(String userToken, String imageVersionId, ImageVersionWrite image)
throws TAuthorizationException, TInternalServerError, TNotFoundException {
UserInfo user = SessionManager.getOrFail(userToken);
User.canEditImageVersionOrFail(user, imageVersionId);
try {
// Do not allow editing remote images
ImageSummaryRead imageSummary = DbImage.getImageSummary(user,
DbImage.getBaseIdForVersionId(imageVersionId));
if (imageSummary.shareMode == ShareMode.DOWNLOAD || imageSummary.shareMode == ShareMode.FROZEN) {
throw new TAuthorizationException(AuthorizationError.NO_PERMISSION,
"Cannot edit image coming from master server");
}
DbImage.updateImageVersion(user, imageVersionId, image);
} catch (SQLException e1) {
throw new TInternalServerError();
}
}
@Override
public void deleteImageVersion(String userToken, String imageVersionId) throws TAuthorizationException,
TNotFoundException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canDeleteImageVersionOrFail(user, imageVersionId);
try {
// Do not allow deleting remote images if share mode is set to "auto download" and
// the version to delete is the latest
ImageSummaryRead imageSummary = DbImage.getImageSummary(user,
DbImage.getBaseIdForVersionId(imageVersionId));
if (imageSummary.shareMode == ShareMode.DOWNLOAD
&& imageSummary.latestVersionId.equals(imageVersionId)) {
throw new TAuthorizationException(AuthorizationError.NO_PERMISSION,
"Cannot delete latest version of image if auto-download is enabled");
}
DbImage.markForDeletion(imageVersionId);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public void writeImagePermissions(String userToken, String imageBaseId,
Map<String, ImagePermissions> permissions) throws TAuthorizationException, TNotFoundException,
TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canEditImagePermissionsOrFail(user, imageBaseId);
try {
DbImagePermissions.writeForImageBase(imageBaseId, permissions);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public Map<String, ImagePermissions> getImagePermissions(String userToken, String imageBaseId)
throws TAuthorizationException, TNotFoundException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
boolean adminOnly = !User.canEditImagePermissions(user, imageBaseId);
try {
return DbImagePermissions.getForImageBase(imageBaseId, adminOnly);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public void setImageOwner(String userToken, String imageBaseId, String newOwnerId)
throws TAuthorizationException, TNotFoundException, TInternalServerError, TException {
UserInfo user = SessionManager.getOrFail(userToken);
User.canChangeImageOwnerOrFail(user, imageBaseId);
try {
ImageSummaryRead imageSummary = DbImage.getImageSummary(user, imageBaseId);
if (imageSummary.shareMode == ShareMode.DOWNLOAD || imageSummary.shareMode == ShareMode.FROZEN) {
throw new TAuthorizationException(AuthorizationError.NO_PERMISSION,
"Cannot change owner of image that gets downloaded from master server");
}
DbImage.setImageOwner(imageBaseId, newOwnerId);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
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.canEditLectureOrFail(user, lectureId);
try {
DbLecture.update(user, lectureId, lecture);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public List<LectureSummary> getLectureList(String userToken, int page) throws TAuthorizationException,
TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
try {
// If user is student, getAll() will only return lectures where the current linked image is not restricted
return DbLecture.getAll(user, page);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public LectureRead getLectureDetails(String userToken, String lectureId) throws TAuthorizationException,
TNotFoundException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canSeeLectureDetailsOrFail(user);
try {
return DbLecture.getLectureDetails(user, lectureId);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public void deleteLecture(String userToken, String lectureId) throws TAuthorizationException,
TNotFoundException, TInternalServerError {
UserInfo user = SessionManager.getOrFail(userToken);
User.canDeleteLectureOrFail(user, lectureId);
try {
if (!DbLecture.delete(lectureId))
throw new TNotFoundException();
} catch (SQLException e) {
throw new TInternalServerError();
}
}
@Override
public void writeLecturePermissions(String userToken, String lectureId,
Map<String, LecturePermissions> permissions) throws TAuthorizationException, TNotFoundException {
// TODO Auto-generated method stub
}
@Override
public Map<String, LecturePermissions> getLecturePermissions(String userToken, String lectureId)
throws TAuthorizationException, TNotFoundException {
// TODO Auto-generated method stub
return null;
}
@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 {
return DbUser.getAll(page);
} catch (SQLException e) {
throw new TInternalServerError();
}
}
}