diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b65bafc9f260dabecd592fea4f08829f08db7c4..9948b8cdabdbb58f7a365b50e0ba88173560d5e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* `Entity/names` resource for retrieving all known entity names. - Scripting is simplified by adding a `home` directory, of which a copy is created for each called script and set as the `HOME` environment variable. - [bend_symlinks.sh](misc/bend_symlinks/bend_symlinks.sh) (version 0.1, experimental) diff --git a/RELEASE_GUIDELINES.md b/RELEASE_GUIDELINES.md new file mode 100644 index 0000000000000000000000000000000000000000..234ff24f40e9c281bfeb23703864c39369aaea05 --- /dev/null +++ b/RELEASE_GUIDELINES.md @@ -0,0 +1,27 @@ +# Release Guidelines for the CaosDB MySQL Backend + +This document specifies release guidelines in addition to the generel release +guidelines of the CaosDB Project +([RELEASE_GUIDELINES.md](https://gitlab.com/caosdb/caosdb/blob/dev/RELEASE_GUIDELINES.md)) + +## General Prerequisites + +* All tests are passing. +* FEATURES.md is up-to-date and a public API is being declared in that document. +* CHANGELOG.md is up-to-date. +* DEPENDENCIES.md is up-to-date. + +## Steps + +1. Create a release branch from the dev branch. This prevents further changes + to the code base and a never ending release process. Naming: `release-<VERSION>` + +2. Check all general prerequisites. + +4. Merge the release branch into the master branch. + +5. Tag the latest commit of the master branch with `v<VERSION>`. + +6. Delete the release branch. + +7. Merge the master branch back into the dev branch. diff --git a/caosdb-webui b/caosdb-webui index 7d67a76f1ceede440a2d4dad4db8dcbd0d61b9ed..9975365e07e601efc55903e6f75a41ef63902fce 160000 --- a/caosdb-webui +++ b/caosdb-webui @@ -1 +1 @@ -Subproject commit 7d67a76f1ceede440a2d4dad4db8dcbd0d61b9ed +Subproject commit 9975365e07e601efc55903e6f75a41ef63902fce diff --git a/makefile b/makefile index 49c65fbf7cd92e2100bd41d337464ee8e9033a3d..98825d4baeb85f497d9825d651f2afbad1e92f7d 100644 --- a/makefile +++ b/makefile @@ -38,6 +38,9 @@ run: compile run-debug: jar java -Xrunjdwp:transport=dt_socket,address=0.0.0.0:$(JPDA_PORT),server=y,suspend=n -Dcaosdb.debug=true -jar target/caosdb-server-0.1-SNAPSHOT-jar-with-dependencies.jar +run-debug-single: + java -Xrunjdwp:transport=dt_socket,address=0.0.0.0:$(JPDA_PORT),server=y,suspend=n -Dcaosdb.debug=true -jar target/caosdb-server-0.1-SNAPSHOT-jar-with-dependencies.jar + run-single: java -jar target/caosdb-server-0.1-SNAPSHOT-jar-with-dependencies.jar diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java index b725ab73e87d34345cf7bba2be605033561efef9..34bfe3e2911955fa724ea5e6ac7258d80f9cc120 100644 --- a/src/main/java/caosdb/server/CaosDBServer.java +++ b/src/main/java/caosdb/server/CaosDBServer.java @@ -54,6 +54,7 @@ import caosdb.server.resource.UserResource; import caosdb.server.resource.UserRolesResource; import caosdb.server.resource.Webinterface; import caosdb.server.resource.WebinterfaceBuildNumber; +import caosdb.server.resource.transaction.EntityNamesResource; import caosdb.server.resource.transaction.EntityResource; import caosdb.server.terminal.CaosDBTerminal; import caosdb.server.terminal.StatsPanel; @@ -632,6 +633,8 @@ public class CaosDBServer extends Application { authenticator.setNext(authorizer); protectedRouter.attach("/scripting", ScriptingResource.class); + protectedRouter.attach("/Entities/names", EntityNamesResource.class); + protectedRouter.attach("/Entity/names", EntityNamesResource.class); protectedRouter.attach("/Entities", EntityResource.class); protectedRouter.attach("/Entities/", EntityResource.class); protectedRouter.attach("/Entities/{specifier}", EntityResource.class); diff --git a/src/main/java/caosdb/server/database/BackendTransaction.java b/src/main/java/caosdb/server/database/BackendTransaction.java index 896491bfba98390fb4c9fdf7ddde4c0ee56e3f6a..14e65e86bd9fe05b074c731e27b601fa4ed51f68 100644 --- a/src/main/java/caosdb/server/database/BackendTransaction.java +++ b/src/main/java/caosdb/server/database/BackendTransaction.java @@ -28,6 +28,7 @@ import caosdb.server.database.backend.implementation.MySQL.MySQLDeletePassword; import caosdb.server.database.backend.implementation.MySQL.MySQLDeleteRole; import caosdb.server.database.backend.implementation.MySQL.MySQLDeleteSparseEntity; import caosdb.server.database.backend.implementation.MySQL.MySQLDeleteUser; +import caosdb.server.database.backend.implementation.MySQL.MySQLGetAllNames; import caosdb.server.database.backend.implementation.MySQL.MySQLGetChildren; import caosdb.server.database.backend.implementation.MySQL.MySQLGetDependentEntities; import caosdb.server.database.backend.implementation.MySQL.MySQLGetFileRecordByPath; @@ -81,6 +82,7 @@ import caosdb.server.database.backend.interfaces.FileCheckHash; import caosdb.server.database.backend.interfaces.FileCheckSize; import caosdb.server.database.backend.interfaces.FileExists; import caosdb.server.database.backend.interfaces.FileWasModifiedAfter; +import caosdb.server.database.backend.interfaces.GetAllNamesImpl; import caosdb.server.database.backend.interfaces.GetChildrenImpl; import caosdb.server.database.backend.interfaces.GetDependentEntitiesImpl; import caosdb.server.database.backend.interfaces.GetFileIteratorImpl; @@ -144,8 +146,15 @@ public abstract class BackendTransaction implements Undoable { this.addMeasurement(this, t2 - t1); } + /** + * Intialiaze the adapters to the database backend. + * + * <p>Currently this is hard-coded to the MySQL-Backend but the architecture of this class is + * designed to make it easy in the future to choose other implementations (i.e. other back-ends) + */ public static void init() { if (impl.isEmpty()) { + setImpl(GetAllNamesImpl.class, MySQLGetAllNames.class); setImpl(DeleteEntityPropertiesImpl.class, MySQLDeleteEntityProperties.class); setImpl(DeleteSparseEntityImpl.class, MySQLDeleteSparseEntity.class); setImpl(GetChildrenImpl.class, MySQLGetChildren.class); diff --git a/src/main/java/caosdb/server/database/DatabaseUtils.java b/src/main/java/caosdb/server/database/DatabaseUtils.java index 7c50f47a01a8528cd078b87eebbe9495d6ebaaa4..84c38fa448b7d8a1035aa28ded7bbfcecc5a88b3 100644 --- a/src/main/java/caosdb/server/database/DatabaseUtils.java +++ b/src/main/java/caosdb/server/database/DatabaseUtils.java @@ -186,26 +186,44 @@ public class DatabaseUtils { return ret; } + /** + * Helper function for parsing MySQL results. + * + * <p>This function creates SparseEntities and parses only the name, the role and the acl of an + * entity. + * + * <p>Never returns null. + */ + public static SparseEntity parseNameRoleACL(ResultSet rs) throws SQLException { + final SparseEntity ret = new SparseEntity(); + ret.role = bytes2UTF8(rs.getBytes("EntityRole")); + ret.name = bytes2UTF8(rs.getBytes("EntityName")); + ret.acl = bytes2UTF8(rs.getBytes("ACL")); + return ret; + } + + /** + * Helper function for parsing MySQL results. + * + * <p>This function creates SparseEntities and parses all fields which belong to a SparseEntity: + * id, name, role, acl, description, datatype, and the file properties. + * + * <p>Never returns null. + */ public static SparseEntity parseEntityResultSet(final ResultSet rs) throws SQLException { - if (rs.next()) { - final SparseEntity ret = new SparseEntity(); - ret.id = rs.getInt("EntityID"); - ret.name = bytes2UTF8(rs.getBytes("EntityName")); - ret.description = bytes2UTF8(rs.getBytes("EntityDesc")); - ret.role = bytes2UTF8(rs.getBytes("EntityRole")); - ret.datatype = bytes2UTF8(rs.getBytes("Datatype")); - ret.collection = bytes2UTF8(rs.getBytes("Collection")); - ret.acl = bytes2UTF8(rs.getBytes("ACL")); + SparseEntity ret = parseNameRoleACL(rs); + ret.id = rs.getInt("EntityID"); + ret.description = bytes2UTF8(rs.getBytes("EntityDesc")); + ret.datatype = bytes2UTF8(rs.getBytes("Datatype")); + ret.collection = bytes2UTF8(rs.getBytes("Collection")); - final String path = bytes2UTF8(rs.getBytes("FilePath")); - if (!rs.wasNull()) { - ret.filePath = path; - ret.fileSize = rs.getLong("FileSize"); - ret.fileHash = bytes2UTF8(rs.getBytes("FileHash")); - } - return ret; + final String path = bytes2UTF8(rs.getBytes("FilePath")); + if (!rs.wasNull()) { + ret.filePath = path; + ret.fileSize = rs.getLong("FileSize"); + ret.fileHash = bytes2UTF8(rs.getBytes("FileHash")); } - return null; + return ret; } public static ArrayList<VerySparseEntity> parseParentResultSet(final ResultSet rs) diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLGetAllNames.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLGetAllNames.java new file mode 100644 index 0000000000000000000000000000000000000000..d7c641cadebcde93b97187aa7a0ea2ded72d4678 --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLGetAllNames.java @@ -0,0 +1,46 @@ +package caosdb.server.database.backend.implementation.MySQL; + +import caosdb.server.database.DatabaseUtils; +import caosdb.server.database.access.Access; +import caosdb.server.database.backend.interfaces.GetAllNamesImpl; +import caosdb.server.database.exceptions.TransactionException; +import caosdb.server.database.proto.SparseEntity; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** Retrieve name, role and acl of all entities from the MySQL backend. */ +public class MySQLGetAllNames extends MySQLTransaction implements GetAllNamesImpl { + + public MySQLGetAllNames(Access access) { + super(access); + } + + public static final String STMT_GET_ALL_NAMES = + "Select e.name as EntityName, e.role as EntityRole, a.acl as ACL FROM entities as e JOIN entity_acl as a ON (a.id=e.acl) WHERE e.name IS NOT NULL and e.role!='ROLE'"; + + @Override + public List<SparseEntity> execute() { + ArrayList<SparseEntity> ret = new ArrayList<>(); + + try { + PreparedStatement stmt = prepareStatement(STMT_GET_ALL_NAMES); + + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + SparseEntity spe = DatabaseUtils.parseNameRoleACL(resultSet); + ret.add(spe); + } + + } catch (SQLException e1) { + throw new TransactionException(e1); + } + } catch (SQLException | ConnectionException e2) { + throw new TransactionException(e2); + } + + return ret; + } +} diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveSparseEntity.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveSparseEntity.java index 30a07213186703596e1afeae6d4c62b1cd0602be..749b0b91455c9f429821bbabce3aa99375a417cd 100644 --- a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveSparseEntity.java +++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveSparseEntity.java @@ -31,6 +31,11 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +/** + * Retrieve a single SparseEntity by id. + * + * <p>A SparseEntity contains only id, name, role, acl, datatype and the file properties. + */ public class MySQLRetrieveSparseEntity extends MySQLTransaction implements RetrieveSparseEntityImpl { @@ -48,7 +53,9 @@ public class MySQLRetrieveSparseEntity extends MySQLTransaction preparedStatement.setInt(1, id); final ResultSet rs = preparedStatement.executeQuery(); try { - return DatabaseUtils.parseEntityResultSet(rs); + if (rs.next()) { + return DatabaseUtils.parseEntityResultSet(rs); + } } finally { rs.close(); } @@ -57,5 +64,6 @@ public class MySQLRetrieveSparseEntity extends MySQLTransaction } catch (final ConnectionException e) { throw new TransactionException(e); } + return null; } } diff --git a/src/main/java/caosdb/server/database/backend/interfaces/GetAllNamesImpl.java b/src/main/java/caosdb/server/database/backend/interfaces/GetAllNamesImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..3a89e579d2713457c72ec2df73e1c1c936d50db2 --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/interfaces/GetAllNamesImpl.java @@ -0,0 +1,14 @@ +package caosdb.server.database.backend.interfaces; + +import caosdb.server.database.proto.SparseEntity; +import java.util.List; + +/** + * Interface for the retrieval of all known names from the backend. + * + * <p>The returned list contains SparseEntities which have only their name, role and acl defined. + */ +public interface GetAllNamesImpl extends BackendTransactionImpl { + + List<SparseEntity> execute(); +} diff --git a/src/main/java/caosdb/server/database/backend/transaction/GetAllNames.java b/src/main/java/caosdb/server/database/backend/transaction/GetAllNames.java new file mode 100644 index 0000000000000000000000000000000000000000..f30ec5b2b33de6ba7341b26f4e94244f6501255c --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/transaction/GetAllNames.java @@ -0,0 +1,29 @@ +package caosdb.server.database.backend.transaction; + +import caosdb.server.database.BackendTransaction; +import caosdb.server.database.backend.interfaces.GetAllNamesImpl; +import caosdb.server.database.proto.SparseEntity; +import caosdb.server.entity.Entity; +import caosdb.server.entity.EntityInterface; +import java.util.ArrayList; +import java.util.List; + +public class GetAllNames extends BackendTransaction { + + private List<SparseEntity> entities; + + @Override + protected void execute() { + final GetAllNamesImpl t = getImplementation(GetAllNamesImpl.class); + + this.entities = t.execute(); + } + + public List<EntityInterface> getEntities() { + ArrayList<EntityInterface> ret = new ArrayList<>(); + for (SparseEntity e : entities) { + ret.add(new Entity().parseSparseEntity(e)); + } + return ret; + } +} diff --git a/src/main/java/caosdb/server/entity/Entity.java b/src/main/java/caosdb/server/entity/Entity.java index bf1022dad1c0e6b954ea876ecce674a87ff7650e..19cd930706e3f3aa691853b020f000191ed8d142 100644 --- a/src/main/java/caosdb/server/entity/Entity.java +++ b/src/main/java/caosdb/server/entity/Entity.java @@ -100,7 +100,7 @@ public class Entity extends AbstractObservable implements EntityInterface { @Override public void checkPermission(final Subject subject, final Permission permission) { try { - if (!this.entityACL.isPermitted(subject, permission)) { + if (!this.hasPermission(subject, permission)) { throw new AuthorizationException( subject.getPrincipal().toString() + " doesn't have permission " @@ -117,6 +117,17 @@ public class Entity extends AbstractObservable implements EntityInterface { checkPermission(subject, permission); } + @Override + public boolean hasPermission(Permission permission) { + final Subject subject = SecurityUtils.getSubject(); + return hasPermission(subject, permission); + } + + @Override + public boolean hasPermission(Subject subject, Permission permission) { + return this.entityACL.isPermitted(subject, permission); + } + @Override public final boolean hasProperties() { return !this.properties.isEmpty(); diff --git a/src/main/java/caosdb/server/entity/EntityInterface.java b/src/main/java/caosdb/server/entity/EntityInterface.java index 76c6c51eaabb3ee5864d9cb538f43338e96ce914..21ed5cd85234bd633914302ce2982b2b6f4f9a66 100644 --- a/src/main/java/caosdb/server/entity/EntityInterface.java +++ b/src/main/java/caosdb/server/entity/EntityInterface.java @@ -171,6 +171,12 @@ public interface EntityInterface public abstract void checkPermission(Permission permission); + /** Return true iff the current thread's subject has a permission. */ + public abstract boolean hasPermission(Permission permission); + + /** Return true iff the given subject has a permission. */ + public abstract boolean hasPermission(Subject subject, Permission permission); + public abstract boolean hasEntityACL(); public abstract String getQueryTemplateDefinition(); diff --git a/src/main/java/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/caosdb/server/entity/container/TransactionContainer.java index 8c820a93164fd84ee6c27ea422941111ea24fdbb..f0ac55fae7b57d24456728508baa7768b83a5711 100644 --- a/src/main/java/caosdb/server/entity/container/TransactionContainer.java +++ b/src/main/java/caosdb/server/entity/container/TransactionContainer.java @@ -24,7 +24,6 @@ package caosdb.server.entity.container; import caosdb.server.CaosDBServer; import caosdb.server.database.misc.TransactionBenchmark; -import caosdb.server.entity.Entity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.FileProperties; import caosdb.server.entity.xml.ToElementable; @@ -36,7 +35,8 @@ import java.util.List; import org.apache.shiro.subject.Subject; import org.jdom2.Element; -public class TransactionContainer extends Container<Entity> implements ToElementable, JobTarget { +public class TransactionContainer extends Container<EntityInterface> + implements ToElementable, JobTarget { private EntityStatus status = EntityStatus.QUALIFIED; private final Subject owner; diff --git a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java index 1feeafdb7c158edd35a2eddd16af85b40e35211c..4d419bbfc17aee5749db70976f1a510ae468032b 100644 --- a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java +++ b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java @@ -541,4 +541,14 @@ public class EntityWrapper implements EntityInterface { public boolean skipJob() { return this.entity.skipJob(); } + + @Override + public boolean hasPermission(Permission permission) { + return this.entity.hasPermission(permission); + } + + @Override + public boolean hasPermission(Subject subject, Permission permission) { + return this.entity.hasPermission(subject, permission); + } } diff --git a/src/main/java/caosdb/server/jobs/core/ResolveNames.java b/src/main/java/caosdb/server/jobs/core/ResolveNames.java index f5e1695f34c30a78f136950f7aae3ae00be170e4..a7781fb4c1fd82d8a1f14df01da152b50ce86ae3 100644 --- a/src/main/java/caosdb/server/jobs/core/ResolveNames.java +++ b/src/main/java/caosdb/server/jobs/core/ResolveNames.java @@ -25,6 +25,7 @@ package caosdb.server.jobs.core; import caosdb.server.database.backend.transaction.GetIDByName; import caosdb.server.database.exceptions.EntityDoesNotExistException; import caosdb.server.entity.Entity; +import caosdb.server.entity.EntityInterface; import caosdb.server.entity.container.TransactionContainer; import caosdb.server.jobs.ContainerJob; import caosdb.server.utils.EntityStatus; @@ -41,7 +42,7 @@ public class ResolveNames extends ContainerJob { public void resolve(final TransactionContainer container) { final ArrayList<Entity> add = new ArrayList<Entity>(); - for (final Entity e : container) { + for (final EntityInterface e : container) { if (e.hasName() && !e.hasId()) { try { final List<Integer> c = execute(new GetIDByName(e.getName(), false)).getList(); diff --git a/src/main/java/caosdb/server/jobs/core/RetriveAllNames.java b/src/main/java/caosdb/server/jobs/core/RetriveAllNames.java new file mode 100644 index 0000000000000000000000000000000000000000..d7f58e00c602d5ed9a79d9e03fa08d9941e64217 --- /dev/null +++ b/src/main/java/caosdb/server/jobs/core/RetriveAllNames.java @@ -0,0 +1,32 @@ +package caosdb.server.jobs.core; + +import caosdb.server.database.backend.transaction.GetAllNames; +import caosdb.server.entity.EntityInterface; +import caosdb.server.jobs.FlagJob; +import caosdb.server.jobs.JobAnnotation; +import caosdb.server.jobs.JobExecutionTime; +import caosdb.server.permissions.EntityPermission; +import caosdb.server.utils.EntityStatus; + +/** + * A jobs which retrieves all known names for which the requesting user has the RETRIEVE_ENTITY + * permission. + * + * <p>The entites' status are set to VALID because the entities parents and properties do not have + * to be retrieved. + */ +@JobAnnotation(flag = "names", time = JobExecutionTime.INIT) +public class RetriveAllNames extends FlagJob { + + @Override + protected void job(String value) { + + GetAllNames t = execute(new GetAllNames()); + for (EntityInterface e : t.getEntities()) { + if (e.hasPermission(EntityPermission.RETRIEVE_ENTITY)) { + this.getContainer().add(e); + e.setEntityStatus(EntityStatus.VALID); + } + } + } +} diff --git a/src/main/java/caosdb/server/jobs/extension/AWIBoxLoan.java b/src/main/java/caosdb/server/jobs/extension/AWIBoxLoan.java index 8df3bc2f8b798a8495f9bb670fa7ce23c5eba9c2..30dd77e0c0fc7f97f85db7d45c00cf762badc695 100644 --- a/src/main/java/caosdb/server/jobs/extension/AWIBoxLoan.java +++ b/src/main/java/caosdb/server/jobs/extension/AWIBoxLoan.java @@ -5,7 +5,6 @@ import static caosdb.server.permissions.Role.ANONYMOUS_ROLE; import caosdb.server.accessControl.UserSources; import caosdb.server.database.exceptions.EntityDoesNotExistException; import caosdb.server.datatype.SingleValue; -import caosdb.server.entity.Entity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.Message; import caosdb.server.entity.Message.MessageType; @@ -489,7 +488,7 @@ public class AWIBoxLoan extends AWIBoxLoanModel { return false; } - boolean checkEmail(Entity entity) { + boolean checkEmail(EntityInterface entity) { runJobFromSchedule(entity, CheckPropValid.class); for (Property p : entity.getProperties()) { if (Objects.equals(p.getId(), getEmailID()) && p.getValue() instanceof SingleValue) { @@ -505,7 +504,7 @@ public class AWIBoxLoan extends AWIBoxLoanModel { return false; } - private boolean checkUniqueName(Entity entity) { + private boolean checkUniqueName(EntityInterface entity) { String firstName = null; String lastName = null; Query q = diff --git a/src/main/java/caosdb/server/resource/transaction/EntityNamesResource.java b/src/main/java/caosdb/server/resource/transaction/EntityNamesResource.java new file mode 100644 index 0000000000000000000000000000000000000000..2bfca90bf8e0c060caf7ca97b85ceaf7d0d35f5c --- /dev/null +++ b/src/main/java/caosdb/server/resource/transaction/EntityNamesResource.java @@ -0,0 +1,18 @@ +package caosdb.server.resource.transaction; + +import caosdb.server.entity.container.RetrieveContainer; +import caosdb.server.resource.transaction.handlers.GetNamesRequestHandler; +import caosdb.server.resource.transaction.handlers.RequestHandler; + +public class EntityNamesResource extends EntityResource { + + public EntityNamesResource() { + // only get is allowed + super(true, false, false, false); + } + + @Override + protected RequestHandler<RetrieveContainer> getGetRequestHandler() { + return new GetNamesRequestHandler(); + } +} diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/GetNamesRequestHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/GetNamesRequestHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..f69c112880e833d0c981b903562889e377fe6f23 --- /dev/null +++ b/src/main/java/caosdb/server/resource/transaction/handlers/GetNamesRequestHandler.java @@ -0,0 +1,13 @@ +package caosdb.server.resource.transaction.handlers; + +import caosdb.server.entity.container.RetrieveContainer; +import caosdb.server.resource.transaction.EntityResource; + +public class GetNamesRequestHandler extends RequestHandler<RetrieveContainer> { + + /** Adds the `names` flag to the RetrieveContainer which triggers the RetrieveAllNames job. */ + @Override + public void handle(EntityResource t, RetrieveContainer container) throws Exception { + container.getFlags().put("names", null); + } +} diff --git a/src/main/java/caosdb/server/transaction/Update.java b/src/main/java/caosdb/server/transaction/Update.java index 8edd27d0aa0250ffebadc8d9a9639490daf1e2c7..b9e6e8de19f137014d10d1c6516c07ca2acabf8e 100644 --- a/src/main/java/caosdb/server/transaction/Update.java +++ b/src/main/java/caosdb/server/transaction/Update.java @@ -58,7 +58,7 @@ public class Update extends WriteTransaction<UpdateContainer> { protected void init() throws Exception { // collect all ids of the entities which are to be updated. final TransactionContainer oldContainer = new TransactionContainer(); - for (final Entity entity : getContainer()) { + for (final EntityInterface entity : getContainer()) { // entity has no id -> it cannot be updated. if (!entity.hasId()) { entity.addError(ServerMessages.ENTITY_HAS_NO_ID); diff --git a/src/test/java/caosdb/server/database/backend/transactions/TestGetAllNames.java b/src/test/java/caosdb/server/database/backend/transactions/TestGetAllNames.java new file mode 100644 index 0000000000000000000000000000000000000000..1c67d5cba56cd3bfb1516788a0187f9bc673f5e6 --- /dev/null +++ b/src/test/java/caosdb/server/database/backend/transactions/TestGetAllNames.java @@ -0,0 +1,65 @@ +package caosdb.server.database.backend.transactions; + +import static org.junit.Assert.assertEquals; + +import caosdb.server.CaosDBServer; +import caosdb.server.database.BackendTransaction; +import caosdb.server.database.access.Access; +import caosdb.server.database.backend.interfaces.GetAllNamesImpl; +import caosdb.server.database.backend.transaction.GetAllNames; +import caosdb.server.database.misc.TransactionBenchmark; +import caosdb.server.database.proto.SparseEntity; +import caosdb.server.entity.EntityInterface; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestGetAllNames { + + public static class GetAllNamesBackend implements GetAllNamesImpl { + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) {} + + @Override + public TransactionBenchmark getBenchmark() { + return null; + } + + @Override + public List<SparseEntity> execute() { + ArrayList<SparseEntity> ret = new ArrayList<>(); + + for (int i = 0; i < 10; i++) { + + SparseEntity e = new SparseEntity(); + e.role = "RecordType"; + e.name = "Test" + Integer.toString(i); + e.acl = ""; + ret.add(e); + } + return ret; + } + + public GetAllNamesBackend(Access access) {} + } + + @BeforeClass + public static void setup() throws IOException { + CaosDBServer.initServerProperties(); + BackendTransaction.init(); + BackendTransaction.setImpl(GetAllNamesImpl.class, GetAllNamesBackend.class); + } + + @Test + public void test() { + GetAllNames getAllNames = new GetAllNames(); + getAllNames.executeTransaction(); + List<EntityInterface> entities = getAllNames.getEntities(); + assertEquals(entities.size(), 10); + EntityInterface first = entities.get(0); + assertEquals(first.getName(), "Test0"); + } +}