diff --git a/CHANGELOG.md b/CHANGELOG.md index fc91c68ad8ee81c2d33a12d48c0c040a1c3d8043..e936d2032060d8931259de3770a3382e9e2ebcac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +* Unknown error when trying to access the user list. + [linkahead-server#250](https://gitlab.com/linkahead/linkahead-server/-/issues/250) +* Legacy integer ids are incremented by 1 again, not by 2. + ### Security +## [0.12.1] - 2023-12-13 +(Timm Fitschen) + +### Fixed + +* Insufficient permission checks during subproperty filters of SELECT queries + when an entity with retrieve permissions references one without + [linkahead-server#244](https://gitlab.com/linkahead/linkahead-server/-/issues/244) +* Insufficient permission checks in queries when a name of an invisible record + is used in a filter where a visible record references the invisible one + [linkahead-server#242](https://gitlab.com/linkahead/linkahead-server/-/issues/242) + +### Security + +This is an important security patch release. The bugs +[linkahead-server#244](https://gitlab.com/linkahead/linkahead-server/-/issues/244) +and +[linkahead-server#242](https://gitlab.com/linkahead/linkahead-server/-/issues/242) +possibly leak sensitive data when an attacker with read access to linkahead +(i.e. the attacker needs an active user account or anonymous needs to be +enabled) can guess the name of entities or properties of referenced entities +and construct a malicious FIND or SELECT statement and when the attacker has +read permissions for an entity which references the entities containing the +sensitive information. See the bug reports for more information. + ## [0.12.0] - 2023-10-25 (Timm Fitschen) diff --git a/CITATION.cff b/CITATION.cff index a7c72943398fe58430003e8412d7d01e911c9f43..77f724679e3c57ef44e9380af8ded72cb7a30410 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -23,6 +23,6 @@ authors: given-names: Stefan orcid: https://orcid.org/0000-0001-7214-8125 title: "CaosDB - Server" -version: 0.12.0 +version: 0.12.1 doi: 10.3390/data4020083 -date-released: 2023-10-25 +date-released: 2023-12-13 diff --git a/README_SETUP.md b/README_SETUP.md index e3b6e3bc3e8a69c2ff1e162476819ec76b93dbe9..567a24663d5c1c7a3343e3e0f137b8196831c7bd 100644 --- a/README_SETUP.md +++ b/README_SETUP.md @@ -241,6 +241,7 @@ Stand-alone documentation is built using Sphinx: `make doc` - recommonmark - sphinx - sphinx-rtd-theme +- sphinx-a4doc - sphinxcontrib-plantuml - javasphinx :: `pip3 install --user javasphinx` - Alternative, if javasphinx fails because python3-sphinx is too recent: diff --git a/caosdb-webui b/caosdb-webui index d5f9090eca25a92fc44dbeeba305768e8d9f4bcb..6e4db2f99e1d441bbda9ccca85fae45526018406 160000 --- a/caosdb-webui +++ b/caosdb-webui @@ -1 +1 @@ -Subproject commit d5f9090eca25a92fc44dbeeba305768e8d9f4bcb +Subproject commit 6e4db2f99e1d441bbda9ccca85fae45526018406 diff --git a/conf/core/usersources.ini.template b/conf/core/usersources.ini.template index fb3285723f0721da3280e5ef33461ff4b684e89f..d54d91d2202bf3ba465346ca0a24ad566bbd73a8 100644 --- a/conf/core/usersources.ini.template +++ b/conf/core/usersources.ini.template @@ -46,11 +46,14 @@ class = org.caosdb.server.accessControl.Pam # scripts or the misc/pam_authentication/ldap_authentication.sh script here. ; pam_script = ./misc/pam_authentication/pam_authentication.sh default_status = ACTIVE -# Only users which fulfill these criteria are accepted. +# Only users which fulfill these criteria are accepted. The values are +# user/group name(s) separated by whitespaces ;include.user = [uncomment and put your users here] ;include.group = [uncomment and put your groups here] ;exclude.user = [uncomment and put excluded users here] ;exclude.group = [uncomment and put excluded groups here] # It is typically necessary to add at least one admin -;user.[uncomment a set a username here].roles = administration +;user.[uncomment and set a username here].roles = administration +# Several roles are separated by commas +;user.[uncomment and set a username here].roles = role1, role2, role with spaces diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000000000000000000000000000000000000..d60cf6116e6e2a19e5422eb86979c96d54652869 --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,4 @@ +sphinx-rtd-theme +sphinxcontrib-plantuml +javasphinx +sphinx-a4doc diff --git a/src/doc/administration/server_side_scripting.rst b/src/doc/administration/server_side_scripting.rst index 6dc08999f38e1912e72440c609b8cde1ea7ce0bb..dc4b020ea884a170df30ddd866e77fa1f6bf5a7a 100644 --- a/src/doc/administration/server_side_scripting.rst +++ b/src/doc/administration/server_side_scripting.rst @@ -1,85 +1,4 @@ Server-Side Scripting ===================== -Introduction ------------- - -Small computation task, like some visualization, might be easily implemented in Python or some other language, but cumbersome to integrate into the server. Furthermore, the CaosDB server should stay a general tool without burden from specific projects. Also, one might want to trigger some standardized processing task from the web interface for convenience. For these situations the "server side scripting" is intended. - -Concepts ------------- - -The basic idea is that a script or program (script in the following) can be called to run on the server (or elsewhere in future) to do some calculations. This triggering of the script is done over the API so it can be done with any client. Input arguments can be passed to the script and the STDOUT and STDERR are returned. - -Each script is executed in a temporary home directory, which is automatically clean up. However, scripts can store files in the "$SHARED" folder and for example provide users a link that allows them to download files. - -Write and Install a Script --------------------------- - -A server-side script must accept at least the ``--auth-token=AUTH_TOKEN`` option. All other command-line parameters which are passed to the script are not specified by the API and maybe defined by the script itself. - -So a minimal bash script would be - -.. code-block:: sh - - #!/bin/bash - echo Hello, World! - -thereby just ignoring the ``--auth-token`` option. - -The script has to be executable and must be placed somewhere in one of the directory trees which are configured by the server config :doc:`SERVER_SIDE_SCRIPTING_BIN_DIRS <configuration>`. - -Users will need the ``SCRIPTING:EXECUTE:path:to:the:script`` permission. Here the path to the script is of course relativet to the ``SERVER_SIDE_SCRIPTING_BIN_DIRS`` where it is located. - -For more information see the :doc:`specification of the API <../specification/Server-side-scripting>` - -Environment ------------- - -The script is called with several special environment variables to accommodate -for its special location. - -`HOME` -^^^^^^^^^^^^ -To be able to run with reduced privileges, the script has its `HOME` environment -variable set to a special directory with write access. This directory will be -deleted after the script has terminated. Its content is freshly copied for each -script invocation from a skeleton directory, located in the server directory, in -`scripting/home/`. By default, this directory contains the following: - -- `readme.md` :: A small text file describing the purpose of the directory. - -Users of CaosDB are invited to populate the directory with whatever their -scripts need (for example a `.pycaosdb.ini` file). - -Invocation ------------- - -Server side scripts are triggered by sending a POST to the `/scripting` resource. There are the following arguments that can be provided: - -- `call`: the name of the script to be called -- `-pN`: positional arguments (e.g. `-p0`, `-p1` etc.) -- `-ONAME`: named arguments (e.g. `-Otest`, `-Onumber` etc.) - -The arguments will be passed to the script. - -An invocation via a button in javascript could look like: - -.. code-block:: javascript - - var _make_sss_button = function (entity) { - const script = "script.py"; - - const scripting_form = $(` - <form class="btn-group-xs ${_css_class_export_button}" - method="POST" - action="/scripting"> - <input type="hidden" name="call" value="${script}"/> - <input name="-p0" value=""/> - <button type="submit" class="btn btn-link">Start script</button> - </form>`); - return scripting_form[0]; - } - -For more information see the :doc:`specification of the API <../specification/Server-side-scripting>` - +The documentation was updated and moved to the :doc:`linkahead's documentation <caosdb-deploy/server_side_scripting.html>`. diff --git a/src/doc/index.rst b/src/doc/index.rst index e34afd382f0c4a1a5520b94a4fc00e1c0a67427b..d80bcc1c0a3b79b5e03a64a0437aadf45cb73938 100644 --- a/src/doc/index.rst +++ b/src/doc/index.rst @@ -19,7 +19,9 @@ Welcome to caosdb-server's documentation! Changelog <CHANGELOG> specification/index.rst Glossary - Server Internals<_apidoc/packages> + Server Internals <_apidoc/packages> + Related Projects <related_projects/index> + Back to overview <https://docs.indiscale.com/> Welcome to the CaosDB, the flexible semantic data management toolkit! diff --git a/src/doc/related_projects/index.rst b/src/doc/related_projects/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..c40b581e68d33ff3e58e3fbb16761ea891c990fb --- /dev/null +++ b/src/doc/related_projects/index.rst @@ -0,0 +1,25 @@ +Related Projects +++++++++++++++++ + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + :hidden: + +.. container:: projects + + For in-depth documentation for users, administrators and developers, you may want to visit the subproject-specific documentation pages for: + + :`MySQL backend <https://docs.indiscale.com/caosdb-mysqlbackend>`_: The MySQL/MariaDB components of the LinkAhead server. + + :`WebUI <https://docs.indiscale.com/caosdb-webui>`_: The default web frontend for the LinkAhead server. + + :`PyLinkAhead <https://docs.indiscale.com/caosdb-pylib>`_: The LinkAhead Python library. + + :`Advanced user tools <https://docs.indiscale.com/caosdb-advanced-user-tools>`_: The advanced Python tools for LinkAhead. + + :`LinkAhead Crawler <https://docs.indiscale.com/caosdb-crawler/>`_: The crawler is the main tool for automatic data integration in LinkAhead. + + :`LinkAhead <https://docs.indiscale.com/caosdb-deploy>`_: Your all inclusive LinkAhead software package. + + :`Back to Overview <https://docs.indiscale.com/>`_: LinkAhead Documentation. diff --git a/src/main/java/org/caosdb/server/CaosDBServer.java b/src/main/java/org/caosdb/server/CaosDBServer.java index 8c75cf51e9a85685c19c3de271f56b519b81add7..4b7c0fe11ecb0c2391e5548ed6e37ede416e1343 100644 --- a/src/main/java/org/caosdb/server/CaosDBServer.java +++ b/src/main/java/org/caosdb/server/CaosDBServer.java @@ -73,7 +73,6 @@ import org.caosdb.server.resource.LogoutResource; import org.caosdb.server.resource.PermissionRulesResource; import org.caosdb.server.resource.RolesResource; import org.caosdb.server.resource.ScriptingResource; -import org.caosdb.server.resource.ServerLogsResource; import org.caosdb.server.resource.ServerPropertiesResource; import org.caosdb.server.resource.SharedFileResource; import org.caosdb.server.resource.ThumbnailsResource; @@ -746,12 +745,6 @@ public class CaosDBServer extends Application { protectedRouter.attach("/Role/{specifier}", RolesResource.class); protectedRouter.attach("/PermissionRules/{specifier}", PermissionRulesResource.class); protectedRouter.attach("/PermissionRules/{realm}/{specifier}", PermissionRulesResource.class); - protectedRouter - .attach("/ServerLogs/", ServerLogsResource.class) - .setMatchingMode(Template.MODE_STARTS_WITH); - protectedRouter - .attach("/ServerLogs", ServerLogsResource.class) - .setMatchingMode(Template.MODE_STARTS_WITH); protectedRouter.attach("/login?username={username}", AuthenticationResource.class); protectedRouter.attach("/logout", LogoutResource.class); protectedRouter.attach("/_server_properties", ServerPropertiesResource.class); diff --git a/src/main/java/org/caosdb/server/database/BackendTransaction.java b/src/main/java/org/caosdb/server/database/BackendTransaction.java index c014972ac52246e87a1d9e6f575a645125ab4c57..534c7bc1ae35c5b8778b7950155337d1a24bd04f 100644 --- a/src/main/java/org/caosdb/server/database/BackendTransaction.java +++ b/src/main/java/org/caosdb/server/database/BackendTransaction.java @@ -37,7 +37,6 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLGetUpdateabl import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertEntityDatatype; import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertEntityProperties; import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertLinCon; -import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertLogRecord; import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertParents; import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertRole; import org.caosdb.server.database.backend.implementation.MySQL.MySQLInsertSparseEntity; @@ -51,7 +50,6 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAllU import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveCurrentMaxId; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveDatatypes; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveEntityACL; -import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveLogRecord; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveParents; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrievePasswordValidator; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrievePermissionRules; @@ -95,7 +93,6 @@ import org.caosdb.server.database.backend.interfaces.GetUpdateableChecksumsImpl; import org.caosdb.server.database.backend.interfaces.InsertEntityDatatypeImpl; import org.caosdb.server.database.backend.interfaces.InsertEntityPropertiesImpl; import org.caosdb.server.database.backend.interfaces.InsertLinConImpl; -import org.caosdb.server.database.backend.interfaces.InsertLogRecordImpl; import org.caosdb.server.database.backend.interfaces.InsertParentsImpl; import org.caosdb.server.database.backend.interfaces.InsertRoleImpl; import org.caosdb.server.database.backend.interfaces.InsertSparseEntityImpl; @@ -109,7 +106,6 @@ import org.caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesIm import org.caosdb.server.database.backend.interfaces.RetrieveCurrentMaxIdImpl; import org.caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl; import org.caosdb.server.database.backend.interfaces.RetrieveEntityACLImpl; -import org.caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl; import org.caosdb.server.database.backend.interfaces.RetrieveParentsImpl; import org.caosdb.server.database.backend.interfaces.RetrievePasswordValidatorImpl; import org.caosdb.server.database.backend.interfaces.RetrievePermissionRulesImpl; @@ -213,8 +209,6 @@ public abstract class BackendTransaction implements Undoable { setImpl(SetPermissionRulesImpl.class, MySQLSetPermissionRules.class); setImpl(RetrievePermissionRulesImpl.class, MySQLRetrievePermissionRules.class); setImpl(UpdateUserRolesImpl.class, MySQLUpdateUserRoles.class); - setImpl(InsertLogRecordImpl.class, MySQLInsertLogRecord.class); - setImpl(RetrieveLogRecordImpl.class, MySQLRetrieveLogRecord.class); setImpl(SetQueryTemplateDefinitionImpl.class, MySQLSetQueryTemplateDefinition.class); setImpl( RetrieveQueryTemplateDefinitionImpl.class, MySQLRetrieveQueryTemplateDefinition.class); diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertLogRecord.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertLogRecord.java deleted file mode 100644 index 6807808d18fb6ba9ce0a4ed9287ea21612cc2d2c..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertLogRecord.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.implementation.MySQL; - -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.List; -import java.util.logging.LogRecord; -import org.caosdb.server.database.access.Access; -import org.caosdb.server.database.backend.interfaces.InsertLogRecordImpl; -import org.caosdb.server.database.exceptions.TransactionException; - -public class MySQLInsertLogRecord extends MySQLTransaction implements InsertLogRecordImpl { - - public MySQLInsertLogRecord(final Access access) { - super(access); - } - - public static final String STMT_INSERT_LOG_RECORD = - "INSERT INTO logging (level, logger, message, millis, logRecord) VALUES (?,?,?,?,?)"; - - @Override - public void insert(final List<LogRecord> toBeFlushed) throws TransactionException { - try { - final PreparedStatement prepInsert = prepareStatement(STMT_INSERT_LOG_RECORD); - for (final LogRecord record : toBeFlushed) { - prepInsert.setInt(1, record.getLevel().intValue()); - prepInsert.setString(2, record.getLoggerName()); - prepInsert.setString(3, record.getMessage()); - prepInsert.setLong(4, record.getMillis()); - prepInsert.setObject(5, record); - prepInsert.executeUpdate(); - } - } catch (final SQLException e) { - throw new TransactionException(e); - } catch (final ConnectionException e) { - throw new TransactionException(e); - } - } -} diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java index 3b68c45d0ff60473ae837f3c9ebc17ae82e68c2d..db00b1d310e636dca4c96973d3578f6ee0400369 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java @@ -54,7 +54,7 @@ public class MySQLListUsers extends MySQLTransaction implements ListUsersImpl { user.realm = rs.getString("realm"); user.email = rs.getString("email"); user.entity = rs.getString("entity"); - if (user.entity.isBlank() || user.entity.equals("0")) { + if (user.entity == null || user.entity.isBlank() || user.entity.equals("0")) { user.entity = null; } user.status = UserStatus.valueOf(rs.getString("status")); diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveLogRecord.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveLogRecord.java deleted file mode 100644 index bba36d2eb9de29fee40f023b9b97602d5b94b8a3..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveLogRecord.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.implementation.MySQL; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.LinkedList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import org.caosdb.server.database.access.Access; -import org.caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl; -import org.caosdb.server.database.exceptions.TransactionException; - -public class MySQLRetrieveLogRecord extends MySQLTransaction implements RetrieveLogRecordImpl { - - public MySQLRetrieveLogRecord(final Access access) { - super(access); - } - - public static final String STMT_RETRIEVE_LOG = "SELECT logRecord FROM logging"; - public static final String WHERE = " WHERE "; - public static final String AND = " AND "; - public static final String LOGGER_COND = "logger LIKE ?"; - public static final String MESSAGE_COND = "message LIKE ?"; - - public static final String LEVEL_COND(final Level level) { - return "level=" + level.intValue(); - } - - private static String getWhereClause( - final String logger, final Level level, final String message) { - - if (logger != null || level != null || message != null) { - final StringBuilder sb = new StringBuilder(); - - if (logger != null) { - sb.append(LOGGER_COND); - } - if (level != null) { - if (sb.length() > 0) { - sb.append(AND); - } - sb.append(LEVEL_COND(level)); - } - if (message != null) { - if (sb.length() > 0) { - sb.append(AND); - } - sb.append(MESSAGE_COND); - } - return WHERE + sb.toString(); - } - return ""; - } - - @Override - public List<LogRecord> retrieve(final String logger, final Level level, final String message) - throws TransactionException { - final List<LogRecord> ret = new LinkedList<LogRecord>(); - - final String stmtStr = STMT_RETRIEVE_LOG + getWhereClause(logger, level, message); - - try { - final PreparedStatement stmt = prepareStatement(stmtStr); - int index = 1; - if (logger != null) { - stmt.setString(index++, logger); - } - if (message != null) { - stmt.setString(index++, message); - } - ResultSet rs = null; - try { - rs = stmt.executeQuery(); - - while (rs.next()) { - final byte[] bytes = rs.getBytes("logRecord"); - - final ObjectInputStream s = new ObjectInputStream(new ByteArrayInputStream(bytes)); - final Object o = s.readObject(); - ret.add((LogRecord) o); - } - } finally { - if (rs != null && !rs.isClosed()) { - rs.close(); - } - } - } catch (final ClassNotFoundException e) { - throw new TransactionException(e); - } catch (final IOException e) { - throw new TransactionException(e); - } catch (final SQLException e) { - throw new TransactionException(e); - } catch (final ConnectionException e) { - throw new TransactionException(e); - } - - return ret; - } -} diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/InsertLogRecordImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/InsertLogRecordImpl.java deleted file mode 100644 index 78bab8e251ff6e151963f1be8caf5e73211cc8e3..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/interfaces/InsertLogRecordImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.interfaces; - -import java.util.List; -import java.util.logging.LogRecord; -import org.caosdb.server.database.exceptions.TransactionException; - -public interface InsertLogRecordImpl extends BackendTransactionImpl { - - public void insert(List<LogRecord> toBeFlushed) throws TransactionException; -} diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveLogRecordImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveLogRecordImpl.java deleted file mode 100644 index b6646d269123d70a3b6d06a381c7a83792e1b659..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveLogRecordImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.interfaces; - -import java.util.List; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import org.caosdb.server.database.exceptions.TransactionException; - -public interface RetrieveLogRecordImpl extends BackendTransactionImpl { - - List<LogRecord> retrieve(String logger, Level level, String message) throws TransactionException; -} diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertLogRecord.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertLogRecord.java deleted file mode 100644 index 3ce27add49761737c0a8365410c979665a3f16a9..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertLogRecord.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.transaction; - -import java.util.List; -import java.util.logging.LogRecord; -import org.caosdb.server.database.BackendTransaction; -import org.caosdb.server.database.backend.interfaces.InsertLogRecordImpl; -import org.caosdb.server.database.exceptions.TransactionException; - -public class InsertLogRecord extends BackendTransaction { - - private final List<LogRecord> toBeFlushed; - - public InsertLogRecord(final List<LogRecord> toBeFlushed) { - this.toBeFlushed = toBeFlushed; - } - - @Override - protected void execute() throws TransactionException { - final InsertLogRecordImpl t = getImplementation(InsertLogRecordImpl.class); - t.insert(this.toBeFlushed); - } -} diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java index 92f5aa841aed5f759d433076700a8b1ce13e26dc..bfb1497d71a5ede778255f6640038d647a001547 100644 --- a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java +++ b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTransaction.java @@ -26,6 +26,7 @@ package org.caosdb.server.database.backend.transaction; import java.util.LinkedList; import java.util.List; +import org.apache.shiro.subject.Subject; import org.caosdb.server.database.BackendTransaction; import org.caosdb.server.database.exceptions.EntityDoesNotExistException; import org.caosdb.server.datatype.CollectionValue; @@ -38,6 +39,7 @@ import org.caosdb.server.entity.RetrieveEntity; import org.caosdb.server.entity.Role; import org.caosdb.server.entity.container.Container; import org.caosdb.server.entity.wrapper.Property; +import org.caosdb.server.permissions.EntityPermission; import org.caosdb.server.query.Query; import org.caosdb.server.query.Query.Selection; import org.caosdb.server.utils.EntityStatus; @@ -57,19 +59,22 @@ import org.caosdb.server.utils.EntityStatus; public class RetrieveFullEntityTransaction extends BackendTransaction { private final Container<? extends EntityInterface> container; + private final Subject subject; - public RetrieveFullEntityTransaction(final EntityInterface entity) { - final Container<EntityInterface> c = new Container<>(); - c.add(entity); - this.container = c; + @SuppressWarnings("unchecked") + public RetrieveFullEntityTransaction(final EntityInterface entity, Subject subject) { + this(new Container<>(), subject); + ((Container<EntityInterface>) this.container).add(entity); } - public RetrieveFullEntityTransaction(final Container<? extends EntityInterface> container) { + public RetrieveFullEntityTransaction( + final Container<? extends EntityInterface> container, final Subject subject) { this.container = container; + this.subject = subject; } - public RetrieveFullEntityTransaction(final EntityID id) { - this(new RetrieveEntity(id)); + public RetrieveFullEntityTransaction(final EntityID id, Subject subject) { + this(new RetrieveEntity(id), subject); } @Override @@ -220,9 +225,17 @@ public class RetrieveFullEntityTransaction extends BackendTransaction { private void resolveReferenceValue( final ReferenceValue value, final List<Selection> selections, final String propertyName) { final RetrieveEntity ref = new RetrieveEntity(value.getId()); - // recursion! (Only for the matching selections) - retrieveFullEntity(ref, getSubSelects(selections, propertyName)); - value.setEntity(ref, true); + + if (this.subject != null) { + // recursion! (Only for the matching selections) + retrieveFullEntity(ref, getSubSelects(selections, propertyName)); + + // check whether the referenced entity is readable + if (!ref.getEntityACL().isPermitted(this.subject, EntityPermission.RETRIEVE_ENTITY)) { + return; + } + value.setEntity(ref, true); + } } /** diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveLogRecord.java b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveLogRecord.java deleted file mode 100644 index eae8a96589aab3558a1978890c85bdd18bc161dc..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveLogRecord.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.transaction; - -import java.util.List; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import org.caosdb.server.database.BackendTransaction; -import org.caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl; -import org.caosdb.server.database.exceptions.TransactionException; - -public class RetrieveLogRecord extends BackendTransaction { - - private final Level level; - private final String logger; - private List<LogRecord> logRecords; - private final String message; - - public RetrieveLogRecord(final String logger, final Level level, final String message) { - this.logger = logger; - this.level = level; - this.message = message; - } - - @Override - protected void execute() throws TransactionException { - final RetrieveLogRecordImpl t = getImplementation(RetrieveLogRecordImpl.class); - this.logRecords = t.retrieve(this.logger, this.level, this.message); - } - - public List<LogRecord> getLogRecords() { - return this.logRecords; - } -} diff --git a/src/main/java/org/caosdb/server/entity/LegacyIds.java b/src/main/java/org/caosdb/server/entity/LegacyIds.java index cf0937e856252a4a29657f2eb7f998500b937bb4..2ad7a1d86b402e8b5f7442a8ace716a6724469a4 100644 --- a/src/main/java/org/caosdb/server/entity/LegacyIds.java +++ b/src/main/java/org/caosdb/server/entity/LegacyIds.java @@ -61,7 +61,6 @@ public class LegacyIds extends EntityIdRegistryStrategy { if (!isInit) { init(); } - ++currentMaxId; return Integer.toString(++currentMaxId); } diff --git a/src/main/java/org/caosdb/server/entity/RetrieveEntity.java b/src/main/java/org/caosdb/server/entity/RetrieveEntity.java index 00a120fbf023024eae8acc5788a9260d020a956d..e1b9e8c06fbc0d14a8719bd50635464a4c117326 100644 --- a/src/main/java/org/caosdb/server/entity/RetrieveEntity.java +++ b/src/main/java/org/caosdb/server/entity/RetrieveEntity.java @@ -24,6 +24,14 @@ */ package org.caosdb.server.entity; +/** + * Entity which is to be retrieved (i.e. read-only). + * + * <p>This class only exposes those constructors which are necessary for Entity which are to be + * retrieved (e.g. Entity(id)) and hide the others (e.g. Entity(XML-Represenation)). + * + * @author Timm Fitschen <t.fitschen@indiscale.com> + */ public class RetrieveEntity extends Entity { public RetrieveEntity() { 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 35d94aa79fd62a04f8b0dae1a17829a1106c2d97..bbe1749c91e2b102a7c41e78e00cd5f02904a5ff 100644 --- a/src/main/java/org/caosdb/server/entity/xml/EntityToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/EntityToElementStrategy.java @@ -169,14 +169,16 @@ public class EntityToElementStrategy implements ToElementStrategy { // processing SELECT Queries. final EntityInterface ref = ((ReferenceValue) entity.getValue()).getEntity(); if (ref != null) { - if (entity.hasDatatype()) { - setDatatype(entity, element); - } ref.addToElement(element, serializeFieldStrategy); - // the referenced entity has been appended. Return here to suppress - // adding the reference id as well. - return; + } else { + entity.getValue().addToElement(element); + } + if (entity.hasDatatype()) { + setDatatype(entity, element); } + // the referenced entity has been appended. Return here to suppress + // adding the reference id as well. + return; } else if (entity.isReferenceList() && serializeFieldStrategy.isToBeSet("_referenced")) { // Append the all referenced entities. This needs to be done when we are // processing SELECT Queries. diff --git a/src/main/java/org/caosdb/server/query/POV.java b/src/main/java/org/caosdb/server/query/POV.java index 6ee5f9d0122aa417c357e71ef6d6ea0516007215..597495f2d16d6e27229660d2341962d1dce20f91 100644 --- a/src/main/java/org/caosdb/server/query/POV.java +++ b/src/main/java/org/caosdb/server/query/POV.java @@ -405,6 +405,12 @@ public class POV implements EntityFilterInterface { } final long t2 = System.currentTimeMillis(); query.addBenchmark(measurement(".initPOVRefidsTable()"), t2 - t1); + + if (this.refIdsTable != null) { + query.getQuery().filterIntermediateResult(this.refIdsTable); + } + final long t3 = System.currentTimeMillis(); + query.addBenchmark(measurement(".filterRefidsWithoutRetrievePermission"), t3 - t2); try (PreparedStatement stmt = query.getConnection().prepareCall("call initPOVPropertiesTable(?,?,?)")) { // initPOVPropertiesTable(in pid INT UNSIGNED, in pname @@ -455,12 +461,12 @@ public class POV implements EntityFilterInterface { } } } - final long t3 = System.currentTimeMillis(); - query.addBenchmark(measurement(""), t3 - t2); + final long t4 = System.currentTimeMillis(); + query.addBenchmark(measurement(""), t4 - t3); if (this.refIdsTable != null) { query.getQuery().applyQueryTemplates(query, this.refIdsTable); - query.addBenchmark(measurement(".applyQueryTemplates()"), System.currentTimeMillis() - t3); + query.addBenchmark(measurement(".applyQueryTemplates()"), System.currentTimeMillis() - t4); } if (hasSubProperty() && this.targetSet != null) { diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java index 117176ec5c6a1fcb10e588b860926b02eb76a2a9..168b7ac8b987ecfd75355580fd6af6409a54c4ac 100644 --- a/src/main/java/org/caosdb/server/query/Query.java +++ b/src/main/java/org/caosdb/server/query/Query.java @@ -72,11 +72,21 @@ import org.caosdb.server.permissions.EntityPermission; import org.caosdb.server.query.CQLParser.CqContext; import org.caosdb.server.query.CQLParsingErrorListener.ParsingError; import org.caosdb.server.transaction.EntityTransactionInterface; +import org.caosdb.server.transaction.Retrieve; import org.caosdb.server.transaction.Transaction; import org.caosdb.server.transaction.WriteTransaction; import org.jdom2.Element; import org.slf4j.Logger; +/** + * This class represents a single, complete Query execution from the parsing of the query string to + * the resulting list of entity ids. + * + * <p>This class handles caching of queries and checking retrieve permissions as well. It does not, + * however, retrieve the resulting entities; this is handled by the {@link Retrieve} class. + * + * @author Timm Fitschen <t.fitschen@indiscale.com> + */ public class Query implements QueryInterface, ToElementable, EntityTransactionInterface { /** Class which represents the selection of (sub)properties. */ diff --git a/src/main/java/org/caosdb/server/resource/ServerLogsResource.java b/src/main/java/org/caosdb/server/resource/ServerLogsResource.java deleted file mode 100644 index acc1833dc5158d23e72f06f15cf1ddd037185043..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/resource/ServerLogsResource.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.resource; - -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.sql.SQLException; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.XMLFormatter; -import org.caosdb.server.CaosDBException; -import org.caosdb.server.database.backend.implementation.MySQL.ConnectionException; -import org.caosdb.server.transaction.RetrieveLogRecordTransaction; -import org.restlet.data.Form; -import org.restlet.data.MediaType; -import org.restlet.representation.Representation; -import org.restlet.representation.StringRepresentation; - -public class ServerLogsResource extends AbstractCaosDBServerResource { - - @Override - protected Representation httpGetInChildClass() - throws ConnectionException, - IOException, - SQLException, - CaosDBException, - NoSuchAlgorithmException, - Exception { - - Level level = null; - String message = null; - final String logger = - getRequest().getResourceRef().getRemainingPart(true, false).replaceAll("/", "."); - final Form form = getRequest().getResourceRef().getQueryAsForm(true); - if (form != null) { - final String levelStr = form.getFirstValue("level"); - if (levelStr != null) { - try { - level = Level.parse(levelStr); - } catch (final IllegalArgumentException e) { - level = Level.OFF; - } - } - message = form.getFirstValue("message"); - } - - final RetrieveLogRecordTransaction t = new RetrieveLogRecordTransaction(logger, level, message); - t.execute(); - - generateRootElement(); - final List<LogRecord> logRecords = t.getLogRecords(); - - final XMLFormatter xmlFormatter = new XMLFormatter(); - String ret = xmlFormatter.getHead(null); - for (final LogRecord r : logRecords) { - ret += xmlFormatter.format(r); - } - ret += xmlFormatter.getTail(null); - - return new StringRepresentation(ret, MediaType.TEXT_XML); - } -} diff --git a/src/main/java/org/caosdb/server/transaction/InsertLogRecordTransaction.java b/src/main/java/org/caosdb/server/transaction/InsertLogRecordTransaction.java deleted file mode 100644 index 950d9b8d25688e47833b60c01335f8dd525a0630..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/transaction/InsertLogRecordTransaction.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.transaction; - -import java.util.List; -import java.util.logging.LogRecord; -import org.caosdb.datetime.UTCDateTime; -import org.caosdb.server.database.DatabaseAccessManager; -import org.caosdb.server.database.access.Access; -import org.caosdb.server.database.backend.transaction.InsertLogRecord; - -public class InsertLogRecordTransaction implements TransactionInterface { - - private final List<LogRecord> toBeFlushed; - private UTCDateTime timestamp; - - public InsertLogRecordTransaction(final List<LogRecord> toBeFlushed) { - this.timestamp = UTCDateTime.SystemMillisToUTCDateTime(System.currentTimeMillis()); - this.toBeFlushed = toBeFlushed; - } - - @Override - public void execute() throws Exception { - final Access access = DatabaseAccessManager.getInstance().acquireReadAccess(this); - try { - execute(new InsertLogRecord(this.toBeFlushed), access); - } finally { - access.release(); - } - } - - @Override - public UTCDateTime getTimestamp() { - return timestamp; - } -} diff --git a/src/main/java/org/caosdb/server/transaction/Retrieve.java b/src/main/java/org/caosdb/server/transaction/Retrieve.java index 643c1201b530af9821c9a5c1a7b62f7c5d04cf52..54500c5932d7d8e4af41b5d88f79a2f5f914492f 100644 --- a/src/main/java/org/caosdb/server/transaction/Retrieve.java +++ b/src/main/java/org/caosdb/server/transaction/Retrieve.java @@ -114,7 +114,7 @@ public class Retrieve extends Transaction<RetrieveContainer> { private void retrieveFullEntities(final RetrieveContainer container, final Access access) throws Exception { - execute(new RetrieveFullEntityTransaction(container), access); + execute(new RetrieveFullEntityTransaction(container, getTransactor()), access); } @Override diff --git a/src/main/java/org/caosdb/server/transaction/RetrieveLogRecordTransaction.java b/src/main/java/org/caosdb/server/transaction/RetrieveLogRecordTransaction.java deleted file mode 100644 index 2f6cafd6e4e55ab868f69f1d3414a2196f0a4fea..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/transaction/RetrieveLogRecordTransaction.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.transaction; - -import java.util.List; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import org.apache.shiro.SecurityUtils; -import org.caosdb.datetime.UTCDateTime; -import org.caosdb.server.accessControl.ACMPermissions; -import org.caosdb.server.database.DatabaseAccessManager; -import org.caosdb.server.database.access.Access; -import org.caosdb.server.database.backend.transaction.RetrieveLogRecord; - -public class RetrieveLogRecordTransaction implements TransactionInterface { - - private List<LogRecord> logRecords; - private final String logger; - private final Level level; - private final String message; - private UTCDateTime timestamp; - - public RetrieveLogRecordTransaction( - final String logger, final Level level, final String message) { - this.level = level; - this.timestamp = UTCDateTime.SystemMillisToUTCDateTime(System.currentTimeMillis()); - if (message != null && message.isEmpty()) { - this.message = null; - } else if (message != null) { - this.message = message.replaceAll("\\*", "%"); - } else { - this.message = null; - } - if (logger != null && logger.isEmpty()) { - this.logger = null; - } else if (logger != null) { - this.logger = logger.replaceAll("\\*", "%"); - } else { - this.logger = logger; - } - } - - @Override - public void execute() throws Exception { - SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_RETRIEVE_SERVERLOGS); - final Access access = DatabaseAccessManager.getInstance().acquireReadAccess(this); - try { - this.logRecords = - execute(new RetrieveLogRecord(this.logger, this.level, this.message), access) - .getLogRecords(); - } finally { - access.release(); - } - } - - public List<LogRecord> getLogRecords() { - return this.logRecords; - } - - @Override - public UTCDateTime getTimestamp() { - return timestamp; - } -} diff --git a/src/main/java/org/caosdb/server/transaction/UpdateACL.java b/src/main/java/org/caosdb/server/transaction/UpdateACL.java index 289b5d53a14c642b4ac85bd9c02dd5c69484fa91..4bb27c2399d97bca0035ea27b5f7e4797428b18e 100644 --- a/src/main/java/org/caosdb/server/transaction/UpdateACL.java +++ b/src/main/java/org/caosdb/server/transaction/UpdateACL.java @@ -67,7 +67,8 @@ public class UpdateACL extends Transaction<TransactionContainer> oldContainer.add(new UpdateEntity(e.getId(), null)); } - RetrieveFullEntityTransaction t = new RetrieveFullEntityTransaction(oldContainer); + RetrieveFullEntityTransaction t = + new RetrieveFullEntityTransaction(oldContainer, getTransactor()); execute(t, getAccess()); // the entities in this container only have an id and an ACL. -> Replace diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java index 939d0bf6473611cb1a0bb1ee28bfd91a568babd3..08f80915f362274cbe2a20ee844afb7075864252 100644 --- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java @@ -165,10 +165,10 @@ public class WriteTransaction extends Transaction<WritableContainer> // Retrieve a container which contains all IDs of those entities // which are to be updated. - execute(new RetrieveFullEntityTransaction(oldContainer), getAccess()); + execute(new RetrieveFullEntityTransaction(oldContainer, getTransactor()), getAccess()); // Retrieve all entities which are to be deleted. - execute(new RetrieveFullEntityTransaction(deleteContainer), getAccess()); + execute(new RetrieveFullEntityTransaction(deleteContainer, getTransactor()), getAccess()); // Check if any updates are to be processed. for (final EntityInterface entity : getContainer()) { diff --git a/src/test/docker/Dockerfile b/src/test/docker/Dockerfile index f0ae05e65389f4b89cb0cb1373a7475b054490cd..68ec89749f06f797ba67855e7671129700075787 100644 --- a/src/test/docker/Dockerfile +++ b/src/test/docker/Dockerfile @@ -6,7 +6,8 @@ RUN apt-get update && \ libtiff5-dev libjpeg-dev libopenjp2-7-dev zlib1g-dev \ libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk \ libharfbuzz-dev libfribidi-dev libxcb1-dev \ - python3-pip screen libpam0g-dev unzip curl shunit2 + python3-pip screen libpam0g-dev unzip curl shunit2 \ + python3-lxml libxml2-dev libxslt-dev RUN apt-get install -y \ libcairo2-dev diff --git a/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java b/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java index cfd8fcc9ba39cdf68dbf43be77de30f81c4fbec9..bb209f0eb5ea2a7438b7488955cb1a1d22424ca5 100644 --- a/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java +++ b/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java @@ -23,8 +23,21 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.concurrent.Callable; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authz.AuthorizationException; +import org.apache.shiro.authz.Permission; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.ExecutionException; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.Subject; +import org.caosdb.server.CaosDBServer; +import org.caosdb.server.accessControl.Principal; import org.caosdb.server.datatype.ReferenceValue; import org.caosdb.server.entity.Entity; import org.caosdb.server.entity.EntityID; @@ -32,15 +45,168 @@ import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.RetrieveEntity; import org.caosdb.server.entity.wrapper.Property; import org.caosdb.server.entity.xml.PropertyToElementStrategyTest; +import org.caosdb.server.permissions.EntityACL; import org.caosdb.server.query.Query.Selection; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; public class RetrieveFullEntityTest { + @BeforeAll + public static void setup() throws IOException { + CaosDBServer.initServerProperties(); + } + @Test public void testRetrieveSubEntities() { final RetrieveFullEntityTransaction r = - new RetrieveFullEntityTransaction(new EntityID("0")) { + new RetrieveFullEntityTransaction( + new EntityID("0"), + new Subject() { + + @Override + public Object getPrincipal() { + return new Principal("Bla", "Blub"); + } + + @Override + public PrincipalCollection getPrincipals() { + return null; + } + + @Override + public boolean isPermitted(String permission) { + assertEquals( + permission, org.caosdb.server.permissions.EntityPermission.RETRIEVE_ENTITY); + return true; + } + + @Override + public boolean isPermitted(Permission permission) { + return false; + } + + @Override + public boolean[] isPermitted(String... permissions) { + return null; + } + + @Override + public boolean[] isPermitted(List<Permission> permissions) { + return null; + } + + @Override + public boolean isPermittedAll(String... permissions) { + return false; + } + + @Override + public boolean isPermittedAll(Collection<Permission> permissions) { + return false; + } + + @Override + public void checkPermission(String permission) throws AuthorizationException {} + + @Override + public void checkPermission(Permission permission) throws AuthorizationException {} + + @Override + public void checkPermissions(String... permissions) throws AuthorizationException {} + + @Override + public void checkPermissions(Collection<Permission> permissions) + throws AuthorizationException {} + + @Override + public boolean hasRole(String roleIdentifier) { + return false; + } + + @Override + public boolean[] hasRoles(List<String> roleIdentifiers) { + return null; + } + + @Override + public boolean hasAllRoles(Collection<String> roleIdentifiers) { + return false; + } + + @Override + public void checkRole(String roleIdentifier) throws AuthorizationException {} + + @Override + public void checkRoles(Collection<String> roleIdentifiers) + throws AuthorizationException {} + + @Override + public void checkRoles(String... roleIdentifiers) throws AuthorizationException {} + + @Override + public void login(AuthenticationToken token) throws AuthenticationException {} + + @Override + public boolean isAuthenticated() { + return false; + } + + @Override + public boolean isRemembered() { + return false; + } + + @Override + public Session getSession() { + return null; + } + + @Override + public Session getSession(boolean create) { + return null; + } + + @Override + public void logout() {} + + @Override + public <V> V execute(Callable<V> callable) throws ExecutionException { + return null; + } + + @Override + public void execute(Runnable runnable) {} + + @Override + public <V> Callable<V> associateWith(Callable<V> callable) { + return null; + } + + @Override + public Runnable associateWith(Runnable runnable) { + return null; + } + + @Override + public void runAs(PrincipalCollection principals) + throws NullPointerException, IllegalStateException {} + + @Override + public boolean isRunAs() { + return false; + } + + @Override + public PrincipalCollection getPreviousPrincipals() { + return null; + } + + @Override + public PrincipalCollection releaseRunAs() { + return null; + } + }) { /** Mock-up */ @Override @@ -53,6 +219,7 @@ public class RetrieveFullEntityTest { assertEquals("description", selections.get(0).getSelector()); e.setDescription("A heart-shaped window."); + e.setEntityACL(new EntityACL()); } ; };