diff --git a/CHANGELOG b/CHANGELOG index 0353684bfe1d6a4ed25b2903eb66171d15d055d4..f36d27f5dbf1012e9f8f2f899f02f26fd9e0f556 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,33 @@ +minerva (14.0.0~beta.2) unstable; urgency=low + * Small improvement: info window contains information about overlay No (#919) + * Small improvement: curator without write access to project has info about + it when editing project (#940) + * Small improvement: when revoking view access to project, revoke + automatically write access to it (#920) + * Bug fix: exported SBML passes online validation (#831) + * Bug fix: changing owner of data overlay should change order index (#945) + * Bug fix: allow user to remove own comments (#931) + * Bug fix: validation of project name length is provided (#950) + * Bug fix: after reducing privileges on himself interface is refreshed (#948) + * Bug fix: list of "Copy from" elements in "Select valid annotations" dialog + is shortened to used bio entity typrd (#911) + * Bug fix: removing overlays as curator in admin panel fixed (#944) + * Bug fix: information about deprecated column is more clear about column + names (#838) + * Bug fix: version of the project is limited to 20 characters (#951) + * Bug fix: link to comment on map from admin panel was broken (#941) + * Bug fix: hide glyphs tab when necessary (#949) + * Bug fix: user with write access but without can_create_privileges cannot + create data overlay (#939) + * Bug fix: export to CD could misalign reaction lines that were imported from + format that didn't require reaction line to be attached to the species (#933) + * Bug fix: problem with migration of default privileges (#902) + * Bug fix: some project privileges were not migrated properly (#902) + * Bug fix: problem with uploading data_overlays with type included in header + (#936) + + -- Piotr Gawron Mon, 18 Sep 2019 19:00:00 +0200 + minerva (14.0.0~beta.1) unstable; urgency=low * Bug fix: problem with changing user role (#932) diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXml.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXml.java index 543b16a5bd33771872fa62f07070c3b89683153e..c871cbb767b4bfaa5974e6d8b19ef5bf2eb15152 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXml.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXml.java @@ -963,6 +963,7 @@ public class ReactionToXml { String getEditPointsXmlStringForSimpleReaction(Reaction reaction) { Product product = reaction.getProducts().get(0); Reactant reactant = reaction.getReactants().get(0); + List points = new ArrayList<>(); for (int i = 0; i < reactant.getLine().getPoints().size() - 1; i++) { points.add(reactant.getLine().getPoints().get(i)); @@ -986,9 +987,18 @@ public class ReactionToXml { } PolylineData pd = new PolylineData(points); + pd.setPoint(0, getAnchorPoint(reactant.getElement(), reactant.getLine().getBeginPoint())); + pd.setPoint(pd.getPoints().size() - 1, getAnchorPoint(product.getElement(), productLine.getEndPoint())); return getEditPointsXmlStringForLine(new PolylineData[] { pd }, centerPosition); } + private Point2D getAnchorPoint(Element element, Point2D originalPoint) { + CellDesignerAliasConverter converter = new CellDesignerAliasConverter(element, sbgn); + + CellDesignerAnchor anchor = converter.getAnchorForCoordinates(element, originalPoint); + return converter.getPointCoordinates(element, anchor); + } + /** * Creates valid xml node with connectScheme for the reaction. * diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java index 790087f132bb3b363cc2967e171a272cf9604964..d55b3d967e56949cbe20148c8ef0837b30cf6a27 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java @@ -230,7 +230,7 @@ public abstract class CellDesignerTestFunctions { throws InconsistentModelException, UnsupportedEncodingException, InvalidInputDataExecption { CellDesignerXmlParser parser = new CellDesignerXmlParser(); String xmlString = parser.model2String(model); - logger.debug(xmlString); +// logger.debug(xmlString); InputStream is = new ByteArrayInputStream(xmlString.getBytes("UTF-8")); Model model2 = parser.createModel(new ConverterParams().inputStream(is).sizeAutoAdjust(false)); diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java index 63e4b455a0a561f7c89f7ae388ae6246bbb331e0..be028cc32e0977ae977f16aad1ebfd2acd24f4cc 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java @@ -799,5 +799,56 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions { assertEquals("Whole reaction should use the same reaction type", 1, reactionTypes.size()); } + @Test + public void testExportReactoinWithLinesNotAttachedToSpecies() throws Exception { + Model model = new ModelFullIndexed(null); + model.setIdModel("as"); + model.setWidth(1000); + model.setHeight(1000); + + Species protein = new SimpleMolecule("id1"); + protein.setX(383); + protein.setY(584); + protein.setWidth(140); + protein.setHeight(60); + model.addElement(protein); + + Species protein2 = new SimpleMolecule("id2"); + protein2.setX(351); + protein2.setY(697); + protein2.setWidth(100); + protein2.setHeight(60); + model.addElement(protein2); + + Reaction reaction = new StateTransitionReaction(); + reaction.setIdReaction("re1"); + reaction.setLine(new PolylineData(new Point2D.Double(401.0, 673.0), new Point2D.Double(401.0, 673.0))); + + Reactant reactant = new Reactant(protein); + reactant.setLine(new PolylineData(Arrays.asList( + new Point2D.Double(420.0, 644.0), + new Point2D.Double(420.0, 654.0), + new Point2D.Double(401.0, 654.0), + new Point2D.Double(401.0, 665.0)))); + reaction.addReactant(reactant); + model.addReaction(reaction); + + Product product = new Product(protein2); + product.setLine(new PolylineData(new Point2D.Double(401.0, 673.0), new Point2D.Double(401.0, 697.0))); + reaction.addProduct(product); + + Model model2 = serializeModel(model); + + Reaction reaction2 = model2.getReactionByReactionId("re1"); + + Reactant newReactant = reaction2.getReactants().get(0); + + // center part of the line shouldn't change - edges should be aligned to touch + // species + assertEquals(0, newReactant.getLine().getPoints().get(1).distance(reactant.getLine().getPoints().get(1)), + Configuration.EPSILON); + assertEquals(0, newReactant.getLine().getPoints().get(2).distance(reactant.getLine().getPoints().get(2)), + Configuration.EPSILON); + } } diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXmlTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXmlTest.java index 3b13bce3e6901607d6a2692c79a98ecb285104ce..a1fddefcdbb319a12f02d971584798e1cbe061ba 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXmlTest.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/reaction/ReactionToXmlTest.java @@ -47,6 +47,9 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { Model model = new ModelFullIndexed(null); Species protein1 = new GenericProtein("2"); Species protein2 = new GenericProtein("3"); + protein2.setX(100); + protein2.setY(100); + Species protein3 = new GenericProtein("4"); model.addElement(protein1); model.addElement(protein2); @@ -61,10 +64,10 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { reaction.addReactant(reactant); reaction.addProduct(product); - Modifier modifier = new Catalysis(protein1); + Modifier modifier = new Catalysis(protein3); modifier.setLine(new PolylineData(new Point2D.Double(), new Point2D.Double(30, 0))); - Modifier modifier2 = new Catalysis(protein1); + Modifier modifier2 = new Catalysis(protein3); List points = new ArrayList<>(); points.add(new Point2D.Double(0, 0)); points.add(new Point2D.Double(30, 30)); @@ -101,6 +104,7 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { Model model = new ModelFullIndexed(null); Species protein1 = new GenericProtein("2"); + protein1.setX(100); Species protein2 = new GenericProtein("3"); model.addElement(protein1); @@ -249,10 +253,18 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { @Test public void testGetEditPointsXmlStringForSimpleReaction() { Reaction r = new TriggerReaction(); - Product product = new Product(); + Species productSpecies = new GenericProtein("id1"); + productSpecies.setX(20); + productSpecies.setY(20); + productSpecies.setWidth(20); + productSpecies.setHeight(20); + Product product = new Product(productSpecies); PolylineData productLine = new PolylineData(new Point2D.Double(10, 10), new Point2D.Double(20, 20)); product.setLine(productLine); - Reactant reactant = new Reactant(); + Species reactantSpecies = new GenericProtein("id1"); + reactantSpecies.setWidth(10); + reactantSpecies.setHeight(10); + Reactant reactant = new Reactant(reactantSpecies); PolylineData reactantLine = new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 10)); reactant.setLine(reactantLine); r.addProduct(product); @@ -264,10 +276,18 @@ public class ReactionToXmlTest extends CellDesignerTestFunctions { @Test public void testGetEditPointsXmlStringForSimpleReactionWhenNotImportedFromCD() { Reaction r = new TriggerReaction(); - Product product = new Product(); + Species productSpecies = new GenericProtein("id1"); + productSpecies.setX(20); + productSpecies.setY(20); + productSpecies.setWidth(20); + productSpecies.setHeight(20); + Product product = new Product(productSpecies); PolylineData productLine = new PolylineData(new Point2D.Double(10, 10), new Point2D.Double(20, 10)); product.setLine(productLine); - Reactant reactant = new Reactant(); + Species reactantSpecies = new GenericProtein("id1"); + reactantSpecies.setWidth(10); + reactantSpecies.setHeight(10); + Reactant reactant = new Reactant(reactantSpecies); PolylineData reactantLine = new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 10)); reactant.setLine(reactantLine); r.addProduct(product); diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java index 4bf203532dbe74413bec5d4d06f29d0be383bcfc..d4184cb7b4e211f4b6370c32635b14e4976af7a3 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/reaction/SbmlReactionExporter.java @@ -1,16 +1,15 @@ package lcsb.mapviewer.converter.model.sbml.reaction; -import java.awt.*; +import java.awt.BasicStroke; +import java.awt.Stroke; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.util.*; -import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.sbml.jsbml.*; import org.sbml.jsbml.ext.layout.*; -import org.sbml.jsbml.ext.layout.Point; import org.sbml.jsbml.ext.render.*; import org.w3c.dom.Node; @@ -237,13 +236,45 @@ public class SbmlReactionExporter extends SbmlBioEntityExporter data() throws IOException { + List result = new ArrayList<>(); + result.add(new Object[] { "testFiles/small/empty.xml" }); + result.add(new Object[] { "testFiles/small/reaction/dissociation.xml" }); + return result; + } + + @Test + public void testIsValidSbml() throws Exception { + SbmlParser parser = new SbmlParser(); + Model model = parser.createModel(new ConverterParams().filename(filename)); + String xml = parser.model2String(model); + + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpPost uploadFile = new HttpPost("http://sbml.org/validator/"); + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addTextBody("file", xml, ContentType.TEXT_PLAIN); + builder.addBinaryBody( + "file", + new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_OCTET_STREAM, + filename); + builder.addTextBody("output", "xml", ContentType.TEXT_PLAIN); + builder.addTextBody("offcheck", "u,r", ContentType.TEXT_PLAIN); + + HttpEntity multipart = builder.build(); + uploadFile.setEntity(multipart); + CloseableHttpResponse response = httpClient.execute(uploadFile); + String responseXml = EntityUtils.toString(response.getEntity()); + Document document = XmlParser.getXmlDocumentFromString(responseXml); + List problems = XmlParser.getAllNotNecessirellyDirectChild("problem", document); + if (problems.size() > 0) { + logger.debug(responseXml); + } + assertEquals("SBML is invalid", 0, problems.size()); + } + +} diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index 0e991151fde07fc8cd9c727dd0d32cceaceb7092..1b12de302ae132964e2af3891b85d1bef918a410 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -1333,7 +1333,7 @@ ServerConnector.getProjectStatistics = function (projectId) { /** * - * @returns {Promise} + * @returns {Promise|PromiseLike} */ ServerConnector.getLoggedUser = function () { var self = this; @@ -2524,7 +2524,13 @@ ServerConnector.updateModel = function (params) { return self.sendPatchRequest(self.updateModelUrl(queryParams), filterParams); }; - +/** + * + * @param {Object} params + * @param {number} params.overlayId + * @param {string} params.projectId + * @return {PromiseLike | Promise} + */ ServerConnector.removeOverlay = function (params) { var self = this; var queryParams = { diff --git a/frontend-js/src/main/js/gui/AddOverlayDialog.js b/frontend-js/src/main/js/gui/AddOverlayDialog.js index e9d20fe7b0e2115e44e38828f21b71cdff976efe..c6a5b3fbb9258593146b5869645c659ccc6e1802 100644 --- a/frontend-js/src/main/js/gui/AddOverlayDialog.js +++ b/frontend-js/src/main/js/gui/AddOverlayDialog.js @@ -164,6 +164,7 @@ AddOverlayDialog.prototype.processFile = function (file) { } if (overlay.getType() !== undefined) { + var typeSelect = $("[name='overlay-type']", self.getElement())[0]; if ($("option[value='" + overlay.getType() + "']", typeSelect).length === 0) { GuiConnector.warn("Invalid type: " + overlay.getType()); } diff --git a/frontend-js/src/main/js/gui/admin/AbstractAnnotatorsDialog.js b/frontend-js/src/main/js/gui/admin/AbstractAnnotatorsDialog.js index d13c51e0603ecd058527a61fd9412534e86dcd78..4871327e410f749c1dfdca41852bc0171e304503 100644 --- a/frontend-js/src/main/js/gui/admin/AbstractAnnotatorsDialog.js +++ b/frontend-js/src/main/js/gui/admin/AbstractAnnotatorsDialog.js @@ -51,4 +51,32 @@ AbstractAnnotatorsDialog.prototype.getAllChildrenTypesIfNeeded = function (eleme return result; }; +/** + * + * @return {BioEntityTypeTreeNode[]} + */ +AbstractAnnotatorsDialog.prototype.getTypeNodeList = function () { + var types = []; + + var treeData = this.getConfiguration().getElementTypeTree(); + + var queue = [treeData]; + + while (queue.length > 0) { + var node = queue.shift(); + if (node.children !== undefined && node.children.length > 0) { + for (var i = 0; i < node.children.length; i++) { + queue.push(node.children[i]); + } + } else { + types.push(node); + } + } + types.sort(function (a, b) { + return a.text.localeCompare(b.text); + }); + return types; +}; + + module.exports = AbstractAnnotatorsDialog; diff --git a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js index d42a9bbf7d002dc787f8fcda61a32700e4b9a719..30825be638e38ba0a1ec680b6ceac9867ab76695 100644 --- a/frontend-js/src/main/js/gui/admin/AddProjectDialog.js +++ b/frontend-js/src/main/js/gui/admin/AddProjectDialog.js @@ -1282,6 +1282,11 @@ AddProjectDialog.prototype.checkValidity = function () { isValid = false; } + var name = self.getName(); + if (name.length > 255) { + error += "
  • name must be shorter than 256 characters
  • "; + isValid = false; + } var rootExist = 0, i; for (i = 0; i < self.getZipEntries().length; i++) { @@ -1399,6 +1404,7 @@ AddProjectDialog.prototype.setZipFileContent = function (file) { guiUtils.hideTab(self, $(".minerva-project-overlays-tab", self.getElement())[0]); guiUtils.hideTab(self, $(".minerva-project-submaps-tab", self.getElement())[0]); guiUtils.hideTab(self, $(".minerva-project-overview-images-tab", self.getElement())[0]); + guiUtils.hideTab(self, $(".minerva-project-glyphs-tab", self.getElement())[0]); return self.setZipEntries([]); } }; diff --git a/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js b/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js index 320eb60e67b85d40d3a100fc62c2cb632134d55a..421a9d0c06adba04e3bbaa0cdc368fbdb23a467d 100644 --- a/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js +++ b/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js @@ -416,33 +416,6 @@ ChooseAnnotatorsDialog.prototype.createAnnotatorsParams = function (selectedAnno }; -/** - * - * @return {BioEntityTypeTreeNode[]} - */ -ChooseAnnotatorsDialog.prototype.getTypeNodeList = function () { - var types = []; - - var treeData = this.getConfiguration().getElementTypeTree(); - - var queue = [treeData]; - - while (queue.length > 0) { - var node = queue.shift(); - if (node.children !== undefined && node.children.length > 0) { - for (var i = 0; i < node.children.length; i++) { - queue.push(node.children[i]); - } - } else { - types.push(node); - } - } - types.sort(function (a, b) { - return a.text.localeCompare(b.text); - }); - return types; -}; - /** * * @returns {Promise} diff --git a/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js b/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js index 78cfe774507c3cb3d6d9f10ae7c1d45c2604b7dc..f39b87d68d3e5cc051e7006a19d5c0408b0e3713 100644 --- a/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js +++ b/frontend-js/src/main/js/gui/admin/ChooseValidatorsDialog.js @@ -21,7 +21,7 @@ var logger = require('../../logger'); * @param {Object} params * @param {HTMLElement} params.element * @param {CustomMap} params.customMap - * @param {Configuration} [params.configuration] + * @param {Configuration} params.configuration * @param {ServerConnector} [params.serverConnector] * * @constructor @@ -125,16 +125,13 @@ ChooseValidatorsDialog.prototype.setElementType = function (elementType) { var copyFromSelect = Functions.createElement({type: "select", style: "margin:5px"}); element.appendChild(copyFromSelect); var options = [], i; - for (i = 0; i < configuration.getElementTypes().length; i++) { - var type = configuration.getElementTypes()[i]; - var name = type.className; - if (name.indexOf(".") > 0) { - name = name.substr(name.lastIndexOf(".") + 1); - } + var nodeList = self.getTypeNodeList(); + for (i = 0; i < nodeList.length; i++) { + var type = nodeList[i]; options.push(Functions.createElement({ type: "option", - value: type.className, - content: name + value: type.data.className, + content: type.text })); } options.sort(function (a, b) { @@ -143,6 +140,7 @@ ChooseValidatorsDialog.prototype.setElementType = function (elementType) { for (i = 0; i < options.length; i++) { copyFromSelect.appendChild(options[i]); } + element.appendChild(includeChildrenCheckbox); element.appendChild(Functions.createElement({type: "span", content: "Apply to all in subtree"})); diff --git a/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js b/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js index 064e6297e73dc6f151556d104405c636a532b6aa..8ba536cf438220148d1fd10f4f7ed6c87fc8e045 100644 --- a/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js @@ -113,17 +113,18 @@ CommentsAdminPanel.prototype.refreshComments = function () { comments = result; return self.getServerConnector().getLoggedUser(); }).then(function (user) { + var curatorAccess = self.getConfiguration().getPrivilegeType(PrivilegeType.IS_CURATOR); var writeAccess = self.getConfiguration().getPrivilegeType(PrivilegeType.WRITE_PROJECT); - var isAdmin = self.getConfiguration().getPrivilegeType(PrivilegeType.IS_ADMIN); + var adminAccess = self.getConfiguration().getPrivilegeType(PrivilegeType.IS_ADMIN); var disable = true; - if (user.hasPrivilege(writeAccess, self.getProject().getProjectId()) || user.hasPrivilege(isAdmin)) { + if ((user.hasPrivilege(writeAccess, self.getProject().getProjectId()) && user.hasPrivilege(curatorAccess)) || user.hasPrivilege(adminAccess)) { disable = false; } var dataTable = $($("[name='commentsTable']", self.getElement())[0]).DataTable(); var data = []; for (var i = 0; i < comments.length; i++) { - data.push(self.commentToTableRow(comments[i], disable)); + data.push(self.commentToTableRow(comments[i], disable && comments[i].getAuthor() !== user.getLogin())); } dataTable.clear().rows.add(data).draw(); }); @@ -152,9 +153,9 @@ CommentsAdminPanel.prototype.commentToTableRow = function (comment, disable) { "&y=" + comment.getCoordinates().y + "&zoom=12" + "&comments=on"; - title = "" + comment.getTitle() + ""; + title = "" + xss(comment.getTitle()) + ""; } else { - title = comment.getTitle(); + title = xss(comment.getTitle()); } var disabled = ""; @@ -169,17 +170,17 @@ CommentsAdminPanel.prototype.commentToTableRow = function (comment, disable) { } var author = comment.getAuthor(); - if (author === undefined) { + if (author === undefined || author === null) { author = "N/A"; } var email = comment.getEmail(); - if (email === undefined) { + if (email === undefined || email === null) { email = "N/A"; } return [comment.getId(), - xss(title), + title, xss(author), xss(email), xss(comment.getContent()), diff --git a/frontend-js/src/main/js/gui/admin/EditProjectDialog.js b/frontend-js/src/main/js/gui/admin/EditProjectDialog.js index ce8f71f5a265ebe5d471b7effc2c313349ac5473..3097f39e91a271833cc3ec5850b0d2ca3375f7b9 100644 --- a/frontend-js/src/main/js/gui/admin/EditProjectDialog.js +++ b/frontend-js/src/main/js/gui/admin/EditProjectDialog.js @@ -34,6 +34,13 @@ var xss = require('xss'); function EditProjectDialog(params) { AbstractGuiElement.call(this, params); var self = this; + /** + * + * @type {string} + * @private + */ + self._title = self.getProject().getProjectId(); + guiUtils.setConfiguration(params.configuration); self.setConfiguration(params.configuration); $(self.getElement()).addClass("minerva-edit-project-dialog"); @@ -614,6 +621,12 @@ EditProjectDialog.prototype.createUsersTabContent = function () { } return self.grantPrivilege(self._userByLogin[login], type, self.getProject().getProjectId()); } else { + if (type === PrivilegeType.READ_PROJECT) { + var writeCheckbox = $("[data='" + PrivilegeType.WRITE_PROJECT + "," + login + "']", usersTable); + if (writeCheckbox.is(":checked")) { + writeCheckbox.click(); + } + } return self.revokePrivilege(self._userByLogin[login], type, self.getProject().getProjectId()); } }); @@ -661,7 +674,14 @@ EditProjectDialog.prototype.init = function () { self.projectDataUpdated(self.getProject()); }); return self.initUsersTab().then(function () { - return self.refresh() + return self.getServerConnector().getLoggedUser(); + }).then(function (loggedUser) { + var readOnlyAccess = loggedUser.hasPrivilege(self.getConfiguration().getPrivilegeType(PrivilegeType.IS_CURATOR)) && + !loggedUser.hasPrivilege(self.getConfiguration().getPrivilegeType(PrivilegeType.WRITE_PROJECT), self.getProject().getProjectId()); + if (readOnlyAccess) { + self._title += " (View only)"; + } + return self.refresh(); }).then(function () { $(window).trigger('resize'); }); @@ -1071,7 +1091,7 @@ EditProjectDialog.prototype.open = function () { if (!$(div).hasClass("ui-dialog-content")) { $(div).dialog({ dialogClass: 'minerva-edit-project-dialog', - title: self.getProject().getProjectId(), + title: self._title, width: window.innerWidth * 0.75, height: window.innerHeight / 2 }); @@ -1218,7 +1238,8 @@ EditProjectDialog.prototype.revokePrivilege = function (user, privilegeType, pro EditProjectDialog.prototype.removeOverlay = function (overlayId) { var self = this; return self.getServerConnector().removeOverlay({ - overlayId: overlayId + overlayId: overlayId, + projectId: self.getProject().getProjectId() }).then(function () { return self.refreshOverlays(); }); diff --git a/frontend-js/src/main/js/gui/admin/EditUserDialog.js b/frontend-js/src/main/js/gui/admin/EditUserDialog.js index f5b4dbe1faf9dde8beb404cd90282c5162209d56..0c5d2f3c74ab41e3609e2e0d0e1dc3f968129dd8 100644 --- a/frontend-js/src/main/js/gui/admin/EditUserDialog.js +++ b/frontend-js/src/main/js/gui/admin/EditUserDialog.js @@ -225,7 +225,13 @@ EditUserDialog.prototype.createGeneralTabContent = function () { } else { GuiConnector.alert("Invalid role: " + role); } - return Promise.all(promises); + return Promise.all(promises).then(function () { + return self.getServerConnector().getLoggedUser(); + }).then(function (loggedUser) { + if (loggedUser.getLogin() === self.getUser().getLogin()) { + window.location.reload(false); + } + }); } ); return result; @@ -379,36 +385,25 @@ EditUserDialog.prototype.initProjectsTab = function () { $(projectsTable).DataTable({ columns: columns }); - $(projectsTable).on("click", "[name='project-privilege-checkbox']", function () { + $(self.getElement()).on("click", "[name='project-privilege-checkbox']", function () { var data = $(this).attr("data").split(":"); var type = data[0]; var projectId = data[1]; if ($(this).is(":checked")) { if (type === PrivilegeType.WRITE_PROJECT) { - var readCheckbox = $("[data='" + PrivilegeType.READ_PROJECT + ":" + data[1] + "']", projectsTable); + var readCheckbox = $("[data='" + PrivilegeType.READ_PROJECT + ":" + data[1] + "']", self.getElement()); if (!readCheckbox.is(":checked")) { readCheckbox.click(); } } return self.grantPrivilege({privilegeType: type, objectId: projectId}); } else { - return self.revokePrivilege({privilegeType: type, objectId: projectId}); - } - }); - - $("[name='defaultProjectsRow']", self.getElement()).on("click", "[name='project-privilege-checkbox']", function () { - var data = $(this).attr("data").split(":"); - var type = data[0]; - var projectId = data[1]; - if ($(this).is(":checked")) { - if (type === PrivilegeType.WRITE_PROJECT) { - var readCheckbox = $("[data='" + PrivilegeType.READ_PROJECT + ":" + data[1] + "']", self.getElement()); - if (!readCheckbox.is(":checked")) { - readCheckbox.click(); + if (type === PrivilegeType.READ_PROJECT) { + var writeCheckbox = $("[data='" + PrivilegeType.WRITE_PROJECT + ":" + data[1] + "']", self.getElement()); + if (writeCheckbox.is(":checked")) { + writeCheckbox.click(); } } - return self.grantPrivilege({privilegeType: type, objectId: projectId}); - } else { return self.revokePrivilege({privilegeType: type, objectId: projectId}); } }); diff --git a/frontend-js/src/main/js/map/data/Comment.js b/frontend-js/src/main/js/map/data/Comment.js index 78c6e950a557af1fc83406cef79d623b7ecc2abd..9f1aa4885ca7e7ebd94aaf0d2cac432e84060729 100644 --- a/frontend-js/src/main/js/map/data/Comment.js +++ b/frontend-js/src/main/js/map/data/Comment.js @@ -25,7 +25,7 @@ function Comment(javaObject) { this.setTitle(javaObject.title); this.setContent(javaObject.content); } - this.setAuthor(javaObject.author); + this.setAuthor(javaObject.owner); this.setEmail(javaObject.email); } diff --git a/frontend-js/src/main/js/map/window/AliasInfoWindow.js b/frontend-js/src/main/js/map/window/AliasInfoWindow.js index 526b21560962149f8129fd22c82916204413b2c4..b4ba0dfea85f37974a277d442891615c933de1e7 100644 --- a/frontend-js/src/main/js/map/window/AliasInfoWindow.js +++ b/frontend-js/src/main/js/map/window/AliasInfoWindow.js @@ -126,6 +126,7 @@ AliasInfoWindow.prototype.createChartDiv = function (params) { if (name.length > 20) { name = name.substr(0, 20) + "..."; } + name = "[" + overlays[i].getOrder() + "] " + name; var nameDiv = document.createElement("div"); nameDiv.className = "minerva-chart-name"; nameDiv.innerHTML = name + " "; diff --git a/frontend-js/src/test/js/gui/AddOverlayDialog-test.js b/frontend-js/src/test/js/gui/AddOverlayDialog-test.js index 5ee5b21065af10119bda8e5ffa10f7dc1edaca6c..1618a2b1c81f39e94bca3205e2b422c02c0b7616 100644 --- a/frontend-js/src/test/js/gui/AddOverlayDialog-test.js +++ b/frontend-js/src/test/js/gui/AddOverlayDialog-test.js @@ -76,6 +76,19 @@ describe('AddOverlayDialog', function () { assert.equal("GENERIC", dialog.getType()); }); }); + it('set type from header', function () { + var dialog; + return ServerConnector.getProject().then(function (project) { + dialog = createDialog(project); + return dialog.init(); + }).then(function () { + return helper.stringToBlob("#TYPE=GENETIC_VARIANT\ns1\n"); + }).then(function (file) { + return dialog.processFile(file); + }).then(function () { + assert.equal("GENETIC_VARIANT", dialog.getType()); + }); + }); }); diff --git a/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js b/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js index 4cc65485bd1e0e3c4247bb4c357ce596a6df1bf0..5951de0fa32789f9da3926b1d2f17b5a8c121091 100644 --- a/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js +++ b/frontend-js/src/test/js/gui/admin/AddProjectDialog-test.js @@ -156,6 +156,20 @@ describe('AddProjectDialog', function () { return dialog.destroy(); }); }); + it('glyphs', function () { + var dialog = createDialog(); + var buf = fs.readFileSync("testFiles/map/complex_model_with_glyphs.zip"); + buf.name = "complex_model_with_glyphs.zip"; + return dialog.init().then(function () { + var dataTable = $($("[name='glyphsTable']", testDiv)[0]).DataTable(); + assert.equal(0, dataTable.data().count()); + return dialog.setZipFileContent(buf); + }).then(function () { + var dataTable = $($("[name='glyphsTable']", testDiv)[0]).DataTable(); + assert.ok(dataTable.data().count() > 0); + return dialog.destroy(); + }); + }); }); describe('showAnnotatorsDialog', function () { diff --git a/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js b/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js index d9c985baf8423f2c4048293d37351c77043678d5..947487387f7df273d92dcbf0324076dc19204ac3 100644 --- a/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js +++ b/frontend-js/src/test/js/gui/admin/ChooseValidatorsDialog-test.js @@ -11,34 +11,31 @@ var Promise = require('bluebird'); var chai = require('chai'); var assert = chai.assert; +function createDialog() { + return new ChooseValidatorsDialog({ + element: testDiv, + customMap: null, + serverConnector: ServerConnector, + configuration: helper.getConfiguration() + }); +} + describe('ChooseValidatorsDialog', function () { it('init', function () { - var dialog = new ChooseValidatorsDialog({ - element: testDiv, - customMap: null, - serverConnector: ServerConnector - }); + var dialog = createDialog(); assert.equal(0, logger.getWarnings().length); return dialog.init(); }); it('setElementType', function () { - var dialog = new ChooseValidatorsDialog({ - element: testDiv, - customMap: null, - serverConnector: ServerConnector - }); + var dialog = createDialog(); return ServerConnector.getConfiguration().then(function (configuration) { return dialog.setElementType(configuration.getReactionTypes()[0]); }) }); it('open', function () { - var dialog = new ChooseValidatorsDialog({ - element: testDiv, - customMap: null, - serverConnector: ServerConnector - }); + var dialog = createDialog(); return dialog.init().then(function () { return dialog.open(); }).then(function () { @@ -52,11 +49,7 @@ describe('ChooseValidatorsDialog', function () { helper.loginAsAdmin(); var originalFunction = ServerConnector.updateUserPreferences; var functionCalled = false; - var dialog = new ChooseValidatorsDialog({ - element: testDiv, - customMap: null, - serverConnector: ServerConnector - }); + var dialog = createDialog(); return dialog.init().then(function () { return dialog.open(); }).then(function () { diff --git a/frontend-js/testFiles/map/complex_model_with_glyphs.zip b/frontend-js/testFiles/map/complex_model_with_glyphs.zip new file mode 100644 index 0000000000000000000000000000000000000000..089b4d20d98443c03ba01edd432ebe761b6c6d2c Binary files /dev/null and b/frontend-js/testFiles/map/complex_model_with_glyphs.zip differ diff --git a/persist/src/main/resources/db/migration/14.0.0~alpha.0/V14.0.0.20190618__new_permission_model.sql b/persist/src/main/resources/db/migration/14.0.0~alpha.0/V14.0.0.20190618__new_permission_model.sql index 37b6f26808c5cd97ce09a1cb465c049a92a5919a..40e2f4a800f3fa321fae9a22a32dabfc550571ec 100644 --- a/persist/src/main/resources/db/migration/14.0.0~alpha.0/V14.0.0.20190618__new_permission_model.sql +++ b/persist/src/main/resources/db/migration/14.0.0~alpha.0/V14.0.0.20190618__new_permission_model.sql @@ -23,6 +23,13 @@ insert into privilege_table (type, object_id) select 'WRITE_PROJECT', id from project_table; +--defaults for project +insert into privilege_table (type, object_id) +values ('WRITE_PROJECT', null); + +insert into privilege_table (type, object_id) +values ('READ_PROJECT', null); + create table user_privilege_map_table ( user_id integer not null references user_table(id), privilege_id integer not null references privilege_table(id) @@ -34,6 +41,18 @@ from (select user_id, object_id from privilege_table where type = 'VIEW_PROJECT' inner join (select id, object_id from privilege_table where type = 'READ_PROJECT') s2 on s1.object_id = s2.object_id; +--default read +insert into user_privilege_map_table (user_id, privilege_id) +select s1.user_id, s2.id +from (select user_id from privilege_table where type = 'VIEW_PROJECT' and object_id is null) s1, +(select id from privilege_table where type = 'READ_PROJECT' and object_id is null) s2; + +--default write +insert into user_privilege_map_table (user_id, privilege_id) +select s1.user_id, s2.id +from (select distinct(user_id) from privilege_table where (type = 'EDIT_COMMENTS_PROJECT' or type = 'LAYOUT_MANAGEMENT') and object_id is null) s1, +(select id from privilege_table where type = 'WRITE_PROJECT' and object_id is null) s2; + insert into user_privilege_map_table (user_id, privilege_id) select s1.user_id, s2.id from (select user_id, object_id from privilege_table where type = 'EDIT_COMMENTS_PROJECT' or type = 'LAYOUT_MANAGEMENT') s1 @@ -71,7 +90,7 @@ delete from privilege_table where type = 'VIEW_PROJECT' or type = 'MANAGE_PLUGINS'; delete from user_privilege_map_table t1 using user_privilege_map_table t2 -where t1.CTID != t2.CTID +where t1.CTID < t2.CTID and t1.user_id = t2.user_id and t1.privilege_id = t2.privilege_id; @@ -87,3 +106,6 @@ alter table privilege_table alter column object_id type varchar; -- change id to project_id for project prvileges update privilege_table set object_id = (select project_id from project_table where id::text = object_id) where object_id is not null; + +-- default privileges are marked with '*' project id +update privilege_table set object_id = '*' where object_id is null and type like '%PROJECT%'; \ No newline at end of file diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertRestImpl.java index d763144b8709c1202ab0e5542aa09581406c5045..6e42cc705f643865e6eb67f7e82e144ec49c15e9 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertRestImpl.java @@ -51,9 +51,12 @@ public class ConvertRestImpl extends BaseRestImpl { } public ByteArrayOutputStream converToImage(String fromFormat, String toFormat, String input) - throws InvalidInputDataExecption, SBMLException, IOException, ConverterException, DrawingException, - QueryException { - return converToImage(fromFormat, toFormat, input, 0.0, 0.0); + throws IOException, DrawingException, QueryException { + try { + return converToImage(fromFormat, toFormat, input, 0.0, 0.0); + } catch (InvalidInputDataExecption | ConverterException e) { + throw new QueryException("Input file is invalid", e); + } } public Map getInformation() { diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java index 2990615b2963492ee851b07eac4f8bfad9e82cda..7bfcf86676e664f94188e7ddd4c9bedd536dbe86 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java @@ -261,14 +261,13 @@ public class ProjectRestImpl extends BaseRestImpl { stringValue = (String) value; } if (fieldName.equalsIgnoreCase("version")) { + if (value != null && ((String) value).length() > 20) { + throw new QueryException("version is too long (>20 characters)"); + } project.setVersion((String) value); } else if (fieldName.equalsIgnoreCase("id")) { - try { - int id = Integer.parseInt(stringValue); - if (id != project.getId()) { - throw new QueryException("Invalid id: " + stringValue); - } - } catch (NumberFormatException e) { + int id = parseInteger(stringValue, "id"); + if (id != project.getId()) { throw new QueryException("Invalid id: " + stringValue); } } else if (fieldName.equalsIgnoreCase("projectId")) { @@ -276,6 +275,9 @@ public class ProjectRestImpl extends BaseRestImpl { throw new QueryException("You cannot modify projectId"); } } else if (fieldName.equalsIgnoreCase("name")) { + if (value != null && ((String) value).length() > 255) { + throw new QueryException("name is too long (>255 characters)"); + } project.setName((String) value); } else if (fieldName.equalsIgnoreCase("notifyEmail")) { project.setNotifyEmail(stringValue); @@ -377,10 +379,16 @@ public class ProjectRestImpl extends BaseRestImpl { params.projectFile(file); params.projectId(projectId); params.projectName(getFirstValue(data.get("name"))); + if (params.getProjectName() != null && params.getProjectName().length() > 255) { + throw new QueryException("name is too long"); + } params.projectOrganism(getFirstValue(data.get("organism"))); params.sbgnFormat(getFirstValue(data.get("sbgn"))); params.semanticZoomContainsMultipleLayouts(getFirstValue(data.get("semantic-zoom-contains-multiple-layouts"))); params.version(getFirstValue(data.get("version"))); + if (params.getVersion() != null && params.getVersion().length() > 20) { + throw new QueryException("version is too long (>20 characters)"); + } params.annotations(getFirstValue(data.get("annotate"))); params.setUser(user); MapCanvasType mapCanvasType; diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java index a39ed1b5687428b41c12a8cc8c801d523c5dffb6..7cfd280fc1d4f4f8f510f2ee985f8fad9a6b1c0d 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java @@ -37,7 +37,8 @@ public class OverlayController extends BaseController { public List> getOverlayList( @PathVariable(value = "projectId") String projectId, @RequestParam(value = "creator", defaultValue = "") String creator, - @RequestParam(value = "publicOverlay", defaultValue = "false") boolean publicOverlay) throws lcsb.mapviewer.api.ObjectNotFoundException { + @RequestParam(value = "publicOverlay", defaultValue = "false") boolean publicOverlay) + throws lcsb.mapviewer.api.ObjectNotFoundException { return overlayRestImp.getOverlayList(projectId).stream() .filter(overlay -> !publicOverlay || (Boolean) overlay.get("publicOverlay")) .filter( @@ -99,7 +100,8 @@ public class OverlayController extends BaseController { Integer.valueOf(reactionId), "ALIAS", columns); } - @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'WRITE_PROJECT:' + #projectId)" + + @PreAuthorize("hasAuthority('IS_ADMIN')" + + " or (hasAuthority('IS_CURATOR') and hasAuthority('WRITE_PROJECT:' + #projectId))" + " or (hasAuthority('READ_PROJECT:' + #projectId) and hasAuthority('CAN_CREATE_OVERLAYS'))") @PostMapping(value = "/") public Map addOverlay( diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java index 56081e1c4f7128414d4b978223a281b7fc1797ef..7d616e6bfdeb4e41f34a9ab72e4ea05b08d44ca0 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java @@ -106,8 +106,8 @@ public class OverlayRestImpl extends BaseRestImpl { private List getDeprecatedColumns(Layout overlay) { try { List result = new ArrayList<>(); - for (ColorSchemaColumn column : new ColorSchemaReader().getDeprecatedColumns(overlay)) { - result.add(column.name()); + for (Pair entry : new ColorSchemaReader().getDeprecatedColumns(overlay)) { + result.add(entry.getRight()); } return result; } catch (IOException | InvalidColorSchemaException e) { @@ -181,6 +181,7 @@ public class OverlayRestImpl extends BaseRestImpl { if (overlayData == null) { throw new QueryException("overlay field cannot be undefined"); } + List reorderUsers = new ArrayList<>(); try { Layout layout = getOverlay(projectId, overlayId); for (String key : overlayData.keySet()) { @@ -202,8 +203,17 @@ public class OverlayRestImpl extends BaseRestImpl { layout.setGoogleLicenseConsent((Boolean) overlayData.get("googleLicenseConsent")); } else if (key.equalsIgnoreCase("creator")) { if ("".equals(value)) { + if (layout.getCreator() != null) { + reorderUsers.add(layout.getCreator()); + } layout.setCreator(null); } else { + if (layout.getCreator() == null) { + reorderUsers.add(getUserService().getUserByLogin((String) value)); + } else if (!layout.getCreator().getLogin().equals(value)) { + reorderUsers.add(getUserService().getUserByLogin((String) value)); + reorderUsers.add(layout.getCreator()); + } layout.setCreator(getUserService().getUserByLogin((String) value)); } } else { @@ -211,6 +221,9 @@ public class OverlayRestImpl extends BaseRestImpl { } } layoutDao.update(layout); + for (User user : reorderUsers) { + reorderOverlays(user, layout.getProject()); + } return getOverlayById(layout.getProject().getProjectId(), overlayId); } catch (NumberFormatException e) { throw new QueryException("invliad overlay id", e); @@ -231,7 +244,12 @@ public class OverlayRestImpl extends BaseRestImpl { User owner = layout.getCreator(); Project project = layout.getProject(); layoutService.removeLayout(layout, null); - + + reorderOverlays(owner, project); + return okStatus(); + } + + private void reorderOverlays(User owner, Project project) { List overlays = layoutService.getLayoutsByProject(project).stream() .filter(lay -> lay.getCreator() == owner).collect(Collectors.toList()); @@ -243,7 +261,6 @@ public class OverlayRestImpl extends BaseRestImpl { layoutService.updateLayout(overlay); } } - return okStatus(); } public Map addOverlay(String projectId, String name, String description, String content, diff --git a/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java b/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java index 3cd4e6053c6b811ec5108ee1164221bed2381157..228de145bead87b74d46288ad18782f46e3a7636 100644 --- a/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java +++ b/service/src/main/java/lcsb/mapviewer/services/utils/ColorSchemaReader.java @@ -814,9 +814,9 @@ public class ColorSchemaReader { return readColorSchema(new ByteArrayInputStream(inputData), params); } - public List getDeprecatedColumns(Layout overlay) + public List> getDeprecatedColumns(Layout overlay) throws IOException, InvalidColorSchemaException { - List result = new ArrayList<>(); + List> result = new ArrayList<>(); if (overlay.getInputData() != null) { BufferedReader br = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(overlay.getInputData().getFileContent()))); @@ -843,13 +843,14 @@ public class ColorSchemaReader { Map schemaColumns = new HashMap<>(); parseColumns(columns, schemaColumns, type); for (ColorSchemaColumn column : schemaColumns.keySet()) { + Pair entry = new Pair<>(column, columns[schemaColumns.get(column)]); try { Field f = ColorSchemaColumn.class.getField(column.name()); if (f.isAnnotationPresent(Deprecated.class)) { - result.add(column); + result.add(entry); } else if (column.getDepractedColumnName() != null && column.getDepractedColumnName().equalsIgnoreCase(columns[schemaColumns.get(column)])) { - result.add(column); + result.add(entry); } } catch (NoSuchFieldException | SecurityException e) { throw new InvalidStateException(e); diff --git a/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java b/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java index ffb65322d3c03825bcdfa667a2cb09972428f7e5..d54b136d005749c05573233d4278a9f6f07539ff 100644 --- a/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java +++ b/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java @@ -9,6 +9,7 @@ import org.junit.runners.Suite.SuiteClasses; ChemicalControllerIntegrationTest.class, CommentControllerIntegrationTest.class, CommentControllerIntegrationTestWithoutTransaction.class, + ConvertControllerIntegrationTest.class, DrugControllerIntegrationTest.class, EndPointsInputValidationTests.class, FileControllerIntegrationTest.class, diff --git a/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java index b17c672c70507bf48a644af3af557698ee73be0c..1e07061c2cd413f759dcbb72b66258f40834dfc0 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java @@ -305,6 +305,12 @@ abstract public class ControllerIntegrationTest { }); } + protected Project createProjectInSeparateThread(String projectId) throws Exception { + return callInSeparateThread(() -> { + return createProject(projectId); + }); + } + protected Layout createOverlay(Project project, User admin) { return createOverlay(project, admin, "elementIdentifier\tvalue\n\t-1"); } diff --git a/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..01b4928513721285b57934123533d8a42d0b24c9 --- /dev/null +++ b/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java @@ -0,0 +1,37 @@ +package lcsb.mapviewer.web; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.RequestBuilder; + +@RunWith(SpringJUnit4ClassRunner.class) +public class ConvertControllerIntegrationTest extends ControllerIntegrationTest { + + @Test + public void testConvertInvalidFile() throws Exception { + String body = "invalid content"; + RequestBuilder request = post("/convert/image/SBGN-ML:svg") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body); + + mockMvc.perform(request) + .andExpect(status().isBadRequest()); + } + + @Test + public void testConvertInvalidMapFormat() throws Exception { + String body = "invalid content"; + RequestBuilder request = post("/convert/image/unknown:svg") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body); + + mockMvc.perform(request) + .andExpect(status().isBadRequest()); + } + +} diff --git a/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java index 0c0a3ea633febeef3fd80ad36ffa2aac4a8c90c2..11839fc471841ce28451344588980e80c4a9c623 100644 --- a/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java @@ -1,6 +1,7 @@ package lcsb.mapviewer.web; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -46,8 +47,6 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest private static final String TEST_USER_LOGIN = "test_user"; private static final String TEST_CURATOR_PASSWORD = "test_curator_pass"; private static final String TEST_CURATOR_LOGIN = "test_curator"; - private static final String TEST_ADMIN_PASSWORD = "test_admin"; - private static final String TEST_ADMIN_LOGIN = "test_admin"; Logger logger = LogManager.getLogger(); @Autowired private LayoutDao layoutDao; @@ -78,7 +77,6 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testListOverlaysByCreator() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); User curator = createCurator(TEST_CURATOR_LOGIN, TEST_CURATOR_PASSWORD); User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); @@ -87,7 +85,7 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest createOverlay(project, curator); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/" + TEST_PROJECT + "/overlays/?creator=" + TEST_CURATOR_LOGIN) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -104,13 +102,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testListPublicOverlaysOverlaysWhenCreatorEmpty() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); - - Layout layout= createOverlay(project, null); + Layout layout = createOverlay(project, null); layout.setPublicLayout(true); layoutDao.add(layout); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/" + TEST_PROJECT + "/overlays/?publicOverlay=true&creator=xxx") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -127,16 +123,14 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testListNonPublicOverlaysOverlaysWhenCreatorEmpty() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); - - Layout layout= createOverlay(project, null); + Layout layout = createOverlay(project, null); layout.setPublicLayout(true); layoutDao.add(layout); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get( - "/projects/" + TEST_PROJECT + "/overlays/?publicOverlay=false&creator=" + TEST_ADMIN_LOGIN) + "/projects/" + TEST_PROJECT + "/overlays/?publicOverlay=false&creator=" + BUILT_IN_TEST_ADMIN_LOGIN) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .session(session); @@ -151,7 +145,6 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testListOverlaysByPublicFlag() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); User curator = createCurator(TEST_CURATOR_LOGIN, TEST_CURATOR_PASSWORD); createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); @@ -164,7 +157,7 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest curatorLayout.setPublicLayout(false); layoutDao.add(curatorLayout); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/" + TEST_PROJECT + "/overlays/?publicOverlay=true") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -257,11 +250,10 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testAdminCanAccessUserOverlay() throws Exception { User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD, project); - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); Layout overlay = createOverlay(project, user); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId() + "/") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -308,7 +300,7 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testUserCannotAccessAnotherUserOverlay() throws Exception { createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD, project); - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(project, admin); @@ -324,11 +316,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetBioEntitiesForOverlay() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get( "/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId() + "/models/" + map.getId() + "/bioEntities/") @@ -395,11 +387,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetReactionsForOverlay() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get( "/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId() + "/models/" + map.getId() @@ -451,11 +443,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetElementsForOverlay() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get( "/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId() + "/models/" + map.getId() @@ -507,11 +499,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testAdminCreateOverlay() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); UploadedFileEntry file = createFile("elementIdentifier\tvalue\n\t-1", admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("fileId", String.valueOf(file.getId())), @@ -640,12 +632,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testAdminCanRemoveOverlay() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); Layout overlay = createOverlay(user); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = delete("/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId()) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -710,14 +701,13 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testAdminCanUpdateOverlay() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); Layout overlay = createOverlay(user); String body = "{\"overlay\":{}}"; - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = patch("/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId()) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -786,12 +776,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testAdminCanAccessOverlaySource() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); Layout overlay = createOverlay(user); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId() + ":downloadSource") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -857,9 +846,9 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest User user = createAdmin(TEST_USER_LOGIN, TEST_USER_PASSWORD); createOverlay(user); - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); UploadedFileEntry file = createFile("elementIdentifier\tvalue\n\t-1", admin); String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( @@ -986,14 +975,12 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testDeprecatedOverlayInformation() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); - Layout overlay = createOverlay(null, "elementIdentifier\t" + ColorSchemaColumn.REACTION_IDENTIFIER + "\tvalue\n\t\t-1"); overlay.setPublicLayout(true); layoutDao.update(overlay); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get( "/projects/" + TEST_PROJECT + "/overlays/" + overlay.getId() + "/") @@ -1020,9 +1007,7 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testListOverlaysWithUnknownProject() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); - - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/overlays/") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1034,11 +1019,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetOverlayByIdWithUnknownProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/overlays/" + overlay.getId() + "/") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1050,11 +1035,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetBioEntitiesForOverlayWithUndefinedProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get( "/projects/*/overlays/" + overlay.getId() + "/models/" + map.getId() + "/bioEntities/") @@ -1067,11 +1052,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetReactionsForOverlayWithUndefinedProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/overlays/" + overlay.getId() + "/models/" + map.getId() + "/bioEntities/reactions/" + reaction.getId() + "/") @@ -1084,11 +1069,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetElementsForOverlayWithUndefinedProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/overlays/" + overlay.getId() + "/models/" + map.getId() + "/bioEntities/elements/" + element.getId() + "/") @@ -1101,11 +1086,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testCreateOverlayWithUndefinedProjectId() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); UploadedFileEntry file = createFile("elementIdentifier\tvalue\n\t-1", admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("fileId", String.valueOf(file.getId())), @@ -1126,11 +1111,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testRemoveOverlayWithUndefinedProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = delete("/projects/*/overlays/" + overlay.getId()) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1142,13 +1127,13 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testUpdateOverlayWithUndefinedProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); String body = "{\"overlay\":{}}"; - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = patch("/projects/*/overlays/" + overlay.getId()) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1161,11 +1146,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testAccessOverlaySourceWithUndefinedProject() throws Exception { - User admin = createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); Layout overlay = createOverlay(admin); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/overlays/" + overlay.getId() + ":downloadSource") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1177,7 +1162,6 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testOrderAfterRemoveOverlay() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); Layout overlay1 = createOverlay(user); @@ -1186,12 +1170,12 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest overlay2.setOrderIndex(2); Layout overlay3 = createOverlay(user); overlay3.setOrderIndex(3); - + layoutDao.update(overlay1); layoutDao.update(overlay2); layoutDao.update(overlay3); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = delete("/projects/" + TEST_PROJECT + "/overlays/" + overlay2.getId()) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1205,20 +1189,18 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest @Test public void testOrderAfterRemoveOverlayForPublicOverlay() throws Exception { - createAdmin(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); - Layout overlay1 = createOverlay(null); overlay1.setOrderIndex(1); Layout overlay2 = createOverlay(null); overlay2.setOrderIndex(2); Layout overlay3 = createOverlay(null); overlay3.setOrderIndex(3); - + layoutDao.update(overlay1); layoutDao.update(overlay2); layoutDao.update(overlay3); - MockHttpSession session = createSession(TEST_ADMIN_LOGIN, TEST_ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = delete("/projects/" + TEST_PROJECT + "/overlays/" + overlay2.getId()) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1230,5 +1212,65 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest assertEquals(2, overlay3.getOrderIndex()); } + @Test + public void testChangeOrderAfterChaningOwner() throws Exception { + User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); + + Layout overlay1 = createOverlay(user); + overlay1.setOrderIndex(1); + Layout overlay2 = createOverlay(user); + overlay2.setOrderIndex(2); + + Layout overlay3 = createOverlay(admin); + overlay3.setOrderIndex(1); + Layout overlay4 = createOverlay(admin); + overlay4.setOrderIndex(2); + + String body = "{\"overlay\":{\"creator\":\"" + admin.getLogin() + "\"}}"; + + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + RequestBuilder request = patch("/projects/" + TEST_PROJECT + "/overlays/" + overlay1.getId()) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(session); + + mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()); + + assertEquals("Order of overlays wasn't updated for original owner of overlay", 1, overlay2.getOrderIndex()); + + assertTrue(overlay1.getOrderIndex() == 1 || overlay3.getOrderIndex() == 1); + assertTrue(overlay1.getOrderIndex() == 2 || overlay3.getOrderIndex() == 2); + assertEquals(3, overlay4.getOrderIndex()); + } + + @Test + public void testCreateOverlayWithoutCreateDataOverlayAccess() throws Exception { + User user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); + userService.grantUserPrivilege(user, PrivilegeType.WRITE_PROJECT, project.getProjectId()); + + UploadedFileEntry file = createFile("elementIdentifier\tvalue\n\t-1", user); + + MockHttpSession session = createSession(TEST_USER_LOGIN, TEST_USER_PASSWORD); + + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("fileId", String.valueOf(file.getId())), + new BasicNameValuePair("name", "overlay name"), + new BasicNameValuePair("description", "overlay name"), + new BasicNameValuePair("filename", "overlay name"), + new BasicNameValuePair("googleLicenseConsent", "overlay name"), + new BasicNameValuePair("type", "GENERIC")))); + + RequestBuilder request = post("/projects/"+TEST_PROJECT+"/overlays/") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isForbidden()); + } + } diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java index fd7624c9dae83917b984832122b68c90b420bbba..704933c43fb6cef01aa0f056443956b96c49e61a 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java @@ -34,8 +34,6 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest private static final String TEST_PROJECT = "test_project"; private static final String CURATOR_PASSWORD = "test_pass"; private static final String CURATOR_LOGIN = "test_user"; - private static final String ADMIN_PASSWORD = "admin_pass"; - private static final String ADMIN_LOGIN = "admin_user"; Logger logger = LogManager.getLogger(); @Autowired private IUserService userService; @@ -44,18 +42,15 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest private ProjectDao projectDao; private User curator; - private User admin; @Before public void setup() { curator = createCurator(CURATOR_LOGIN, CURATOR_PASSWORD); - - admin = createAdmin(ADMIN_LOGIN, ADMIN_PASSWORD); } @Test public void testGetAllProjectsAsAdmin() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); createProject(TEST_PROJECT); RequestBuilder request = get("/projects/") @@ -136,7 +131,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest public void testGrantPrivilege() throws Exception { createProject(TEST_PROJECT); - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = "[{" + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", " @@ -158,7 +153,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest Project project = createProject(TEST_PROJECT); userService.grantUserPrivilege(curator, PrivilegeType.READ_PROJECT, project.getProjectId()); - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = "[{" + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", " @@ -177,7 +172,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetNonExistingProject() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/") .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -189,7 +184,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testUpdateProject() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); Project project = createProject(TEST_PROJECT); String content = "{\"project\":{\"version\":\"xxx\"}}"; @@ -206,9 +201,25 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest } + @Test + public void testUpdateProjectWithTooLongVersion() throws Exception { + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + createProject(TEST_PROJECT); + + String content = "{\"project\":{\"version\":\"12345678901234567890123456\"}}"; + + RequestBuilder request = patch("/projects/" + TEST_PROJECT + "/") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(content) + .session(session); + + mockMvc.perform(request) + .andExpect(status().isBadRequest()); + } + @Test public void testUpdateProjectWithUndefinedProjectId() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String content = "{\"project\":{\"version\":\"xxx\"}}"; @@ -223,7 +234,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGrantPrivilegeForUndefinedProject() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = "[{" + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", " @@ -240,7 +251,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testRevokePrivilegeForUndefinedProject() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = "[{" + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", " @@ -257,7 +268,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testRemoveProjectForUndefinedProjectId() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = delete("/projects/*/") .session(session); @@ -268,7 +279,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetStatisticsForUndefinedProjectId() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/statistics") .session(session); @@ -279,7 +290,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testDownloadSourceForUndefinedProjectId() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*:downloadSource") .session(session); @@ -290,7 +301,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetLogsForUndefinedProjectId() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/logs/") .session(session); @@ -301,7 +312,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest @Test public void testGetSubmapConnectionsForUndefinedProjectId() throws Exception { - MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/projects/*/submapConnections/") .session(session); diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestForAsyncCalls.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestForAsyncCalls.java index a0ea1e520fd2e40e594a6c0256d6fe4b8bbd2595..0b0a9afabf8655b5694a4dd6cf45a8a32942be2c 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestForAsyncCalls.java +++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestForAsyncCalls.java @@ -194,13 +194,6 @@ public class ProjectControllerIntegrationTestForAsyncCalls extends ControllerInt } } - private Project createProjectInSeparateThread(String projectId) throws Exception { - return callInSeparateThread(() -> { - return createProject(projectId); - }); - - } - private void grantPrivilegeInSeparateThread(User user, String string) throws Exception { callInSeparateThread(() -> { userService.grantUserPrivilege(user, PrivilegeType.valueOf(string.split(":")[0]), string.split(":")[1]); diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java index 0ce88ed33af6c30d41caf310c4c2266a6356969b..553c289fe1058188119a42c739b1c4e08a70f9bc 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java +++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java @@ -1,5 +1,6 @@ package lcsb.mapviewer.web; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -101,4 +102,81 @@ public class ProjectControllerIntegrationTestWithoutTransaction extends Controll } } + @Test + public void addProjectWithTooLongName() throws Exception { + User admin = userService.getUserByLogin(BUILT_IN_ADMIN_LOGIN); + UploadedFileEntry fileEntry = createFileInSeparateThread( + new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), + admin); + try { + String invalidName = "aaaaaaaaxvncnbvscbnmcnbmccbnsbnsdsnbmdsvbnmsdvnbmsdbmnbndvmsbnmsvdnbmnmbdsvnbmdsvxncbmbnmscbnzdnbnabnsbnamsdbmnsadbmnasdbnmnbmsadbnmasdnbasdbnmsadnbnbmsadbnmadsnbmadsnbnbsadnbmadsbnndsabnbmdasbnmdsajqwrhgjrwhjghgjwerghjwreghwewnjnnbbbnbnbmbnbnzcmnnbmzcnmbcsbnmcsnbcnbzmnbczxnbmczxnbmcxznbcnxbmznbmxzcnbzcxnnbcxznbmzcnbczxnbmnbzcxnbmcznnczbnbzcnbmzcbnmbncznbcznbcz"; + + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("name", invalidName), + new BasicNameValuePair("parser", + "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); + + RequestBuilder request = post("/projects/" + TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_ADMIN_LOGIN, BUILT_IN_ADMIN_PASSWORD)); + + mockMvc.perform(request).andExpect(status().isBadRequest()); + + } finally { + removeFileInSeparateThread(fileEntry); + } + } + + @Test + public void addProjectWithTooLongVersion() throws Exception { + User admin = userService.getUserByLogin(BUILT_IN_ADMIN_LOGIN); + UploadedFileEntry fileEntry = createFileInSeparateThread( + new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), + admin); + try { + String invalidVersion = "12345678901234567890123456"; + + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("version", invalidVersion), + new BasicNameValuePair("parser", + "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); + + RequestBuilder request = post("/projects/" + TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_ADMIN_LOGIN, BUILT_IN_ADMIN_PASSWORD)); + + mockMvc.perform(request).andExpect(status().isBadRequest()); + + } finally { + removeFileInSeparateThread(fileEntry); + removeProjectInSeparateThread(TEST_PROJECT); + } + } + + @Test + public void modifyProjectWithTooLongName() throws Exception { + createProjectInSeparateThread(TEST_PROJECT); + try { + String invalidName = "aaaaaaaaxvncnbvscbnmcnbmccbnsbnsdsnbmdsvbnmsdvnbmsdbmnbndvmsbnmsvdnbmnmbdsvnbmdsvxncbmbnmscbnzdnbnabnsbnamsdbmnsadbmnasdbnmnbmsadbnmasdnbasdbnmsadnbnbmsadbnmadsnbmadsnbnbsadnbmadsbnndsabnbmdasbnmdsajqwrhgjrwhjghgjwerghjwreghwewnjnnbbbnbnbmbnbnzcmnnbmzcnmbcsbnmcsnbcnbzmnbczxnbmczxnbmcxznbcnxbmznbmxzcnbzcxnnbcxznbmzcnbczxnbmnbzcxnbmcznnczbnbzcnbmzcbnmbncznbcznbcz"; + + String content = "{\"project\":{\"name\":\"" + invalidName + "\"}}"; + + RequestBuilder request = patch("/projects/" + TEST_PROJECT + "/") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(content) + .session(createSession(BUILT_IN_ADMIN_LOGIN, BUILT_IN_ADMIN_PASSWORD)); + + mockMvc.perform(request).andExpect(status().isBadRequest()); + + } finally { + removeProjectInSeparateThread(TEST_PROJECT); + } + } + }