diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41cf3af0c2e6157d2e31b4f589bf5c256849b89d..0c5decad3d8be81a49dccdd4a748dc667994c587 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,11 +32,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Fixed ###
 
+* Denying a role permission has no effect
+  [#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). See security
+  notes below.
 * Missing RecordType leads to unexpected server error
   [#166](https://gitlab.com/caosdb/caosdb-server/-/issues/166)
 
 ### Security ###
 
+* Fixed [#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). This was
+  an error in the authorization procedure which allowed unprivileged users
+  execute insert, update or delete transactions on entities. However, the
+  unprivileged users would also need the correct entity permissions to do that.
+
+  Without backup, this means possible data loss. Also there was the possibility
+  to spam the database by creating unwanted entities.
+
 ### Documentation ###
 
 - Nested queries.
diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md
index d772f4b392b782e7bcb9a82f77898402218660c1..fbcb186e45ff5bff20ca7ff20fa321f547048527 100644
--- a/DEPENDENCIES.md
+++ b/DEPENDENCIES.md
@@ -7,6 +7,7 @@
 * `>=Java 11`
 * `>=Apache Maven 3.6.0`
 * `>=Make 4.2`
+* `>=gcc 8` (if PAM authentication is required)
 * `libpam` (if PAM authentication is required)
 * More dependencies are being pulled and installed automatically by Maven. See the complete list of dependencies in the [pom.xml](pom.xml)
 
diff --git a/README_SETUP.md b/README_SETUP.md
index ce6f03d7c287f3842eac6af2d017eed5a7d8bcb5..acb3a79ad256fbba6a0d0a69887bb7c7ba7b28b9 100644
--- a/README_SETUP.md
+++ b/README_SETUP.md
@@ -15,12 +15,18 @@ See [DEPENDENCIES.md](DEPENDENCIES.md).
 
 On Debian, the required packages can be installed with:
 
-    apt-get install git make mariadb-server maven openjdk-11-jdk-headless \
-      python3-pip screen libpam0g-dev unzip
+    apt-get install make mariadb-server maven openjdk-11-jdk-headless \
+      python3-pip libpam0g-dev unzip
 
 Note that installing MariaDB will uninstall existing MySQL packages and vice
 versa.
 
+#### Install the requirements on Fedora
+
+On Fedora, the required packages can be installed with:
+
+    sudo dnf install make pam-devel mariadb-server mariadb python3 java-17-openjdk-headless unzip gcc
+
 ### System
 
 * `>=Linux 4.0.0`, `x86_64`, e.g. Ubuntu 18.04
@@ -160,20 +166,47 @@ sources (if you called `make run` previously).
 
 ## Setup Eclipse
 
-1. Open Eclipse (recommended version: Oxygen.1a Release (4.7.1a))
-2. `File > New > Java Project`: Choose a project name and specify the location
-   of this repo. The JRE and Project layout should be configured automatically.
-   Now, the project should initially have two source-folders: `./src/main/java`
-   and `./src/test/java`. After a build, another one,
-   `./target/generated-sources/antlr4` should be generated. If there are more
-   than these three source-folders, reconfigure the projects source folders
-   appropriately with `Project > Properties > Java Build Path > Source`.
-3. In the `Package Explorer` view, right-click on the project and `Configure >
-   Convert to Maven Project`.
-4. In the `Package Explorer` view, right-click on the project and `Maven >
-   Update Project`.
-5. Usually a build of the project is started automatically. Otherwise `Project >
-   Build Project`.
+1. Open Eclipse (tested with 2022-R12)
+2. File > Import > Maven > Existing Maven Projects: Specify location.
+3. You will most likely encounter "Plugin execution not covered by lifecycle
+   configuration: ..." errors. Adapt the file
+   `<eclipse-workspace>/.metadata/.plugins/org.eclipse.m2e.core/lifecycle-mapping-metadata.xml`.
+
+   Example:
+
+   ```xml 
+   <?xml version="1.0" encoding="UTF-8"?>
+   <lifecycleMappingMetadata>
+     <pluginExecutions>
+       <pluginExecution>
+         <pluginExecutionFilter>
+           <groupId>com.coveo</groupId>
+           <artifactId>fmt-maven-plugin</artifactId>
+           <versionRange>2.5.1</versionRange>
+           <goals>
+             <goal>format</goal>
+           </goals>
+         </pluginExecutionFilter>
+         <action>
+           <ignore />
+         </action>
+       </pluginExecution>
+       <pluginExecution>
+         <pluginExecutionFilter>
+           <groupId>org.codehaus.mojo</groupId>
+           <artifactId>buildnumber-maven-plugin</artifactId>
+           <versionRange>1.4</versionRange>
+           <goals>
+             <goal>create-metadata</goal>
+           </goals>
+         </pluginExecutionFilter>
+         <action>
+           <ignore />
+         </action>
+       </pluginExecution>
+     </pluginExecutions>
+   </lifecycleMappingMetadata>
+   ```
 
 Done!
 
diff --git a/conf/core/server.conf b/conf/core/server.conf
index 46c0f83d4b7327d84c9009bdcba10b54ee0df70f..c030d6eb63d61ad2d9adc6a174877b1006396537 100644
--- a/conf/core/server.conf
+++ b/conf/core/server.conf
@@ -67,7 +67,7 @@ MYSQL_DATABASE_NAME=caosdb
 # User name for connecting to mysql
 MYSQL_USER_NAME=caosdb
 # Password for the user
-MYSQL_USER_PASSWORD=caosdb
+MYSQL_USER_PASSWORD=random1234
 # Schema of mysql procedures and tables which is required by this CaosDB instance
 MYSQL_SCHEMA_VERSION=v5.0
 
diff --git a/src/main/java/org/caosdb/server/jobs/core/AccessControl.java b/src/main/java/org/caosdb/server/jobs/core/AccessControl.java
index 4217c55e1153dafc302630823873fc75640ca9be..ede7658580811671f19f955f36faa59db4df922f 100644
--- a/src/main/java/org/caosdb/server/jobs/core/AccessControl.java
+++ b/src/main/java/org/caosdb/server/jobs/core/AccessControl.java
@@ -1,9 +1,10 @@
 /*
- * ** 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
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2023 IndiScale <info@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,17 +18,17 @@
  *
  * 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.jobs.core;
 
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.subject.Subject;
 import org.caosdb.server.accessControl.ACMPermissions;
-import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity;
+import org.caosdb.server.entity.DeleteEntity;
 import org.caosdb.server.entity.EntityInterface;
-import org.caosdb.server.entity.wrapper.Parent;
+import org.caosdb.server.entity.InsertEntity;
+import org.caosdb.server.entity.Role;
+import org.caosdb.server.entity.UpdateEntity;
 import org.caosdb.server.jobs.ContainerJob;
 import org.caosdb.server.jobs.JobAnnotation;
 import org.caosdb.server.jobs.TransactionStage;
@@ -35,6 +36,14 @@ import org.caosdb.server.transaction.Retrieve;
 import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
 
+/**
+ * Checks the TRANSACTION:* permissions before a transaction begins.
+ *
+ * <p>Users need TRANSACTION:INSERT:?ENTITY_ROLE? permission to insert an entity of the particular
+ * entity role. Likewise, they need the TRANSACTION:UPDATE or TRANSACTION:DELETE permissions.
+ *
+ * @author Timm Fitschen <f.fitschen@indiscale.com>
+ */
 @JobAnnotation(stage = TransactionStage.INIT)
 public class AccessControl extends ContainerJob {
 
@@ -46,12 +55,15 @@ public class AccessControl extends ContainerJob {
       super(permission, description);
     }
 
-    public final String toString(String entityRole) {
-      return toString().replace(ENTITY_ROLE_PARAMETER, entityRole);
+    public final String toString(Role entityRole) {
+      String roleString = entityRole == null ? "" : entityRole.toString();
+      return toString().replace(ENTITY_ROLE_PARAMETER, roleString);
     }
 
-    public final String toString(String transaction, String entityRole) {
-      return "TRANSACTION:" + transaction + (entityRole != null ? (":" + entityRole) : "");
+    public final String toString(String transaction, Role entityRole) {
+      return "TRANSACTION:"
+          + transaction
+          + (entityRole != null ? (":" + entityRole.toString()) : "");
     }
 
     public static String init() {
@@ -80,38 +92,26 @@ public class AccessControl extends ContainerJob {
   protected void run() {
     final Subject subject = SecurityUtils.getSubject();
 
-    // subject has complete permissions for this kind of transaction
-    if (subject.isPermitted(
-        TRANSACTION_PERMISSIONS.toString(getTransaction().getClass().getSimpleName(), null))) {
-      return;
-    }
-
     if (getTransaction() instanceof Retrieve) {
       return;
     }
 
     for (final EntityInterface e : getContainer()) {
 
-      // per role permission
-      if (subject.isPermitted(
-          TRANSACTION_PERMISSIONS.toString(
-              getTransaction().getClass().getSimpleName(), e.getRole().toString()))) {
-        continue;
-      }
-
-      // special annotations permission
-      if (e.hasParents() && e.getParents().size() == 1) {
-        final Parent par1 = e.getParents().get(0);
-        if (par1.hasId() && !par1.getId().isTemporary()) {
-          execute(new RetrieveSparseEntity(par1));
+      if (e instanceof InsertEntity) {
+        if (subject.isPermitted(INSERT.toString(e.getRole()))) {
+          continue;
         }
-        if (par1.hasName()
-            && par1.getName().equals("CommentAnnotation")
-            && subject.isPermitted(
-                getTransaction().getClass().getSimpleName() + ":CommentAnnotation")) {
+      } else if (e instanceof DeleteEntity) {
+        if (subject.isPermitted(DELETE.toString(e.getRole()))) {
+          continue;
+        }
+      } else if (e instanceof UpdateEntity) {
+        if (subject.isPermitted(UPDATE.toString(e.getRole()))) {
           continue;
         }
       }
+
       e.setEntityStatus(EntityStatus.UNQUALIFIED);
       e.addMessage(ServerMessages.AUTHORIZATION_ERROR);
     }