diff --git a/CHANGELOG.md b/CHANGELOG.md index f3f91ee218efceca40e597823706b39a2ac714ec..1354bf47d72d110a064b970cd2c8393024c8fbe3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,11 +33,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 attributes. * [caosdb-server#217](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/217) Server gets list property datatype wrong if description is updated. +* [caosdb-server#220](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/220) + Entities can be retrieved via GRPC despite insufficient permissions. * [caosdb-server#221](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/221) Unknown error during update of property leaving out datatype. +* [caosdb-server#223](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/223) + State is being leaked even though RETRIEVE:ENTITY permission is not granted. ### Security +* Update of logging backend log4j to 2.17.2 +* Fix for [caosdb-server#220](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/220) + Entities can be retrieved via GRPC despite insufficient permissions. +* Fix for [caosdb-server#223](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/223) + State is being leaked even though RETRIEVE:ENTITY permission is not granted. ## [v0.7.1] - 2021-12-13 (Timm Fitschen) diff --git a/pom.xml b/pom.xml index 1d665fcea44e070f38afb1cc17da3086916cc108..733a5b4ca3c741fef0d611885327545eee8c0129 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ <grpc.version>1.42.1</grpc.version> <netty-tcnative.version>2.0.34.Final</netty-tcnative.version> <restlet.version>2.4.3</restlet.version> - <log4j.version>2.15.0</log4j.version> + <log4j.version>2.17.2</log4j.version> </properties> <repositories> <repository> diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java index 20ef481cde3845a35fbdc3853fb12a31278dc7e3..07c451a328b8a1a6d52810f25f78276699fce797 100644 --- a/src/main/java/org/caosdb/server/entity/Entity.java +++ b/src/main/java/org/caosdb/server/entity/Entity.java @@ -51,7 +51,7 @@ import org.caosdb.server.entity.wrapper.Domain; import org.caosdb.server.entity.wrapper.Parent; import org.caosdb.server.entity.wrapper.Property; import org.caosdb.server.entity.xml.EntityToElementStrategy; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.entity.xml.ToElementStrategy; import org.caosdb.server.entity.xml.ToElementable; import org.caosdb.server.permissions.EntityACL; @@ -537,16 +537,25 @@ public class Entity extends AbstractObservable implements EntityInterface { @Override public final Element toElement() { - return getToElementStrategy().toElement(this, new SetFieldStrategy(getSelections())); + return getToElementStrategy().toElement(this, getSerializeFieldStrategy()); + } + + @Override + public SerializeFieldStrategy getSerializeFieldStrategy() { + // @review Florian Spreckelsen 2022-03-22 + if (this.serializeFieldStrategy == null) { + this.serializeFieldStrategy = new SerializeFieldStrategy(getSelections()); + } + return this.serializeFieldStrategy; } @Override public final void addToElement(final Element element) { - addToElement(element, new SetFieldStrategy(getSelections())); + addToElement(element, getSerializeFieldStrategy()); } @Override - public void addToElement(Element element, SetFieldStrategy strategy) { + public void addToElement(Element element, SerializeFieldStrategy strategy) { getToElementStrategy().addToElement(this, element, strategy); } @@ -930,6 +939,7 @@ public class Entity extends AbstractObservable implements EntityInterface { private boolean datatypeOverride = false; private Version version = new Version(); + private SerializeFieldStrategy serializeFieldStrategy = null; @Override public EntityInterface setDatatypeOverride(final boolean b) { @@ -1067,4 +1077,10 @@ public class Entity extends AbstractObservable implements EntityInterface { && this.getDatatype() instanceof AbstractCollectionDatatype && ((AbstractCollectionDatatype) getDatatype()).getDatatype() instanceof ReferenceDatatype; } + + @Override + public void setSerializeFieldStrategy(SerializeFieldStrategy s) { + // @review Florian Spreckelsen 2022-03-22 + this.serializeFieldStrategy = s; + } } diff --git a/src/main/java/org/caosdb/server/entity/EntityInterface.java b/src/main/java/org/caosdb/server/entity/EntityInterface.java index 46726df63dcedb651e0762f54a7b2cdafb5041d7..cfb4c28050f871684044c6216081101759a1cf17 100644 --- a/src/main/java/org/caosdb/server/entity/EntityInterface.java +++ b/src/main/java/org/caosdb/server/entity/EntityInterface.java @@ -34,7 +34,7 @@ import org.caosdb.server.entity.container.PropertyContainer; import org.caosdb.server.entity.wrapper.Domain; import org.caosdb.server.entity.wrapper.Parent; import org.caosdb.server.entity.wrapper.Property; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.entity.xml.ToElementable; import org.caosdb.server.jobs.JobTarget; import org.caosdb.server.permissions.EntityACL; @@ -189,7 +189,7 @@ public interface EntityInterface public abstract void setVersion(Version version); - public abstract void addToElement(Element element, SetFieldStrategy strategy); + public abstract void addToElement(Element element, SerializeFieldStrategy strategy); /** Return true iff the data type is present and is an instance of ReferenceDatatype. */ public abstract boolean isReference(); @@ -199,4 +199,6 @@ public interface EntityInterface * AbstractCollectionDatatype's elements' data type is an instance of ReferenceDatatype. */ public abstract boolean isReferenceList(); + + public abstract SerializeFieldStrategy getSerializeFieldStrategy(); } diff --git a/src/main/java/org/caosdb/server/entity/TransactionEntity.java b/src/main/java/org/caosdb/server/entity/TransactionEntity.java index 7dd96b7f5ba8dc71c976731fed4d91e43688f919..976106223800802cd3e885baaad5d0113d9726da 100644 --- a/src/main/java/org/caosdb/server/entity/TransactionEntity.java +++ b/src/main/java/org/caosdb/server/entity/TransactionEntity.java @@ -25,6 +25,7 @@ package org.caosdb.server.entity; import java.util.List; import java.util.Map; import java.util.Set; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.entity.xml.ToElementStrategy; import org.caosdb.server.entity.xml.ToElementable; import org.caosdb.server.query.Query.Selection; @@ -47,6 +48,8 @@ public interface TransactionEntity { public abstract void setToElementStragegy(ToElementStrategy s); + public abstract void setSerializeFieldStrategy(SerializeFieldStrategy s); + public abstract Element toElement(); public abstract Set<ToElementable> getMessages(); diff --git a/src/main/java/org/caosdb/server/entity/container/ParentContainer.java b/src/main/java/org/caosdb/server/entity/container/ParentContainer.java index 90c6078a47471712ac51448ac4aac3d05794f5a6..896a355c5f2df67a542ec17b0710777c543313ef 100644 --- a/src/main/java/org/caosdb/server/entity/container/ParentContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/ParentContainer.java @@ -26,7 +26,7 @@ import org.caosdb.server.entity.Entity; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.wrapper.Parent; import org.caosdb.server.entity.xml.ParentToElementStrategy; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.entity.xml.ToElementStrategy; import org.caosdb.server.utils.EntityStatus; import org.caosdb.server.utils.Observable; @@ -51,10 +51,10 @@ public class ParentContainer extends Container<Parent> { } public Element addToElement(final Element element) { - final SetFieldStrategy setFieldStrategy = - new SetFieldStrategy(this.child.getSelections()).forProperty("parent"); + final SerializeFieldStrategy serializeFieldStrategy = + new SerializeFieldStrategy(this.child.getSelections()).forProperty("parent"); for (final EntityInterface entity : this) { - s.addToElement(entity, element, setFieldStrategy); + s.addToElement(entity, element, serializeFieldStrategy); } return element; } diff --git a/src/main/java/org/caosdb/server/entity/container/PropertyContainer.java b/src/main/java/org/caosdb/server/entity/container/PropertyContainer.java index f5cce963fa4611bbdebfacdb11f98497c2a68544..2a6593d1e801cdd795756d58cc38e66b8f3b919b 100644 --- a/src/main/java/org/caosdb/server/entity/container/PropertyContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/PropertyContainer.java @@ -31,7 +31,7 @@ import org.caosdb.server.entity.Entity; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.wrapper.Property; import org.caosdb.server.entity.xml.PropertyToElementStrategy; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.entity.xml.ToElementStrategy; import org.caosdb.server.utils.EntityStatus; import org.caosdb.server.utils.Observable; @@ -72,12 +72,12 @@ public class PropertyContainer extends Container<Property> { * * @param property * @param element - * @param setFieldStrategy + * @param serializeFieldStrategy */ public void addToElement( - EntityInterface property, Element element, SetFieldStrategy setFieldStrategy) { - if (setFieldStrategy.isToBeSet(property.getName())) { - SetFieldStrategy strategy = setFieldStrategy.forProperty(property.getName()); + EntityInterface property, Element element, SerializeFieldStrategy serializeFieldStrategy) { + if (serializeFieldStrategy.isToBeSet(property.getName())) { + SerializeFieldStrategy strategy = serializeFieldStrategy.forProperty(property.getName()); this.s.addToElement(property, element, strategy); } } @@ -86,12 +86,13 @@ public class PropertyContainer extends Container<Property> { * Add all properties to the element using the given setFieldStrategy. * * @param element - * @param setFieldStrategy + * @param serializeFieldStrategy */ - public void addToElement(final Element element, final SetFieldStrategy setFieldStrategy) { + public void addToElement( + final Element element, final SerializeFieldStrategy serializeFieldStrategy) { sort(); for (final EntityInterface property : this) { - addToElement(property, element, setFieldStrategy); + addToElement(property, element, serializeFieldStrategy); } } diff --git a/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java index e5115dc219ac427e93ae87c0921ced965023f55e..2028bee793d1f81525d3e1a86ebd22b7e5d46963 100644 --- a/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java +++ b/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java @@ -41,7 +41,7 @@ import org.caosdb.server.entity.StatementStatus; import org.caosdb.server.entity.Version; import org.caosdb.server.entity.container.ParentContainer; import org.caosdb.server.entity.container.PropertyContainer; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.entity.xml.ToElementStrategy; import org.caosdb.server.entity.xml.ToElementable; import org.caosdb.server.permissions.EntityACL; @@ -562,7 +562,7 @@ public class EntityWrapper implements EntityInterface { } @Override - public void addToElement(Element element, SetFieldStrategy strategy) { + public void addToElement(Element element, SerializeFieldStrategy strategy) { this.entity.addToElement(element, strategy); } @@ -575,4 +575,16 @@ public class EntityWrapper implements EntityInterface { public boolean isReferenceList() { return this.entity.isReferenceList(); } + + @Override + public void setSerializeFieldStrategy(SerializeFieldStrategy s) { + // @review Florian Spreckelsen 2022-03-22 + this.entity.setSerializeFieldStrategy(s); + } + + @Override + public SerializeFieldStrategy getSerializeFieldStrategy() { + // @review Florian Spreckelsen 2022-03-22 + return this.entity.getSerializeFieldStrategy(); + } } diff --git a/src/main/java/org/caosdb/server/entity/xml/DomainToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/DomainToElementStrategy.java index a8b600793a6fdaf8d15ec499112cc06771f66fc3..9480119221aec4fa31c44b812539928327d97ccd 100644 --- a/src/main/java/org/caosdb/server/entity/xml/DomainToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/DomainToElementStrategy.java @@ -39,9 +39,10 @@ public class DomainToElementStrategy extends EntityToElementStrategy { } @Override - public Element toElement(final EntityInterface entity, final SetFieldStrategy setFieldStrategy) { + public Element toElement( + final EntityInterface entity, final SerializeFieldStrategy serializeFieldStrategy) { Element element = new Element(tagName); - sparseEntityToElement(element, entity, setFieldStrategy); + sparseEntityToElement(element, entity, serializeFieldStrategy); return element; } @@ -49,8 +50,8 @@ public class DomainToElementStrategy extends EntityToElementStrategy { public Element addToElement( final EntityInterface entity, final Element element, - final SetFieldStrategy setFieldStrategy) { - element.addContent(toElement(entity, setFieldStrategy)); + final SerializeFieldStrategy serializeFieldStrategy) { + element.addContent(toElement(entity, serializeFieldStrategy)); return element; } } diff --git a/src/main/java/org/caosdb/server/entity/xml/EntityToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/EntityToElementStrategy.java index 89420c596894da9be35e33a507821c96d10f5b7d..a274d269b2281ebed59530728c767cb1bca14f4a 100644 --- a/src/main/java/org/caosdb/server/entity/xml/EntityToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/EntityToElementStrategy.java @@ -76,41 +76,59 @@ public class EntityToElementStrategy implements ToElementStrategy { * * @param element * @param entity - * @param setFieldStrategy + * @param serializeFieldStrategy */ public void sparseEntityToElement( final Element element, final EntityInterface entity, - final SetFieldStrategy setFieldStrategy) { + final SerializeFieldStrategy serializeFieldStrategy) { + + // @review Florian Spreckelsen 2022-03-22 if (entity.getEntityACL() != null) { element.addContent(entity.getEntityACL().getPermissionsFor(SecurityUtils.getSubject())); } - if (setFieldStrategy.isToBeSet("id") && entity.hasId()) { + if (serializeFieldStrategy.isToBeSet("id") && entity.hasId()) { element.setAttribute("id", Integer.toString(entity.getId())); } - if (entity.hasVersion()) { + if (serializeFieldStrategy.isToBeSet("version") && entity.hasVersion()) { Element v = new VersionXMLSerializer().toElement(entity.getVersion()); element.addContent(v); } - if (setFieldStrategy.isToBeSet("cuid") && entity.hasCuid()) { + if (serializeFieldStrategy.isToBeSet("cuid") && entity.hasCuid()) { element.setAttribute("cuid", entity.getCuid()); } - if (setFieldStrategy.isToBeSet("name") && entity.hasName()) { + if (serializeFieldStrategy.isToBeSet("name") && entity.hasName()) { element.setAttribute("name", entity.getName()); } - if (setFieldStrategy.isToBeSet("description") && entity.hasDescription()) { + if (serializeFieldStrategy.isToBeSet("description") && entity.hasDescription()) { element.setAttribute("description", entity.getDescription()); } - if (setFieldStrategy.isToBeSet("datatype") && entity.hasDatatype()) { + if (serializeFieldStrategy.isToBeSet("datatype") && entity.hasDatatype()) { setDatatype(entity, element); } - if (setFieldStrategy.isToBeSet("message") && entity.hasMessages()) { + if (serializeFieldStrategy.isToBeSet("message") && entity.hasMessages()) { for (final ToElementable m : entity.getMessages()) { m.addToElement(element); } + } else { + if (serializeFieldStrategy.isToBeSet("error")) { + for (ToElementable m : entity.getMessages("error")) { + m.addToElement(element); + } + } + if (serializeFieldStrategy.isToBeSet("warning")) { + for (ToElementable m : entity.getMessages("warning")) { + m.addToElement(element); + } + } + if (serializeFieldStrategy.isToBeSet("info")) { + for (ToElementable m : entity.getMessages("info")) { + m.addToElement(element); + } + } } - if (setFieldStrategy.isToBeSet("query") && entity.getQueryTemplateDefinition() != null) { + if (serializeFieldStrategy.isToBeSet("query") && entity.getQueryTemplateDefinition() != null) { final Element q = new Element("Query"); q.setText(entity.getQueryTemplateDefinition()); element.addContent(q); @@ -127,9 +145,10 @@ public class EntityToElementStrategy implements ToElementStrategy { * * @param entity * @param element - * @param setFieldStrategy + * @param serializeFieldStrategy */ - public void setValue(EntityInterface entity, Element element, SetFieldStrategy setFieldStrategy) { + public void setValue( + EntityInterface entity, Element element, SerializeFieldStrategy serializeFieldStrategy) { if (entity.hasValue()) { try { entity.parseValue(); @@ -139,7 +158,7 @@ public class EntityToElementStrategy implements ToElementStrategy { // CheckValueParsable job. } - if (entity.isReference() && setFieldStrategy.isToBeSet("_referenced")) { + if (entity.isReference() && serializeFieldStrategy.isToBeSet("_referenced")) { // Append the complete entity. This needs to be done when we are // processing SELECT Queries. EntityInterface ref = ((ReferenceValue) entity.getValue()).getEntity(); @@ -147,12 +166,12 @@ public class EntityToElementStrategy implements ToElementStrategy { if (entity.hasDatatype()) { setDatatype(entity, element); } - ref.addToElement(element, setFieldStrategy); + ref.addToElement(element, serializeFieldStrategy); // the referenced entity has been appended. Return here to suppress // adding the reference id as well. return; } - } else if (entity.isReferenceList() && setFieldStrategy.isToBeSet("_referenced")) { + } else if (entity.isReferenceList() && serializeFieldStrategy.isToBeSet("_referenced")) { // Append the all referenced entities. This needs to be done when we are // processing SELECT Queries. boolean skipValue = false; @@ -163,7 +182,7 @@ public class EntityToElementStrategy implements ToElementStrategy { setDatatype(entity, element); } Element valueElem = new Element("Value"); - ref.addToElement(valueElem, setFieldStrategy); + ref.addToElement(valueElem, serializeFieldStrategy); element.addContent(valueElem); skipValue = true; } @@ -174,7 +193,7 @@ public class EntityToElementStrategy implements ToElementStrategy { return; } - if (setFieldStrategy.isToBeSet("value")) { + if (serializeFieldStrategy.isToBeSet("value")) { if (entity.hasDatatype()) { setDatatype(entity, element); } @@ -184,24 +203,25 @@ public class EntityToElementStrategy implements ToElementStrategy { } @Override - public Element toElement(final EntityInterface entity, final SetFieldStrategy setFieldStrategy) { + public Element toElement( + final EntityInterface entity, final SerializeFieldStrategy serializeFieldStrategy) { final Element element = new Element(tagName); // always have the values at the beginning of the children - setValue(entity, element, setFieldStrategy); + setValue(entity, element, serializeFieldStrategy); - sparseEntityToElement(element, entity, setFieldStrategy); + sparseEntityToElement(element, entity, serializeFieldStrategy); - if (entity.hasStatementStatus() && setFieldStrategy.isToBeSet("importance")) { + if (entity.hasStatementStatus() && serializeFieldStrategy.isToBeSet("importance")) { element.setAttribute("importance", entity.getStatementStatus().toString()); } - if (entity.hasParents() && setFieldStrategy.isToBeSet("parent")) { + if (entity.hasParents() && serializeFieldStrategy.isToBeSet("parent")) { entity.getParents().addToElement(element); } if (entity.hasProperties()) { - entity.getProperties().addToElement(element, setFieldStrategy); + entity.getProperties().addToElement(element, serializeFieldStrategy); } - if (entity.hasTransactionLogMessages() && setFieldStrategy.isToBeSet("history")) { + if (entity.hasTransactionLogMessages() && serializeFieldStrategy.isToBeSet("history")) { for (final TransactionLogMessage t : entity.getTransactionLogMessages()) { t.xmlAppendTo(element); } @@ -211,9 +231,11 @@ public class EntityToElementStrategy implements ToElementStrategy { @Override public Element addToElement( - final EntityInterface entity, final Element parent, final SetFieldStrategy setFieldStrategy) { + final EntityInterface entity, + final Element parent, + final SerializeFieldStrategy serializeFieldStrategy) { if (entity.getEntityStatus() != EntityStatus.IGNORE) { - parent.addContent(toElement(entity, setFieldStrategy)); + parent.addContent(toElement(entity, serializeFieldStrategy)); } return parent; } diff --git a/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java index 7ac394a2e3f226afa6f4723daadc95c63db69b25..288159809057d08f57c71dc7cd6decf8adc3be73 100644 --- a/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java @@ -33,17 +33,19 @@ public class FileToElementStrategy extends EntityToElementStrategy { } @Override - public Element toElement(final EntityInterface entity, final SetFieldStrategy setFieldStrategy) { - final Element element = super.toElement(entity, setFieldStrategy); + public Element toElement( + final EntityInterface entity, final SerializeFieldStrategy serializeFieldStrategy) { + final Element element = super.toElement(entity, serializeFieldStrategy); if (entity.hasFileProperties()) { - if (setFieldStrategy.isToBeSet("checksum") && entity.getFileProperties().hasChecksum()) { + if (serializeFieldStrategy.isToBeSet("checksum") + && entity.getFileProperties().hasChecksum()) { element.setAttribute(new Attribute("checksum", entity.getFileProperties().getChecksum())); } - if (setFieldStrategy.isToBeSet("path") && entity.getFileProperties().hasPath()) { + if (serializeFieldStrategy.isToBeSet("path") && entity.getFileProperties().hasPath()) { element.setAttribute(new Attribute("path", "/" + entity.getFileProperties().getPath())); } - if (setFieldStrategy.isToBeSet("size") && entity.getFileProperties().hasSize()) { + if (serializeFieldStrategy.isToBeSet("size") && entity.getFileProperties().hasSize()) { element.setAttribute( new Attribute("size", Long.toString(entity.getFileProperties().getSize()))); } diff --git a/src/main/java/org/caosdb/server/entity/xml/IdAndServerMessagesOnlyStrategy.java b/src/main/java/org/caosdb/server/entity/xml/IdAndServerMessagesOnlyStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..42f7eef9536ae9525875064e7eb60ec855a3952d --- /dev/null +++ b/src/main/java/org/caosdb/server/entity/xml/IdAndServerMessagesOnlyStrategy.java @@ -0,0 +1,21 @@ +package org.caosdb.server.entity.xml; + +/** + * Special purpose subclass of {@link SerializeFieldStrategy} which only serializes the id and the + * server messages (error, warning, info). + * + * <p>This strategy is used when the client doesn't have the permission to retrieve and entity. + * + * @author Timm Fitschen <t.fitschen@indiscale.com> + */ +public class IdAndServerMessagesOnlyStrategy extends SerializeFieldStrategy { + + // @review Florian Spreckelsen 2022-03-22 + @Override + public boolean isToBeSet(String field) { + return "id".equals(field) + || "error".equals(field) + || "warning".equals(field) + || "info".equals(field); + } +} diff --git a/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java index 29c163dc5ca55b731aa44a85224821c41356e35a..4f7906829427a2305f0f1b2addf72d2b69112a9e 100644 --- a/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/ParentToElementStrategy.java @@ -41,7 +41,8 @@ public class ParentToElementStrategy extends EntityToElementStrategy { } @Override - public Element toElement(final EntityInterface entity, final SetFieldStrategy setFieldStrategy) { + public Element toElement( + final EntityInterface entity, final SerializeFieldStrategy setFieldStrategy) { final Element element = new Element(this.tagName); sparseEntityToElement(element, entity, setFieldStrategy); final Parent parent = (Parent) entity; @@ -55,7 +56,7 @@ public class ParentToElementStrategy extends EntityToElementStrategy { public Element addToElement( final EntityInterface entity, final Element element, - final SetFieldStrategy setFieldStrategy) { + final SerializeFieldStrategy setFieldStrategy) { if (entity.getEntityStatus() != EntityStatus.IGNORE) { element.addContent(toElement(entity, setFieldStrategy)); } diff --git a/src/main/java/org/caosdb/server/entity/xml/PropertyToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/PropertyToElementStrategy.java index 60014d82b18da4e8dfdd5fe0bcf042171c2bdda7..23fd8a553e66df23349c20e8539e3154f3e2ac0a 100644 --- a/src/main/java/org/caosdb/server/entity/xml/PropertyToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/PropertyToElementStrategy.java @@ -39,7 +39,7 @@ public class PropertyToElementStrategy extends EntityToElementStrategy { public Element addToElement( final EntityInterface entity, final Element element, - final SetFieldStrategy setFieldStrategy) { + final SerializeFieldStrategy setFieldStrategy) { try { final Value v = entity.getValue(); if (entity.hasId()) { diff --git a/src/main/java/org/caosdb/server/entity/xml/SetFieldStrategy.java b/src/main/java/org/caosdb/server/entity/xml/SerializeFieldStrategy.java similarity index 86% rename from src/main/java/org/caosdb/server/entity/xml/SetFieldStrategy.java rename to src/main/java/org/caosdb/server/entity/xml/SerializeFieldStrategy.java index 1d9f219086e5ddd921d9519d3391e1cca9fbffc9..30210118c0fe8c7b88f0f56532560c49c3782cc0 100644 --- a/src/main/java/org/caosdb/server/entity/xml/SetFieldStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/SerializeFieldStrategy.java @@ -39,7 +39,7 @@ import org.caosdb.server.query.Query.Selection; * * @author Timm Fitschen <t.fitschen@indiscale.com> */ -public class SetFieldStrategy { +public class SerializeFieldStrategy { private final List<Selection> selections = new LinkedList<Selection>(); private HashMap<String, Boolean> cache = null; @@ -48,25 +48,25 @@ public class SetFieldStrategy { * The default is: Any field should be included into the serialization, unless it is a referenced * entity. */ - private static final SetFieldStrategy defaultSelections = - new SetFieldStrategy(null) { + private static final SerializeFieldStrategy defaultSelections = + new SerializeFieldStrategy(null) { @Override public boolean isToBeSet(final String field) { return field == null || !field.equalsIgnoreCase("_referenced"); } }; - public SetFieldStrategy(final List<Selection> selections) { + public SerializeFieldStrategy(final List<Selection> selections) { if (selections != null) { this.selections.addAll(selections); } } - public SetFieldStrategy() { + public SerializeFieldStrategy() { this(null); } - public SetFieldStrategy addSelection(final Selection selection) { + public SerializeFieldStrategy addSelection(final Selection selection) { // ignore null if (selection == null) { return this; @@ -80,15 +80,15 @@ public class SetFieldStrategy { return this; } - public SetFieldStrategy forProperty(final EntityInterface property) { + public SerializeFieldStrategy forProperty(final EntityInterface property) { return forProperty(property.getName()); } /** Return the strategy for a property. */ - public SetFieldStrategy forProperty(final String name) { + public SerializeFieldStrategy forProperty(final String name) { // if property is to be omitted: always-false-strategy if (!isToBeSet(name)) { - return new SetFieldStrategy() { + return new SerializeFieldStrategy() { @Override public boolean isToBeSet(final String field) { return false; @@ -111,7 +111,7 @@ public class SetFieldStrategy { * <p>This is the case when the selections are deeply nested but only the very last segments * are actually used, e.g ["a.b.c.d1", "a.b.c.d2"]. */ - return new SetFieldStrategy() { + return new SerializeFieldStrategy() { // Return true for everything except version fields. @Override public boolean isToBeSet(String field) { @@ -119,7 +119,7 @@ public class SetFieldStrategy { } }; } - return new SetFieldStrategy(subselections); + return new SerializeFieldStrategy(subselections); } public boolean isToBeSet(final String field) { @@ -135,9 +135,11 @@ public class SetFieldStrategy { if (this.cache == null) { this.cache = new HashMap<String, Boolean>(); - // always include the id and the name + // always include the id, version, role and the name this.cache.put("id", true); + this.cache.put("version", true); this.cache.put("name", true); + this.cache.put("role", true); // ... and the referenced entity. this.cache.put("_referenced", true); diff --git a/src/main/java/org/caosdb/server/entity/xml/ToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/ToElementStrategy.java index 81a7074c90df84f88ff3104c84662cb9a7a56433..01e114a25253865e164ca02d6cf42690c57cca0b 100644 --- a/src/main/java/org/caosdb/server/entity/xml/ToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/ToElementStrategy.java @@ -27,8 +27,8 @@ import org.jdom2.Element; public interface ToElementStrategy { - public Element toElement(EntityInterface entity, SetFieldStrategy setFieldStrategy); + public Element toElement(EntityInterface entity, SerializeFieldStrategy setFieldStrategy); public Element addToElement( - EntityInterface entity, Element parent, SetFieldStrategy setFieldStrategy); + EntityInterface entity, Element parent, SerializeFieldStrategy setFieldStrategy); } diff --git a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java index d9ac193c104c9cb643897a0cabc97ff2f42cbb9a..40fda9d8af48aa0b5736c328d7d2f2c3353c9a1d 100644 --- a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java +++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java @@ -24,6 +24,8 @@ package org.caosdb.server.grpc; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; import java.util.TimeZone; import org.caosdb.api.entity.v1.AtomicDataType; import org.caosdb.api.entity.v1.CollectionValues; @@ -69,8 +71,8 @@ import org.caosdb.server.entity.Message; import org.caosdb.server.entity.Role; import org.caosdb.server.entity.StatementStatus; import org.caosdb.server.entity.container.ParentContainer; -import org.caosdb.server.entity.container.PropertyContainer; import org.caosdb.server.entity.wrapper.Property; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.permissions.EntityACI; import org.caosdb.server.permissions.EntityPermission; @@ -87,7 +89,7 @@ public class CaosDBToGrpcConverters { final Iterator<Property> iterator = entity.getProperties().iterator(); while (iterator.hasNext()) { final Property p = iterator.next(); - if (MagicTypes.UNIT.getId() == p.getId()) { + if (Objects.equals(MagicTypes.UNIT.getId(), p.getId())) { iterator.remove(); return p.getValue().toString(); } @@ -97,24 +99,27 @@ public class CaosDBToGrpcConverters { public EntityResponse.Builder convert(final EntityInterface from) { + // @review Florian Spreckelsen 2022-03-22 + + SerializeFieldStrategy s = from.getSerializeFieldStrategy(); final Builder entityBuilder = Entity.newBuilder(); - if (from.hasId()) { + if (from.hasId() && s.isToBeSet("id")) { entityBuilder.setId(Integer.toString(from.getId())); } - if (from.getRole() != null) { + if (from.getRole() != null && s.isToBeSet("role")) { entityBuilder.setRole(convert(from.getRole())); } - if (from.hasName()) { + if (from.hasName() && s.isToBeSet("name")) { entityBuilder.setName(from.getName()); } - if (from.hasDescription()) { + if (from.hasDescription() && s.isToBeSet("description")) { entityBuilder.setDescription(from.getDescription()); } - if (from.hasDatatype()) { + if (from.hasDatatype() && s.isToBeSet("datatype")) { entityBuilder.setDataType(convert(from.getDatatype())); } - if (from.hasValue()) { + if (from.hasValue() && s.isToBeSet("value")) { try { from.parseValue(); } catch (final Message e) { @@ -125,17 +130,20 @@ public class CaosDBToGrpcConverters { entityBuilder.setValue(convert(from.getValue())); } final String unit = getStringUnit(from); - if (unit != null) { + if (unit != null && s.isToBeSet("unit")) { entityBuilder.setUnit(unit); } if (from.hasProperties()) { - entityBuilder.addAllProperties(convert(from.getProperties())); + entityBuilder.addAllProperties(convertProperties(from)); } - if (from.hasParents()) { + if (from.hasParents() && s.isToBeSet("parent")) { entityBuilder.addAllParents(convert(from.getParents())); } if (from.hasFileProperties()) { - entityBuilder.setFileDescriptor(convert(from.getFileProperties())); + FileDescriptor.Builder fileDescriptor = convert(s, from.getFileProperties()); + if (fileDescriptor != null) { + entityBuilder.setFileDescriptor(fileDescriptor); + } } final EntityResponse.Builder responseBuilder = EntityResponse.newBuilder(); @@ -146,10 +154,19 @@ public class CaosDBToGrpcConverters { return responseBuilder; } - private FileDescriptor.Builder convert(FileProperties fileProperties) { - FileDescriptor.Builder result = FileDescriptor.newBuilder(); - result.setPath(fileProperties.getPath()); - result.setSize(fileProperties.getSize()); + private FileDescriptor.Builder convert(SerializeFieldStrategy s, FileProperties fileProperties) { + // @review Florian Spreckelsen 2022-03-22 + FileDescriptor.Builder result = null; + if (s.isToBeSet("path")) { + result = FileDescriptor.newBuilder(); + result.setPath(fileProperties.getPath()); + } + if (s.isToBeSet("size")) { + if (result == null) { + result = FileDescriptor.newBuilder(); + } + result.setSize(fileProperties.getSize()); + } return result; } @@ -213,26 +230,28 @@ public class CaosDBToGrpcConverters { } public org.caosdb.api.entity.v1.Property convert(final Property from) { + // @review Florian Spreckelsen 2022-03-22 final org.caosdb.api.entity.v1.Property.Builder builder = org.caosdb.api.entity.v1.Property.newBuilder(); - if (from.hasId()) { + SerializeFieldStrategy s = from.getSerializeFieldStrategy(); + if (from.hasId() && s.isToBeSet("id")) { builder.setId(from.getId().toString()); } - if (from.hasName()) { + if (from.hasName() && s.isToBeSet("name")) { builder.setName(from.getName()); } - if (from.hasDescription()) { + if (from.hasDescription() && s.isToBeSet("description")) { builder.setDescription(from.getDescription()); } - if (from.hasDatatype()) { + if (from.hasDatatype() && s.isToBeSet("datatype")) { builder.setDataType(convert(from.getDatatype())); } final String unit = getStringUnit(from); - if (unit != null) { + if (unit != null && s.isToBeSet("unit")) { builder.setUnit(unit); } - if (from.hasValue()) { + if (from.hasValue() && s.isToBeSet("value")) { try { from.parseValue(); } catch (final Message e) { @@ -242,7 +261,9 @@ public class CaosDBToGrpcConverters { } builder.setValue(convert(from.getValue())); } - builder.setImportance(convert(from.getStatementStatus())); + if (s.isToBeSet("importance")) { + builder.setImportance(convert(from.getStatementStatus())); + } return builder.build(); } @@ -429,20 +450,42 @@ public class CaosDBToGrpcConverters { return ReferenceDataType.newBuilder().setName(datatype.getName()); } - public Iterable<? extends org.caosdb.api.entity.v1.Property> convert( - final PropertyContainer from) { - final Iterator<org.caosdb.server.entity.wrapper.Property> iterator = from.iterator(); + public Iterable<? extends org.caosdb.api.entity.v1.Property> convertProperties( + final EntityInterface from) { + // @review Florian Spreckelsen 2022-03-22 + final Iterator<org.caosdb.server.entity.wrapper.Property> iterator = + from.getProperties().iterator(); return () -> new Iterator<>() { + private Property property; + @Override public boolean hasNext() { - return iterator.hasNext(); + while (iterator.hasNext()) { + this.property = iterator.next(); + if (from.getSerializeFieldStrategy().isToBeSet(this.property.getName())) { + this.property.setSerializeFieldStrategy( + from.getSerializeFieldStrategy().forProperty(this.property)); + return true; + } + } + return false; } @Override public org.caosdb.api.entity.v1.Property next() { - return convert(iterator.next()); + if (this.property == null) { + // trigger this.property to be non-null + if (!hasNext()) { + throw new NoSuchElementException("The iterator has no more elements."); + } + } + + Property next_property = this.property; + this.property = null; + + return convert(next_property); } }; } @@ -466,26 +509,30 @@ public class CaosDBToGrpcConverters { public void appendMessages( final EntityInterface from, final org.caosdb.api.entity.v1.EntityResponse.Builder builder) { - if (from.hasMessage(Message.MessageType.Error.toString())) { + // @review Florian Spreckelsen 2022-03-22 + SerializeFieldStrategy s = from.getSerializeFieldStrategy(); + if (from.hasMessage(Message.MessageType.Error.toString()) && s.isToBeSet("error")) { builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString()))); } - if (from.hasMessage(Message.MessageType.Warning.toString())) { + if (from.hasMessage(Message.MessageType.Warning.toString()) && s.isToBeSet("warning")) { builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString()))); } - if (from.hasMessage(Message.MessageType.Info.toString())) { + if (from.hasMessage(Message.MessageType.Info.toString()) && s.isToBeSet("info")) { builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString()))); } } public void appendMessages( final EntityInterface from, final org.caosdb.api.entity.v1.IdResponse.Builder builder) { - if (from.hasMessage(Message.MessageType.Error.toString())) { + // @review Florian Spreckelsen 2022-03-22 + SerializeFieldStrategy s = from.getSerializeFieldStrategy(); + if (from.hasMessage(Message.MessageType.Error.toString()) && s.isToBeSet("error")) { builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString()))); } - if (from.hasMessage(Message.MessageType.Warning.toString())) { + if (from.hasMessage(Message.MessageType.Warning.toString()) && s.isToBeSet("warning")) { builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString()))); } - if (from.hasMessage(Message.MessageType.Info.toString())) { + if (from.hasMessage(Message.MessageType.Info.toString()) && s.isToBeSet("info")) { builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString()))); } } diff --git a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java index c234e61048ba7af730dd7928d0b64ff587c005cc..50845c5456c98ee59a1b4d1a05bae0e84d712774 100644 --- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java +++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.TimeZone; import java.util.UUID; import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.AuthenticationException; import org.caosdb.api.entity.v1.DeleteRequest; import org.caosdb.api.entity.v1.DeleteResponse; import org.caosdb.api.entity.v1.Entity; @@ -52,10 +53,12 @@ import org.caosdb.server.entity.DeleteEntity; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.FileProperties; import org.caosdb.server.entity.InsertEntity; +import org.caosdb.server.entity.Message; import org.caosdb.server.entity.RetrieveEntity; import org.caosdb.server.entity.UpdateEntity; import org.caosdb.server.entity.container.RetrieveContainer; import org.caosdb.server.entity.container.WritableContainer; +import org.caosdb.server.permissions.EntityPermission; import org.caosdb.server.transaction.Retrieve; import org.caosdb.server.transaction.RetrieveACL; import org.caosdb.server.transaction.UpdateACL; @@ -83,6 +86,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa * @throws Exception */ public MultiTransactionResponse retrieve(final MultiTransactionRequest request) throws Exception { + // @review Florian Spreckelsen 2022-03-22 final MultiTransactionResponse.Builder builder = MultiTransactionResponse.newBuilder(); final RetrieveContainer container = new RetrieveContainer( @@ -136,13 +140,19 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa final EntityResponse.Builder entityResponse = caosdbToGrpc.convert(entity); if ((download_files_container || entity.getFlags().containsKey("download_files")) && entity.hasFileProperties()) { - if (fileDownload == null) { - fileDownload = fileTransmissionService.registerFileDownload(null); + try { + entity.checkPermission(EntityPermission.RETRIEVE_FILE); + if (fileDownload == null) { + fileDownload = fileTransmissionService.registerFileDownload(null); + } + entity.getFileProperties().retrieveFromFileSystem(); + entityResponse.setDownloadId( + fileTransmissionService.registerFileDownload( + fileDownload.getId(), entity.getFileProperties())); + } catch (AuthenticationException exc) { + entityResponse.addErrors(caosdbToGrpc.convert(ServerMessages.AUTHORIZATION_ERROR)); + entityResponse.addInfos(caosdbToGrpc.convert(new Message(exc.getMessage()))); } - entity.getFileProperties().retrieveFromFileSystem(); - entityResponse.setDownloadId( - fileTransmissionService.registerFileDownload( - fileDownload.getId(), entity.getFileProperties())); } builder .addResponsesBuilder() diff --git a/src/main/java/org/caosdb/server/transaction/Retrieve.java b/src/main/java/org/caosdb/server/transaction/Retrieve.java index 45647c1d554d38ab2b90e91f9516305265d370b8..86b7672cf9ebc0ad8e74f3974ee89174532d9f73 100644 --- a/src/main/java/org/caosdb/server/transaction/Retrieve.java +++ b/src/main/java/org/caosdb/server/transaction/Retrieve.java @@ -27,9 +27,7 @@ import org.caosdb.server.database.access.Access; import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransaction; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.container.RetrieveContainer; -import org.caosdb.server.entity.xml.SetFieldStrategy; -import org.caosdb.server.entity.xml.ToElementStrategy; -import org.caosdb.server.entity.xml.ToElementable; +import org.caosdb.server.entity.xml.IdAndServerMessagesOnlyStrategy; import org.caosdb.server.jobs.ScheduledJob; import org.caosdb.server.jobs.core.JobFailureSeverity; import org.caosdb.server.jobs.core.RemoveDuplicates; @@ -37,7 +35,6 @@ import org.caosdb.server.jobs.core.ResolveNames; import org.caosdb.server.permissions.EntityPermission; import org.caosdb.server.utils.EntityStatus; import org.caosdb.server.utils.ServerMessages; -import org.jdom2.Element; public class Retrieve extends Transaction<RetrieveContainer> { @@ -80,40 +77,15 @@ public class Retrieve extends Transaction<RetrieveContainer> { @Override protected void postTransaction() { + // @review Florian Spreckelsen 2022-03-22 + // generate Error for missing RETRIEVE:ENTITY Permission. for (final EntityInterface e : getContainer()) { - if (e.getEntityACL() != null) { + if (e.hasEntityACL()) { try { e.checkPermission(EntityPermission.RETRIEVE_ENTITY); } catch (final AuthorizationException exc) { - e.setToElementStragegy( - new ToElementStrategy() { - - @Override - public Element toElement( - final EntityInterface entity, final SetFieldStrategy setFieldStrategy) { - Element ret; - if (entity.hasRole()) { - ret = new Element(entity.getRole().toString()); - } else { - ret = new Element("Entity"); - } - ret.setAttribute("id", entity.getId().toString()); - for (final ToElementable m : entity.getMessages()) { - m.addToElement(ret); - } - return ret; - } - - @Override - public Element addToElement( - final EntityInterface entity, - final Element parent, - final SetFieldStrategy setFieldStrategy) { - parent.addContent(toElement(entity, setFieldStrategy)); - return parent; - } - }); + e.setSerializeFieldStrategy(new IdAndServerMessagesOnlyStrategy()); e.setEntityStatus(EntityStatus.UNQUALIFIED); e.addError(ServerMessages.AUTHORIZATION_ERROR); e.addInfo(exc.getMessage()); diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java index 916e0cec02f6ce60783360e969255f120c9c1589..3497f912c33a69716a701f6f0d15af732d63870f 100644 --- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java @@ -420,7 +420,7 @@ public class WriteTransaction extends Transaction<WritableContainer> try { newEntity.parseValue(); oldEntity.parseValue(); - } catch (NullPointerException|Message m) { + } catch (NullPointerException | Message m) { // ignore, parsing is handled elsewhere } if (!newEntity.getValue().equals(oldEntity.getValue())) { diff --git a/src/test/java/org/caosdb/server/entity/SelectionTest.java b/src/test/java/org/caosdb/server/entity/SelectionTest.java index 0ede3a970be6504ef0a89868aed40e4cadb141d0..26fbf413d42e66ccb5c65759a65dbb08a9d94df5 100644 --- a/src/test/java/org/caosdb/server/entity/SelectionTest.java +++ b/src/test/java/org/caosdb/server/entity/SelectionTest.java @@ -30,7 +30,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; import org.caosdb.server.CaosDBServer; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.caosdb.server.query.Query; import org.caosdb.server.query.Query.Selection; import org.junit.Assert; @@ -46,7 +46,7 @@ public class SelectionTest { @Test public void testEmpty1() { - final SetFieldStrategy setFieldStrategy = new SetFieldStrategy(); + final SerializeFieldStrategy setFieldStrategy = new SerializeFieldStrategy(); Assert.assertTrue(setFieldStrategy.isToBeSet("id")); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); @@ -64,7 +64,8 @@ public class SelectionTest { @Test public void testName1() { final Selection selection = new Selection("name"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -72,7 +73,8 @@ public class SelectionTest { @Test public void testName2() { final Selection selection = new Selection("id"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -80,7 +82,8 @@ public class SelectionTest { @Test public void testName3() { final Selection selection = new Selection("value"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -88,7 +91,8 @@ public class SelectionTest { @Test public void testName4() { final Selection selection = new Selection("description"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -96,7 +100,8 @@ public class SelectionTest { @Test public void testName5() { final Selection selection = new Selection("datatype"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -104,7 +109,8 @@ public class SelectionTest { @Test public void testName6() { final Selection selection = new Selection("datatype"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -112,7 +118,8 @@ public class SelectionTest { @Test public void testName7() { final Selection selection = new Selection("blabla"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); } @@ -120,7 +127,8 @@ public class SelectionTest { @Test public void testId1() { final Selection selection = new Selection("id"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("id")); } @@ -128,7 +136,8 @@ public class SelectionTest { @Test public void testId2() { final Selection selection = new Selection("name"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("id")); } @@ -136,7 +145,8 @@ public class SelectionTest { @Test public void testId3() { final Selection selection = new Selection("description"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("id")); } @@ -144,7 +154,8 @@ public class SelectionTest { @Test public void testId4() { final Selection selection = new Selection("blablabla"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("id")); } @@ -152,7 +163,8 @@ public class SelectionTest { @Test public void testDesc1() { final Selection selection = new Selection("description"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertTrue(setFieldStrategy.isToBeSet("description")); } @@ -160,7 +172,8 @@ public class SelectionTest { @Test public void testDesc2() { final Selection selection = new Selection("name"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertFalse(setFieldStrategy.isToBeSet("description")); } @@ -168,7 +181,8 @@ public class SelectionTest { @Test public void testDesc3() { final Selection selection = new Selection("id"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertFalse(setFieldStrategy.isToBeSet("description")); } @@ -176,15 +190,16 @@ public class SelectionTest { @Test public void testDesc4() { final Selection selection = new Selection("blablaba"); - final SetFieldStrategy setFieldStrategy = (new SetFieldStrategy()).addSelection(selection); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(selection); Assert.assertFalse(setFieldStrategy.isToBeSet("description")); } @Test public void testMulti1() { - final SetFieldStrategy setFieldStrategy = - (new SetFieldStrategy()) + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()) .addSelection(new Selection("id")) .addSelection(new Selection("name")); @@ -196,8 +211,8 @@ public class SelectionTest { @Test public void testMulti2() { - final SetFieldStrategy setFieldStrategy = - (new SetFieldStrategy()) + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()) .addSelection(new Selection("id")) .addSelection(new Selection("description")); @@ -210,8 +225,8 @@ public class SelectionTest { @Test public void testMulti3() { - final SetFieldStrategy setFieldStrategy = - (new SetFieldStrategy()) + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()) .addSelection(new Selection("datatype")) .addSelection(new Selection("description")); @@ -224,8 +239,8 @@ public class SelectionTest { @Test public void testMulti4() { - final SetFieldStrategy setFieldStrategy = - (new SetFieldStrategy()) + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()) .addSelection(new Selection("datatype")) .addSelection(new Selection("value")); @@ -238,15 +253,15 @@ public class SelectionTest { @Test public void testComposition1() { - final SetFieldStrategy setFieldStrategy = - (new SetFieldStrategy()).addSelection(new Selection("blabla")); + final SerializeFieldStrategy setFieldStrategy = + (new SerializeFieldStrategy()).addSelection(new Selection("blabla")); Assert.assertTrue(setFieldStrategy.isToBeSet("blabla")); Assert.assertTrue(setFieldStrategy.isToBeSet("id")); Assert.assertTrue(setFieldStrategy.isToBeSet("name")); Assert.assertFalse(setFieldStrategy.isToBeSet("bleb")); - final SetFieldStrategy forProperty = setFieldStrategy.forProperty("blabla"); + final SerializeFieldStrategy forProperty = setFieldStrategy.forProperty("blabla"); Assert.assertTrue(forProperty.isToBeSet("id")); Assert.assertTrue(forProperty.isToBeSet("name")); Assert.assertTrue(forProperty.isToBeSet("blub")); @@ -254,8 +269,8 @@ public class SelectionTest { @Test public void testComposition2() { - final SetFieldStrategy setFieldStrategy = - new SetFieldStrategy() + final SerializeFieldStrategy setFieldStrategy = + new SerializeFieldStrategy() .addSelection(new Selection("blabla")) .addSelection(new Selection("blabla.name")); @@ -264,7 +279,7 @@ public class SelectionTest { Assert.assertTrue(setFieldStrategy.isToBeSet("name")); Assert.assertFalse(setFieldStrategy.isToBeSet("bleb")); - final SetFieldStrategy forProperty = setFieldStrategy.forProperty("blabla"); + final SerializeFieldStrategy forProperty = setFieldStrategy.forProperty("blabla"); Assert.assertTrue(forProperty.isToBeSet("id")); Assert.assertTrue(forProperty.isToBeSet("name")); Assert.assertTrue(forProperty.isToBeSet("blub")); @@ -272,8 +287,8 @@ public class SelectionTest { @Test public void testComposition3() { - final SetFieldStrategy setFieldStrategy = - new SetFieldStrategy() + final SerializeFieldStrategy setFieldStrategy = + new SerializeFieldStrategy() .addSelection(new Selection("blabla").setSubSelection(new Selection("value"))) .addSelection(new Selection("blabla").setSubSelection(new Selection("description"))); @@ -282,7 +297,7 @@ public class SelectionTest { assertTrue(setFieldStrategy.isToBeSet("name")); assertFalse(setFieldStrategy.isToBeSet("bleb")); - final SetFieldStrategy forProperty = setFieldStrategy.forProperty("blabla"); + final SerializeFieldStrategy forProperty = setFieldStrategy.forProperty("blabla"); assertTrue(forProperty.isToBeSet("id")); assertTrue(forProperty.isToBeSet("name")); assertTrue(forProperty.isToBeSet("description")); @@ -312,7 +327,7 @@ public class SelectionTest { assertEquals(s.toString(), "property.subproperty.subsubproperty"); - SetFieldStrategy setFieldStrategy = new SetFieldStrategy().addSelection(s); + SerializeFieldStrategy setFieldStrategy = new SerializeFieldStrategy().addSelection(s); assertTrue(setFieldStrategy.isToBeSet("property")); assertFalse(setFieldStrategy.forProperty("property").isToBeSet("sadf")); // assertFalse(setFieldStrategy.forProperty("property").isToBeSet("name")); diff --git a/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java b/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java index 0428af146f7b4a191fa6be679e01af45aff315f2..a65d2bccb61c787ee6fed4663f97b0b84e1d98c0 100644 --- a/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java +++ b/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java @@ -30,7 +30,7 @@ import org.caosdb.server.entity.Entity; import org.caosdb.server.entity.Role; import org.caosdb.server.entity.wrapper.Property; import org.caosdb.server.entity.xml.PropertyToElementStrategyTest; -import org.caosdb.server.entity.xml.SetFieldStrategy; +import org.caosdb.server.entity.xml.SerializeFieldStrategy; import org.jdom2.Element; import org.junit.BeforeClass; import org.junit.Test; @@ -70,8 +70,9 @@ public class PropertyContainerTest { public void test() { PropertyContainer container = new PropertyContainer(new Entity()); Element element = new Element("Record"); - SetFieldStrategy setFieldStrategy = - new SetFieldStrategy().addSelection(PropertyToElementStrategyTest.parse("window.height")); + SerializeFieldStrategy setFieldStrategy = + new SerializeFieldStrategy() + .addSelection(PropertyToElementStrategyTest.parse("window.height")); container.addToElement(windowProperty, element, setFieldStrategy); diff --git a/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java b/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java index 436278ad640663ba42f71b824924b2f1293a5132..fa8469dba9d95b70d77dcf0428e4426ff1672548 100644 --- a/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java +++ b/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java @@ -88,7 +88,8 @@ public class PropertyToElementStrategyTest { @Test public void test() { PropertyToElementStrategy strategy = new PropertyToElementStrategy(); - SetFieldStrategy setFieldStrategy = new SetFieldStrategy().addSelection(parse("height")); + SerializeFieldStrategy setFieldStrategy = + new SerializeFieldStrategy().addSelection(parse("height")); EntityInterface property = windowProperty; ((ReferenceValue) property.getValue()).setEntity(window, true); Element element = strategy.toElement(property, setFieldStrategy); diff --git a/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java b/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java index 6b21c9b1a5aa4afbe4b018029bf938ae2edd997e..84baba26fbadb920320b8d22a789509e855f9693 100644 --- a/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java +++ b/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java @@ -2,12 +2,20 @@ package org.caosdb.server.grpc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.util.TimeZone; import org.caosdb.datetime.DateTimeFactory2; +import org.caosdb.server.datatype.GenericValue; import org.caosdb.server.datatype.Value; import org.caosdb.server.entity.FileProperties; +import org.caosdb.server.entity.Message; import org.caosdb.server.entity.RetrieveEntity; +import org.caosdb.server.entity.Role; +import org.caosdb.server.entity.StatementStatus; +import org.caosdb.server.entity.wrapper.Parent; +import org.caosdb.server.entity.wrapper.Property; +import org.caosdb.server.entity.xml.IdAndServerMessagesOnlyStrategy; import org.junit.Test; public class CaosDBToGrpcConvertersTest { @@ -53,4 +61,43 @@ public class CaosDBToGrpcConvertersTest { converters.convert(entity).toString(), "entity {\n file_descriptor {\n path: \"the/path\"\n size: 1024\n }\n}\n"); } + + @Test + public void testIdServerMessagesOnlyStrategy() { + // @review Florian Spreckelsen 2022-03-22 + RetrieveEntity entity = new RetrieveEntity(null); + + // must be printed + entity.setId(1234); + entity.addInfo("info"); + entity.addWarning(new Message("warning")); + entity.addError(new Message("error")); + + // must not be printed + Parent par = new Parent(); + par.setName("dont print parent"); + entity.addParent(par); + entity.setName("dont print"); + entity.setDescription("dont print"); + entity.setRole(Role.File); + entity.setFileProperties(new FileProperties("dont print checksum", "dont print path", 1234L)); + Property p = new Property(); + p.setStatementStatus(StatementStatus.FIX); + p.setName("dont print property"); + p.setDatatype("TEXT"); + p.setValue(new GenericValue("don print")); + entity.addProperty(p); + + CaosDBToGrpcConverters converters = new CaosDBToGrpcConverters(null); + + // first test the normal SerializeFieldStrategy instead + entity.setSerializeFieldStrategy(null); + assertTrue(converters.convert(entity).toString().contains("dont print")); + + // now suppress all fields but id and server messages. + entity.setSerializeFieldStrategy(new IdAndServerMessagesOnlyStrategy()); + assertEquals( + converters.convert(entity).toString(), + "entity {\n id: \"1234\"\n}\nerrors {\n code: 1\n description: \"error\"\n}\nwarnings {\n code: 1\n description: \"warning\"\n}\ninfos {\n code: 1\n description: \"info\"\n}\n"); + } } diff --git a/src/test/java/org/caosdb/server/transaction/RetrieveTest.java b/src/test/java/org/caosdb/server/transaction/RetrieveTest.java new file mode 100644 index 0000000000000000000000000000000000000000..08c41ba4a2346058d9d2da587dd7c26930ad2896 --- /dev/null +++ b/src/test/java/org/caosdb/server/transaction/RetrieveTest.java @@ -0,0 +1,79 @@ +package org.caosdb.server.transaction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import org.caosdb.server.CaosDBServer; +import org.caosdb.server.ServerProperties; +import org.caosdb.server.accessControl.AnonymousAuthenticationToken; +import org.caosdb.server.accessControl.Role; +import org.caosdb.server.database.BackendTransaction; +import org.caosdb.server.database.access.Access; +import org.caosdb.server.database.backend.interfaces.RetrieveRoleImpl; +import org.caosdb.server.database.exceptions.TransactionException; +import org.caosdb.server.database.misc.TransactionBenchmark; +import org.caosdb.server.entity.EntityInterface; +import org.caosdb.server.entity.RetrieveEntity; +import org.caosdb.server.entity.container.RetrieveContainer; +import org.caosdb.server.entity.xml.IdAndServerMessagesOnlyStrategy; +import org.caosdb.server.permissions.EntityACLFactory; +import org.caosdb.server.utils.EntityStatus; +import org.caosdb.server.utils.ServerMessages; +import org.junit.BeforeClass; +import org.junit.Test; + +public class RetrieveTest { + + // @review Florian Spreckelsen 2022-03-22 + @BeforeClass + public static void setup() throws IOException { + CaosDBServer.initServerProperties(); + CaosDBServer.setProperty(ServerProperties.KEY_AUTH_OPTIONAL, "TRUE"); + CaosDBServer.initShiro(); + + BackendTransaction.setImpl(RetrieveRoleImpl.class, RetrieveRoleMockup.class); + } + + /** a mock-up which returns null */ + public static class RetrieveRoleMockup implements RetrieveRoleImpl { + + public RetrieveRoleMockup(Access a) {} + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) {} + + @Override + public TransactionBenchmark getBenchmark() { + return null; + } + + @Override + public Role retrieve(String role) throws TransactionException { + return null; + } + } + + @Test + public void testMissingRetrievePermission() { + Subject subject = SecurityUtils.getSubject(); + subject.login(AnonymousAuthenticationToken.getInstance()); + EntityInterface entity = new RetrieveEntity(1234); + EntityACLFactory fac = new EntityACLFactory(); + fac.deny(AnonymousAuthenticationToken.PRINCIPAL, "RETRIEVE:ENTITY"); + entity.setEntityACL(fac.create()); + RetrieveContainer container = new RetrieveContainer(null, null, null, null); + assertTrue(entity.getMessages().isEmpty()); + assertEquals(entity.getEntityStatus(), EntityStatus.QUALIFIED); + container.add(entity); + Retrieve retrieve = new Retrieve(container); + retrieve.postTransaction(); + assertFalse(entity.getMessages().isEmpty()); + assertEquals(entity.getMessages("error").get(0), ServerMessages.AUTHORIZATION_ERROR); + assertEquals(entity.getEntityStatus(), EntityStatus.UNQUALIFIED); + assertTrue(entity.getSerializeFieldStrategy() instanceof IdAndServerMessagesOnlyStrategy); + } +}