You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2021/10/17 20:51:34 UTC

[incubator-streampipes] 02/02: [STREAMPIPES-426] Add initial draft of permission management

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch STREAMPIPES-426
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit df6d25b72ef06062a72c4a56b4ae5fa8132842be
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Sun Oct 17 22:51:19 2021 +0200

    [STREAMPIPES-426] Add initial draft of permission management
---
 .../streampipes/commons/random/UUIDGenerator.java  |  19 +---
 .../streampipes/model/client/user/Group.java       |  13 ++-
 .../streampipes/model/client/user/Permission.java  | 104 +++++++++++++++++++++
 .../model/client/user/PermissionBuilder.java       |  51 ++++++++++
 .../streampipes/model/client/user/Principal.java   |  12 +++
 .../streampipes/model/client/user/Privilege.java   |  52 ++++-------
 .../apache/streampipes/model/client/user/Role.java |   6 +-
 .../manager/permission/PermissionManager.java      |  24 ++---
 .../manager/pipeline/PipelineManager.java          |  20 +++-
 .../manager/setup/CouchDbInstallationStep.java     |  18 +++-
 .../base/impl/AbstractAuthGuardedRestResource.java |  11 +++
 .../streampipes/rest/impl/PipelineResource.java    |   8 +-
 .../org/apache/streampipes/rest/impl/Version.java  |   4 +-
 .../rest/impl/security/AuthConstants.java          |   1 +
 .../rest/impl/security/SpPermissionEvaluator.java  |  13 ++-
 .../streampipes/storage/api/INoSqlStorage.java     |   2 +
 .../storage/api/IPermissionStorage.java            |  27 +++---
 .../streampipes/storage/api/IUserStorage.java      |   6 +-
 .../storage/couchdb/CouchDbStorageManager.java     |   5 +
 .../storage/couchdb/dao/AbstractDao.java           |  28 ++----
 .../couchdb/dao/{AbstractDao.java => CrudDao.java} |  22 ++---
 .../dao/{FindAllCommand.java => CrudViewDao.java}  |  19 ++--
 .../storage/couchdb/dao/FindAllCommand.java        |  10 +-
 .../couchdb/impl/PermissionStorageImpl.java        |  76 +++++++++++++++
 .../storage/couchdb/impl/UserGroupStorageImpl.java |  18 ++--
 .../storage/couchdb/impl/UserStorage.java          |  41 +++-----
 .../management/model/PrincipalUserDetails.java     |  11 ++-
 ...Builder.java => GrantedAuthoritiesBuilder.java} |   4 +-
 .../management/util/GrantedPermissionsBuilder.java |  44 ++++-----
 29 files changed, 464 insertions(+), 205 deletions(-)

diff --git a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/random/UUIDGenerator.java
similarity index 63%
copy from streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
copy to streampipes-commons/src/main/java/org/apache/streampipes/commons/random/UUIDGenerator.java
index c42e0a4..5c0eb06 100644
--- a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/random/UUIDGenerator.java
@@ -15,22 +15,13 @@
  * limitations under the License.
  *
  */
-package org.apache.streampipes.rest.core.base.impl;
+package org.apache.streampipes.commons.random;
 
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.SecurityContext;
+import java.util.UUID;
 
-public class AbstractAuthGuardedRestResource extends AbstractRestResource {
+public class UUIDGenerator {
 
-  @Context
-  protected SecurityContext securityContext;
-
-  protected boolean isAuthenticated() {
-    return this.securityContext.getUserPrincipal() != null;
-  }
-
-  protected String getAuthenticatedUsername() {
-    return this.securityContext.getUserPrincipal().getName();
+  public static String generateUuid() {
+    return UUID.randomUUID().toString().replace("-", "");
   }
-
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Group.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Group.java
index 8ee6e90..8b319f0 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Group.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Group.java
@@ -17,11 +17,11 @@
  */
 package org.apache.streampipes.model.client.user;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.gson.annotations.SerializedName;
 import org.apache.streampipes.model.shared.annotation.TsModel;
 
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 @TsModel
@@ -30,6 +30,9 @@ public class Group {
   protected @SerializedName("_id") String groupId;
   protected @SerializedName("_rev") String rev;
 
+  @JsonIgnore
+  private String $type = "group";
+
   private String groupName;
 
   private Set<Role> roles;
@@ -69,4 +72,12 @@ public class Group {
   public void setRoles(Set<Role> roles) {
     this.roles = roles;
   }
+
+  public String get$type() {
+    return $type;
+  }
+
+  public void set$type(String $type) {
+    this.$type = $type;
+  }
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Permission.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Permission.java
new file mode 100644
index 0000000..2c0f2cb
--- /dev/null
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Permission.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.model.client.user;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Permission {
+
+  protected @SerializedName("_id") String permissionId;
+  protected @SerializedName("_rev") String rev;
+
+  @JsonIgnore
+  private String $type = "permission";
+
+  private String objectInstanceId;
+  private String objectClassName;
+
+  private String ownerSid;
+
+  private List<String> allowedSids;
+
+  public Permission() {
+    this.allowedSids = new ArrayList<>();
+  }
+
+  public String getPermissionId() {
+    return permissionId;
+  }
+
+  public void setPermissionId(String permissionId) {
+    this.permissionId = permissionId;
+  }
+
+  public String getRev() {
+    return rev;
+  }
+
+  public void setRev(String rev) {
+    this.rev = rev;
+  }
+
+  public String getObjectInstanceId() {
+    return objectInstanceId;
+  }
+
+  public void setObjectInstanceId(String objectInstanceId) {
+    this.objectInstanceId = objectInstanceId;
+  }
+
+  public String getObjectClassName() {
+    return objectClassName;
+  }
+
+  public void setObjectClassName(String objectClassName) {
+    this.objectClassName = objectClassName;
+  }
+
+  public String getOwnerSid() {
+    return ownerSid;
+  }
+
+  public void setOwnerSid(String ownerSid) {
+    this.ownerSid = ownerSid;
+  }
+
+  public void addAllowedSid(String sid) {
+    this.allowedSids.add(sid);
+  }
+
+  public List<String> getAllowedSids() {
+    return allowedSids;
+  }
+
+  public void setAllowedSids(List<String> allowedSids) {
+    this.allowedSids = allowedSids;
+  }
+
+  public String get$type() {
+    return $type;
+  }
+
+  public void set$type(String $type) {
+    this.$type = $type;
+  }
+}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/PermissionBuilder.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/PermissionBuilder.java
new file mode 100644
index 0000000..70da030
--- /dev/null
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/PermissionBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.model.client.user;
+
+public class PermissionBuilder {
+
+  private Permission permission;
+
+  public static PermissionBuilder create(String objectInstanceId,
+                                         Class<?> objectInstanceClass,
+                                         String ownerSid) {
+    return new PermissionBuilder(
+            objectInstanceId,
+            objectInstanceClass,
+            ownerSid
+    );
+  }
+
+  private PermissionBuilder(String objectInstanceId,
+                            Class<?> objectInstanceClass,
+                            String ownerSid) {
+    this.permission = new Permission();
+    this.permission.setObjectInstanceId(objectInstanceId);
+    this.permission.setObjectClassName(objectInstanceClass.getCanonicalName());
+    this.permission.setOwnerSid(ownerSid);
+  }
+
+  public PermissionBuilder with(String sid) {
+    this.permission.addAllowedSid(sid);
+    return this;
+  }
+
+  public Permission build() {
+    return permission;
+  }
+}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java
index 777556a..0c06b40 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Principal.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.model.client.user;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.gson.annotations.SerializedName;
 
 import java.util.ArrayList;
@@ -30,6 +31,9 @@ public abstract class Principal {
 	protected @SerializedName("_id") String principalId;
 	protected @SerializedName("_rev") String rev;
 
+	@JsonIgnore
+	private String $type = "principal";
+
 	private boolean accountEnabled;
 	private boolean accountLocked;
 	private boolean accountExpired;
@@ -189,4 +193,12 @@ public abstract class Principal {
 	public void setObjectPermissions(Set<String> objectPermissions) {
 		this.objectPermissions = objectPermissions;
 	}
+
+	public String get$type() {
+		return $type;
+	}
+
+	public void set$type(String $type) {
+		this.$type = $type;
+	}
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Privilege.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Privilege.java
index 4170e31..5950ba0 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Privilege.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Privilege.java
@@ -22,58 +22,50 @@ import org.apache.streampipes.model.shared.annotation.TsModel;
 @TsModel
 public enum Privilege {
   // Pipelines
-  PRIVILEGE_CREATE_PIPELINE(Constants.PRIVILEGE_CREATE_PIPELINE_VALUE),
   PRIVILEGE_READ_PIPELINE(Constants.PRIVILEGE_READ_PIPELINE_VALUE),
-  PRIVILEGE_UPDATE_PIPELINE(Constants.PRIVILEGE_UPDATE_PIPELINE_VALUE),
+  PRIVILEGE_WRITE_PIPELINE(Constants.PRIVILEGE_WRITE_PIPELINE_VALUE),
   PRIVILEGE_DELETE_PIPELINE(Constants.PRIVILEGE_DELETE_PIPELINE_VALUE),
 
   // Adapters
-  PRIVILEGE_CREATE_ADAPTER(Constants.PRIVILEGE_CREATE_ADAPTER_VALUE),
   PRIVILEGE_READ_ADAPTER(Constants.PRIVILEGE_READ_ADAPTER_VALUE),
-  PRIVILEGE_UPDATE_ADAPTER(Constants.PRIVILEGE_UPDATE_ADAPTER_VALUE),
+  PRIVILEGE_WRITE_ADAPTER(Constants.PRIVILEGE_WRITE_ADAPTER_VALUE),
   PRIVILEGE_DELETE_ADAPTER(Constants.PRIVILEGE_DELETE_ADAPTER_VALUE),
 
   // Pipeline Elements
-  PRIVILEGE_CREATE_PIPELINE_ELEMENT(Constants.PRIVILEGE_CREATE_PIPELINE_ELEMENT_VALUE),
   PRIVILEGE_READ_PIPELINE_ELEMENT(Constants.PRIVILEGE_READ_PIPELINE_ELEMENT_VALUE),
-  PRIVILEGE_UPDATE_PIPELINE_ELEMENT(Constants.PRIVILEGE_UPDATE_PIPELINE_ELEMENT_VALUE),
+  PRIVILEGE_WRITE_PIPELINE_ELEMENT(Constants.PRIVILEGE_WRITE_PIPELINE_ELEMENT_VALUE),
   PRIVILEGE_DELETE_PIPELINE_ELEMENT(Constants.PRIVILEGE_DELETE_PIPELINE_ELEMENT_VALUE),
 
   // Dashboard
-  PRIVILEGE_CREATE_DASHBOARD(Constants.PRIVILEGE_CREATE_DASHBOARD_VALUE),
   PRIVILEGE_READ_DASHBOARD(Constants.PRIVILEGE_READ_DASHBOARD_VALUE),
-  PRIVILEGE_UPDATE_DASHBOARD(Constants.PRIVILEGE_UPDATE_DASHBOARD_VALUE),
+  PRIVILEGE_WRITE_DASHBOARD(Constants.PRIVILEGE_WRITE_DASHBOARD_VALUE),
   PRIVILEGE_DELETE_DASHBOARD(Constants.PRIVILEGE_DELETE_DASHBOARD_VALUE),
 
   // Dashboard widget
-  PRIVILEGE_CREATE_DASHBOARD_WIDGET(Constants.PRIVILEGE_CREATE_DASHBOARD_WIDGET_VALUE),
   PRIVILEGE_READ_DASHBOARD_WIDGET(Constants.PRIVILEGE_READ_DASHBOARD_WIDGET_VALUE),
-  PRIVILEGE_UPDATE_DASHBOARD_WIDGET(Constants.PRIVILEGE_UPDATE_DASHBOARD_WIDGET_VALUE),
+  PRIVILEGE_WRITE_DASHBOARD_WIDGET(Constants.PRIVILEGE_WRITE_DASHBOARD_WIDGET_VALUE),
   PRIVILEGE_DELETE_DASHBOARD_WIDGET(Constants.PRIVILEGE_DELETE_DASHBOARD_WIDGET_VALUE),
 
   // Data Explorer view
-  PRIVILEGE_CREATE_DATA_EXPLORER_VIEW(Constants.PRIVILEGE_CREATE_DATA_EXPLORER_VIEW_VALUE),
   PRIVILEGE_READ_DATA_EXPLORER_VIEW(Constants.PRIVILEGE_READ_DATA_EXPLORER_VIEW_VALUE),
-  PRIVILEGE_UPDATE_DATA_EXPLORER_VIEW(Constants.PRIVILEGE_UPDATE_DATA_EXPLORER_VIEW_VALUE),
+  PRIVILEGE_WRITE_DATA_EXPLORER_VIEW(Constants.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW_VALUE),
   PRIVILEGE_DELETE_DATA_EXPLORER_VIEW(Constants.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW_VALUE),
 
   // Data Explorer widget
-  PRIVILEGE_CREATE_DATA_EXPLORER_WIDGET(Constants.PRIVILEGE_CREATE_DATA_EXPLORER_WIDGET_VALUE),
   PRIVILEGE_READ_DATA_EXPLORER_WIDGET(Constants.PRIVILEGE_READ_DATA_EXPLORER_WIDGET_VALUE),
-  PRIVILEGE_UPDATE_DATA_EXPLORER_WIDGET(Constants.PRIVILEGE_UPDATE_DATA_EXPLORER_WIDGET_VALUE),
+  PRIVILEGE_WRITE_DATA_EXPLORER_WIDGET(Constants.PRIVILEGE_WRITE_DATA_EXPLORER_WIDGET_VALUE),
   PRIVILEGE_DELETE_DATA_EXPLORER_WIDGET(Constants.PRIVILEGE_DELETE_DATA_EXPLORER_WIDGET_VALUE),
 
   // Apps
   PRIVILEGE_READ_APPS(Constants.PRIVILEGE_READ_APPS_VALUE),
-  PRIVILEGE_UPDATE_APPS(Constants.PRIVILEGE_UPDATE_APPS_VALUE),
+  PRIVILEGE_WRITE_APPS(Constants.PRIVILEGE_WRITE_APPS_VALUE),
 
   // NOTIFICATIONS
   PRIVILEGE_READ_NOTIFICATIONS(Constants.PRIVILEGE_READ_NOTIFICATIONS_VALUE),
 
   // FILES
   PRIVILEGE_READ_FILES(Constants.PRIVILEGE_READ_FILES_VALUE),
-  PRIVILEGE_CREATE_FILES(Constants.PRIVILEGE_CREATE_FILES_VALUE),
-  PRIVILEGE_UPDATE_FILES(Constants.PRIVILEGE_UPDATE_FILES_VALUE),
+  PRIVILEGE_WRITE_FILES(Constants.PRIVILEGE_WRITE_FILES_VALUE),
   PRIVILEGE_DELETE_FILES(Constants.PRIVILEGE_DELETE_FILES_VALUE);
 
   private String privilegeString;
@@ -83,49 +75,41 @@ public enum Privilege {
   }
 
   public static final class Constants {
-    public static final String PRIVILEGE_CREATE_PIPELINE_VALUE = "PRIVILEGE_CREATE_PIPELINE";
     public static final String PRIVILEGE_READ_PIPELINE_VALUE = "PRIVILEGE_READ_PIPELINE";
-    public static final String PRIVILEGE_UPDATE_PIPELINE_VALUE = "PRIVILEGE_UPDATE_PIPELINE";
+    public static final String PRIVILEGE_WRITE_PIPELINE_VALUE = "PRIVILEGE_WRITE_PIPELINE";
     public static final String PRIVILEGE_DELETE_PIPELINE_VALUE = "PRIVILEGE_DELETE_PIPELINE";
 
-    public static final String PRIVILEGE_CREATE_ADAPTER_VALUE = "PRIVILEGE_CREATE_ADAPTER";
     public static final String PRIVILEGE_READ_ADAPTER_VALUE = "PRIVILEGE_READ_ADAPTER";
-    public static final String PRIVILEGE_UPDATE_ADAPTER_VALUE = "PRIVILEGE_UPDATE_ADAPTER";
+    public static final String PRIVILEGE_WRITE_ADAPTER_VALUE = "PRIVILEGE_WRITE_ADAPTER";
     public static final String PRIVILEGE_DELETE_ADAPTER_VALUE = "PRIVILEGE_DELETE_ADAPTER";
 
-    public static final String PRIVILEGE_CREATE_PIPELINE_ELEMENT_VALUE = "PRIVILEGE_CREATE_PIPELINE_ELEMENT";
     public static final String PRIVILEGE_READ_PIPELINE_ELEMENT_VALUE = "PRIVILEGE_READ_PIPELINE_ELEMENT";
-    public static final String PRIVILEGE_UPDATE_PIPELINE_ELEMENT_VALUE = "PRIVILEGE_UPDATE_PIPELINE_ELEMENT";
+    public static final String PRIVILEGE_WRITE_PIPELINE_ELEMENT_VALUE = "PRIVILEGE_WRITE_PIPELINE_ELEMENT";
     public static final String PRIVILEGE_DELETE_PIPELINE_ELEMENT_VALUE = "PRIVILEGE_DELETE_PIPELINE_ELEMENT";
 
-    public static final String PRIVILEGE_CREATE_DASHBOARD_VALUE = "PRIVILEGE_CREATE_DASHBOARD";
     public static final String PRIVILEGE_READ_DASHBOARD_VALUE = "PRIVILEGE_READ_DASHBOARD";
-    public static final String PRIVILEGE_UPDATE_DASHBOARD_VALUE = "PRIVILEGE_UPDATE_DASHBOARD";
+    public static final String PRIVILEGE_WRITE_DASHBOARD_VALUE = "PRIVILEGE_WRITE_DASHBOARD";
     public static final String PRIVILEGE_DELETE_DASHBOARD_VALUE = "PRIVILEGE_DELETE_DASHBOARD";
 
-    public static final String PRIVILEGE_CREATE_DASHBOARD_WIDGET_VALUE = "PRIVILEGE_CREATE_DASHBOARD_WIDGET";
     public static final String PRIVILEGE_READ_DASHBOARD_WIDGET_VALUE = "PRIVILEGE_READ_DASHBOARD_WIDGET";
-    public static final String PRIVILEGE_UPDATE_DASHBOARD_WIDGET_VALUE = "PRIVILEGE_UPDATE_DASHBOARD_WIDGET";
+    public static final String PRIVILEGE_WRITE_DASHBOARD_WIDGET_VALUE = "PRIVILEGE_WRITE_DASHBOARD_WIDGET";
     public static final String PRIVILEGE_DELETE_DASHBOARD_WIDGET_VALUE = "PRIVILEGE_DELETE_DASHBOARD_WIDGET";
 
-    public static final String PRIVILEGE_CREATE_DATA_EXPLORER_VIEW_VALUE = "PRIVILEGE_CREATE_DATA_EXPLORER_VIEW";
     public static final String PRIVILEGE_READ_DATA_EXPLORER_VIEW_VALUE = "PRIVILEGE_READ_DATA_EXPLORER_VIEW";
-    public static final String PRIVILEGE_UPDATE_DATA_EXPLORER_VIEW_VALUE = "PRIVILEGE_UPDATE_DATA_EXPLORER_VIEW";
+    public static final String PRIVILEGE_WRITE_DATA_EXPLORER_VIEW_VALUE = "PRIVILEGE_WRITE_DATA_EXPLORER_VIEW";
     public static final String PRIVILEGE_DELETE_DATA_EXPLORER_VIEW_VALUE = "PRIVILEGE_DELETE_DATA_EXPLORER_VIEW";
 
-    public static final String PRIVILEGE_CREATE_DATA_EXPLORER_WIDGET_VALUE = "PRIVILEGE_CREATE_DATA_EXPLORER_WIDGET";
     public static final String PRIVILEGE_READ_DATA_EXPLORER_WIDGET_VALUE = "PRIVILEGE_READ_DATA_EXPLORER_WIDGET";
-    public static final String PRIVILEGE_UPDATE_DATA_EXPLORER_WIDGET_VALUE = "PRIVILEGE_UPDATE_DATA_EXPLORER_WIDGET";
+    public static final String PRIVILEGE_WRITE_DATA_EXPLORER_WIDGET_VALUE = "PRIVILEGE_WRITE_DATA_EXPLORER_WIDGET";
     public static final String PRIVILEGE_DELETE_DATA_EXPLORER_WIDGET_VALUE = "PRIVILEGE_DELETE_DATA_EXPLORER_WIDGET";
 
     public static final String PRIVILEGE_READ_APPS_VALUE = "PRIVILEGE_READ_APPS";
-    public static final String PRIVILEGE_UPDATE_APPS_VALUE = "PRIVILEGE_UPDATE_APPS";
+    public static final String PRIVILEGE_WRITE_APPS_VALUE = "PRIVILEGE_WRITE_APPS";
 
     public static final String PRIVILEGE_READ_NOTIFICATIONS_VALUE = "PRIVILEGE_READ_NOTIFICATIONS";
 
     public static final String PRIVILEGE_READ_FILES_VALUE = "PRIVILEGE_READ_FILES";
-    public static final String PRIVILEGE_CREATE_FILES_VALUE = "PRIVILEGE_CREATE_FILES";
-    public static final String PRIVILEGE_UPDATE_FILES_VALUE = "PRIVILEGE_UPDATE_FILES";
+    public static final String PRIVILEGE_WRITE_FILES_VALUE = "PRIVILEGE_WRITE_FILES";
     public static final String PRIVILEGE_DELETE_FILES_VALUE = "PRIVILEGE_DELETE_FILES";
   }
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
index 11c5c2a..58adc39 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
@@ -30,17 +30,15 @@ public enum Role {
 
   ROLE_PIPELINE_ADMIN(
           Constants.ROLE_PIPELINE_ADMIN_VALUE,
-          Privilege.PRIVILEGE_CREATE_PIPELINE,
           Privilege.PRIVILEGE_READ_PIPELINE,
-          Privilege.PRIVILEGE_UPDATE_PIPELINE,
+          Privilege.PRIVILEGE_WRITE_PIPELINE,
           Privilege.PRIVILEGE_DELETE_PIPELINE
   ),
 
   ROLE_DASHBOARD_ADMIN(
           Constants.ROLE_DASHBOARD_ADMIN_VALUE,
-          Privilege.PRIVILEGE_CREATE_DASHBOARD,
           Privilege.PRIVILEGE_READ_DASHBOARD,
-          Privilege.PRIVILEGE_UPDATE_DASHBOARD,
+          Privilege.PRIVILEGE_WRITE_DASHBOARD,
           Privilege.PRIVILEGE_DELETE_DASHBOARD
   ),
 
diff --git a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/permission/PermissionManager.java
similarity index 61%
copy from streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
copy to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/permission/PermissionManager.java
index c42e0a4..0472dc7 100644
--- a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/permission/PermissionManager.java
@@ -15,22 +15,18 @@
  * limitations under the License.
  *
  */
-package org.apache.streampipes.rest.core.base.impl;
+package org.apache.streampipes.manager.permission;
 
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.SecurityContext;
+import org.apache.streampipes.model.client.user.Permission;
+import org.apache.streampipes.model.client.user.PermissionBuilder;
+import org.apache.streampipes.model.pipeline.Pipeline;
 
-public class AbstractAuthGuardedRestResource extends AbstractRestResource {
+public class PermissionManager {
 
-  @Context
-  protected SecurityContext securityContext;
-
-  protected boolean isAuthenticated() {
-    return this.securityContext.getUserPrincipal() != null;
-  }
-
-  protected String getAuthenticatedUsername() {
-    return this.securityContext.getUserPrincipal().getName();
+  public Permission makePermission(Pipeline pipeline,
+                                   String ownerSid) {
+    return PermissionBuilder
+            .create(pipeline.getPipelineId(), pipeline.getClass(), ownerSid)
+            .build();
   }
-
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
index 2e3172f..c1a0680 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
@@ -18,16 +18,19 @@
 
 package org.apache.streampipes.manager.pipeline;
 
+import org.apache.streampipes.commons.random.UUIDGenerator;
 import org.apache.streampipes.manager.operations.Operations;
+import org.apache.streampipes.manager.permission.PermissionManager;
 import org.apache.streampipes.manager.storage.UserManagementService;
+import org.apache.streampipes.model.client.user.Permission;
 import org.apache.streampipes.model.pipeline.Pipeline;
 import org.apache.streampipes.model.pipeline.PipelineOperationStatus;
+import org.apache.streampipes.storage.api.IPermissionStorage;
 import org.apache.streampipes.storage.api.IPipelineStorage;
 import org.apache.streampipes.storage.management.StorageDispatcher;
 
 import java.util.Date;
 import java.util.List;
-import java.util.UUID;
 
 public class PipelineManager {
 
@@ -59,17 +62,20 @@ public class PipelineManager {
 
     /**
      * Adds a new pipeline for the user with the username to the storage
-     * @param username
+     * @param principalSid the ID of the owner principal
      * @param pipeline
      * @return the pipelineId
      */
-    public static String addPipeline(String username, Pipeline pipeline) {
+    public static String addPipeline(String principalSid, Pipeline pipeline) {
 
         // call by reference bad smell
-        String pipelineId = UUID.randomUUID().toString();
-        preparePipelineBasics(username, pipeline, pipelineId);
+        String pipelineId = UUIDGenerator.generateUuid();
+        preparePipelineBasics(principalSid, pipeline, pipelineId);
         Operations.storePipeline(pipeline);
 
+        Permission permission = new PermissionManager().makePermission(pipeline, principalSid);
+        getPermissionStorage().addPermission(permission);
+
         return pipelineId;
     }
 
@@ -121,4 +127,8 @@ public class PipelineManager {
     private static IPipelineStorage getPipelineStorage() {
         return StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI();
     }
+
+    private static IPermissionStorage getPermissionStorage() {
+        return StorageDispatcher.INSTANCE.getNoSqlStore().getPermissionStorage();
+    }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
index 7143075..c1a05f8 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
@@ -142,17 +142,29 @@ public class CouchDbInstallationStep extends InstallationStep {
       Map<String, MapReduce> views = new HashMap<>();
 
       MapReduce passwordFunction = new MapReduce();
-      passwordFunction.setMap("function(doc) { if(doc.username && doc.principalType === 'USER_ACCOUNT' && doc.password) { emit(doc.username, doc.password); } }");
+      passwordFunction.setMap("function(doc) { if(doc.properties.username && doc.properties.principalType === 'USER_ACCOUNT' && doc.properties.password) { emit(doc.properties.username, doc.properties.password); } }");
 
       MapReduce usernameFunction = new MapReduce();
-      usernameFunction.setMap("function(doc) { if(doc.username) { emit(doc.username, doc); } }");
+      usernameFunction.setMap("function(doc) { if(doc.properties.username) { emit(doc.properties.username, doc); } }");
+
+      MapReduce permissionFunction = new MapReduce();
+      permissionFunction.setMap("function(doc) { if(doc.$type === 'permission') { emit(doc._id, doc); } }");
+
+      MapReduce groupFunction = new MapReduce();
+      groupFunction.setMap("function(doc) { if(doc.$type === 'group') { emit(doc._id, doc); } }");
 
       MapReduce tokenFunction = new MapReduce();
-      tokenFunction.setMap("function(doc) { if (doc.userApiTokens) { doc.userApiTokens.forEach(function(token) { emit(token.hashedToken, doc.email); });}}");
+      tokenFunction.setMap("function(doc) { if (doc.properties.userApiTokens) { doc.properties.userApiTokens.forEach(function(token) { emit(token.properties.hashedToken, doc.properties.email); });}}");
+
+      MapReduce userPermissionFunction = new MapReduce();
+      userPermissionFunction.setMap("function(doc) { if (doc.$type === 'permission') {emit(doc.ownerSid, doc); for(var i = 0; i < doc.allowedSids.length; i++) {emit(doc.allowedSids[i],doc)}}}");
 
       views.put("password", passwordFunction);
       views.put("username", usernameFunction);
+      views.put("groups", groupFunction);
+      views.put("permissions", permissionFunction);
       views.put("token", tokenFunction);
+      views.put("userpermissions", userPermissionFunction);
 
       userDocument.setViews(views);
       Response resp = Utils.getCouchDbUserClient().design().synchronizeWithDb(userDocument);
diff --git a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java b/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
index c42e0a4..1e24ff5 100644
--- a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
+++ b/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
@@ -17,6 +17,9 @@
  */
 package org.apache.streampipes.rest.core.base.impl;
 
+import org.apache.streampipes.user.management.model.PrincipalUserDetails;
+import org.springframework.security.core.context.SecurityContextHolder;
+
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.SecurityContext;
 
@@ -33,4 +36,12 @@ public class AbstractAuthGuardedRestResource extends AbstractRestResource {
     return this.securityContext.getUserPrincipal().getName();
   }
 
+  protected PrincipalUserDetails<?> getPrincipal() {
+    return (PrincipalUserDetails<?>) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+  }
+
+  protected String getAuthenticatedUserSid() {
+    return getPrincipal().getDetails().getPrincipalId();
+  }
+
 }
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java
index d741409..55345c1 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java
@@ -42,6 +42,7 @@ import org.apache.streampipes.rest.impl.security.AuthConstants;
 import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PostFilter;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;
 
@@ -68,11 +69,10 @@ public class PipelineResource extends AbstractAuthGuardedRestResource {
                                   mediaType = "application/json",
                                   array = @ArraySchema(schema = @Schema(implementation = Pipeline.class)))
                   })})
-  @PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
+  @PreAuthorize(AuthConstants.HAS_READ_PIPELINE_PRIVILEGE)
+  @PostFilter("hasPermission(filterObject.pipelineId, 'READ')")
   public List<Pipeline> getOwn() {
     return PipelineManager.getAllPipelines();
-    //return ok(PipelineManager.getOwnPipelines(getAuthenticatedUsername()));
-
   }
 
   @GET
@@ -165,7 +165,7 @@ public class PipelineResource extends AbstractAuthGuardedRestResource {
   @PreAuthorize(AuthConstants.HAS_CREATE_PIPELINE_PRIVILEGE)
   public Response addPipeline(Pipeline pipeline) {
 
-    String pipelineId = PipelineManager.addPipeline(getAuthenticatedUsername(), pipeline);
+    String pipelineId = PipelineManager.addPipeline(getAuthenticatedUserSid(), pipeline);
     SuccessMessage message = Notifications.success("Pipeline stored");
     message.addNotification(new Notification("id", pipelineId));
     return ok(message);
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Version.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Version.java
index 733b434..d56851b 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Version.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Version.java
@@ -19,7 +19,7 @@ package org.apache.streampipes.rest.impl;
 
 import org.apache.streampipes.manager.info.SystemInfoProvider;
 import org.apache.streampipes.manager.info.VersionInfoProvider;
-import org.apache.streampipes.rest.core.base.impl.AbstractRestResource;
+import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -28,7 +28,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 @Path("/v2/info")
-public class Version extends AbstractRestResource {
+public class Version extends AbstractAuthGuardedRestResource {
 
   @GET
   @Path("/versions")
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/AuthConstants.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/AuthConstants.java
index 7ee6da7..f457f47 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/AuthConstants.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/AuthConstants.java
@@ -43,5 +43,6 @@ public class AuthConstants {
   public static final String HAS_UPDATE_PIPELINE_PRIVILEGE = BS + IS_ADMIN_ROLE + OR + HAS_ANY_AUTHORITY + PRIVILEGE_UPDATE_PIPELINE_VALUE + Q + BE2;
   public static final String HAS_DELETE_PIPELINE_PRIVILEGE = BS + IS_ADMIN_ROLE + OR + HAS_ANY_AUTHORITY + PRIVILEGE_DELETE_PIPELINE_VALUE + Q + BE2;
 
+  public static final String IS_AUTHENTICATED = "isAuthenticated()";
 
 }
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/SpPermissionEvaluator.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/SpPermissionEvaluator.java
index 6769d51..d33c153 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/SpPermissionEvaluator.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/security/SpPermissionEvaluator.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.rest.impl.security;
 
+import org.apache.streampipes.user.management.model.PrincipalUserDetails;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.access.PermissionEvaluator;
 import org.springframework.security.core.Authentication;
@@ -27,14 +28,18 @@ import java.io.Serializable;
 public class SpPermissionEvaluator implements PermissionEvaluator {
 
   @Override
-  public boolean hasPermission(Authentication authentication, Object o, Object o1) {
+  public boolean hasPermission(Authentication authentication, Object o, Object permission) {
+    String objectInstanceId = (String) o;
 
-    return true;
+    return getUserDetails(authentication).getAllObjectPermissions().contains(objectInstanceId);
   }
 
   @Override
-  public boolean hasPermission(Authentication authentication, Serializable serializable, String s, Object o) {
+  public boolean hasPermission(Authentication authentication, Serializable serializable, String s, Object permission) {
+    return getUserDetails(authentication).getAllObjectPermissions().contains(serializable.toString());
+  }
 
-    return true;
+  private PrincipalUserDetails<?> getUserDetails(Authentication authentication) {
+    return (PrincipalUserDetails<?>) authentication.getPrincipal();
   }
 }
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
index e2ce843..8b99e42 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
@@ -65,4 +65,6 @@ public interface INoSqlStorage {
 
   IPipelineElementDescriptionStorageCache getPipelineElementDescriptionStorage();
 
+  IPermissionStorage getPermissionStorage();
+
 }
diff --git a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPermissionStorage.java
similarity index 62%
copy from streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
copy to streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPermissionStorage.java
index c42e0a4..65ac07c 100644
--- a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPermissionStorage.java
@@ -15,22 +15,25 @@
  * limitations under the License.
  *
  */
-package org.apache.streampipes.rest.core.base.impl;
+package org.apache.streampipes.storage.api;
 
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.SecurityContext;
+import org.apache.streampipes.model.client.user.Permission;
 
-public class AbstractAuthGuardedRestResource extends AbstractRestResource {
+import java.util.List;
+import java.util.Set;
 
-  @Context
-  protected SecurityContext securityContext;
+public interface IPermissionStorage {
 
-  protected boolean isAuthenticated() {
-    return this.securityContext.getUserPrincipal() != null;
-  }
+  List<Permission> getAllPermissions();
 
-  protected String getAuthenticatedUsername() {
-    return this.securityContext.getUserPrincipal().getName();
-  }
+  Permission getPermissionById(String permissionId);
+
+  void addPermission(Permission permission);
+
+  void updatePermission(Permission permission);
+
+  void deletePermission(String permissionId);
+
+  Set<String> getObjectPermissions(List<String> sids);
 
 }
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
index d7f996a..be374cf 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
@@ -17,13 +17,12 @@
  */
 package org.apache.streampipes.storage.api;
 
-import org.apache.streampipes.model.client.user.Principal;
-import org.apache.streampipes.model.client.user.ServiceAccount;
-import org.apache.streampipes.model.client.user.UserAccount;
+import org.apache.streampipes.model.client.user.*;
 
 import java.util.List;
 
 public interface IUserStorage {
+
   List<Principal> getAllUsers();
 
   List<UserAccount> getAllUserAccounts();
@@ -47,4 +46,5 @@ public interface IUserStorage {
   void deleteUser(String principalId);
 
   Principal getUserById(String principalId);
+
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
index e47f3fa..dba767e 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
@@ -135,4 +135,9 @@ public enum CouchDbStorageManager implements INoSqlStorage {
   public IPipelineElementDescriptionStorageCache getPipelineElementDescriptionStorage() {
     return new PipelineElementDescriptionStorageImpl();
   }
+
+  @Override
+  public IPermissionStorage getPermissionStorage() {
+    return new PermissionStorageImpl();
+  }
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java
index 5f88886..2e26b30 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java
@@ -24,47 +24,39 @@ import java.util.List;
 import java.util.Optional;
 import java.util.function.Supplier;
 
-public class AbstractDao<T> {
+public class AbstractDao<T> extends CrudDao {
+
+  private static final String ALL_DOCS = "_all_docs";
 
-  protected Supplier<CouchDbClient> couchDbClientSupplier;
   protected Class<T> clazz;
 
   public AbstractDao(Supplier<CouchDbClient> couchDbClientSupplier, Class<T> clazz) {
-    this.couchDbClientSupplier = couchDbClientSupplier;
+    super(couchDbClientSupplier);
     this.clazz = clazz;
   }
 
   public Tuple2<Boolean, String> persist(T objToPersist) {
-    DbCommand<Tuple2<Boolean, String>, T> cmd = new PersistCommand<>(couchDbClientSupplier,
-            objToPersist,
-            clazz);
-    return cmd.execute();
+    return persist(objToPersist, clazz);
   }
 
   public Boolean delete(String key) {
-    DbCommand<Boolean, T> cmd = new DeleteCommand<>(couchDbClientSupplier, key, clazz);
-    return cmd.execute();
+    return delete(key, clazz);
   }
 
   public Boolean update(T objToUpdate) {
-    DbCommand<Boolean, T> cmd = new UpdateCommand<>(couchDbClientSupplier, objToUpdate, clazz);
-    return cmd.execute();
+    return update(objToUpdate, clazz);
   }
 
   public Optional<T> find(String id) {
-    DbCommand<Optional<T>, T> cmd = new FindCommand<>(couchDbClientSupplier, id, clazz);
-    return cmd.execute();
+    return find(id, clazz);
   }
 
   public List<T> findAll() {
-    DbCommand<List<T>, T> cmd = new FindAllCommand<>(couchDbClientSupplier, clazz);
-    return cmd.execute();
+    return findAll(ALL_DOCS, clazz);
   }
 
   public T findWithNullIfEmpty(String id) {
-    DbCommand<Optional<T>, T> cmd = new FindCommand<>(couchDbClientSupplier, id, clazz);
-    return cmd.execute().orElse(null);
+   return findWithNullIfEmpty(id, clazz);
   }
 
-
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/CrudDao.java
similarity index 79%
copy from streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java
copy to streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/CrudDao.java
index 5f88886..05e8c16 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/AbstractDao.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/CrudDao.java
@@ -24,47 +24,43 @@ import java.util.List;
 import java.util.Optional;
 import java.util.function.Supplier;
 
-public class AbstractDao<T> {
+public class CrudDao {
 
   protected Supplier<CouchDbClient> couchDbClientSupplier;
-  protected Class<T> clazz;
 
-  public AbstractDao(Supplier<CouchDbClient> couchDbClientSupplier, Class<T> clazz) {
+  public CrudDao(Supplier<CouchDbClient> couchDbClientSupplier) {
     this.couchDbClientSupplier = couchDbClientSupplier;
-    this.clazz = clazz;
   }
 
-  public Tuple2<Boolean, String> persist(T objToPersist) {
+  public <T> Tuple2<Boolean, String> persist(T objToPersist, Class<T> clazz) {
     DbCommand<Tuple2<Boolean, String>, T> cmd = new PersistCommand<>(couchDbClientSupplier,
             objToPersist,
             clazz);
     return cmd.execute();
   }
 
-  public Boolean delete(String key) {
+  public <T> Boolean delete(String key, Class<T> clazz) {
     DbCommand<Boolean, T> cmd = new DeleteCommand<>(couchDbClientSupplier, key, clazz);
     return cmd.execute();
   }
 
-  public Boolean update(T objToUpdate) {
+  public <T> Boolean update(T objToUpdate, Class<T> clazz) {
     DbCommand<Boolean, T> cmd = new UpdateCommand<>(couchDbClientSupplier, objToUpdate, clazz);
     return cmd.execute();
   }
 
-  public Optional<T> find(String id) {
+  public <T> Optional<T> find(String id, Class<T> clazz) {
     DbCommand<Optional<T>, T> cmd = new FindCommand<>(couchDbClientSupplier, id, clazz);
     return cmd.execute();
   }
 
-  public List<T> findAll() {
-    DbCommand<List<T>, T> cmd = new FindAllCommand<>(couchDbClientSupplier, clazz);
+  public <T> List<T> findAll(String viewName, Class<T> clazz) {
+    DbCommand<List<T>, T> cmd = new FindAllCommand<>(couchDbClientSupplier, clazz, viewName);
     return cmd.execute();
   }
 
-  public T findWithNullIfEmpty(String id) {
+  public <T> T findWithNullIfEmpty(String id, Class<T> clazz) {
     DbCommand<Optional<T>, T> cmd = new FindCommand<>(couchDbClientSupplier, id, clazz);
     return cmd.execute().orElse(null);
   }
-
-
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/CrudViewDao.java
similarity index 71%
copy from streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java
copy to streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/CrudViewDao.java
index b5830ba..5f61635 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/CrudViewDao.java
@@ -19,22 +19,23 @@ package org.apache.streampipes.storage.couchdb.dao;
 
 import org.lightcouch.CouchDbClient;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.function.Supplier;
 
-public class FindAllCommand<T> extends DbCommand<List<T>, T> {
+public class CrudViewDao extends CrudDao {
 
-  public FindAllCommand(Supplier<CouchDbClient> couchDbClient, Class<T> clazz) {
-    super(couchDbClient, clazz);
+  public CrudViewDao(Supplier<CouchDbClient> couchDbClientSupplier) {
+    super(couchDbClientSupplier);
   }
 
-  @Override
-  protected List<T> executeCommand(CouchDbClient couchDbClient) {
-    List<T> allResults = couchDbClient.view("_all_docs")
+  public <T> List<T> findByKey(String viewName,
+                              String key,
+                              Class<T> clazz) {
+    return couchDbClientSupplier
+            .get()
+            .view(viewName)
+            .key(key)
             .includeDocs(true)
             .query(clazz);
-
-    return allResults != null ? allResults : Collections.emptyList();
   }
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java
index b5830ba..186dd64 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/dao/FindAllCommand.java
@@ -25,13 +25,19 @@ import java.util.function.Supplier;
 
 public class FindAllCommand<T> extends DbCommand<List<T>, T> {
 
-  public FindAllCommand(Supplier<CouchDbClient> couchDbClient, Class<T> clazz) {
+  private String viewName;
+
+  public FindAllCommand(Supplier<CouchDbClient> couchDbClient,
+                        Class<T> clazz,
+                        String viewName) {
     super(couchDbClient, clazz);
+    this.viewName = viewName;
   }
 
   @Override
   protected List<T> executeCommand(CouchDbClient couchDbClient) {
-    List<T> allResults = couchDbClient.view("_all_docs")
+    List<T> allResults = couchDbClient
+            .view(viewName)
             .includeDocs(true)
             .query(clazz);
 
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/PermissionStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/PermissionStorageImpl.java
new file mode 100644
index 0000000..b518c4a
--- /dev/null
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/PermissionStorageImpl.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.storage.couchdb.impl;
+
+import org.apache.streampipes.model.client.user.Permission;
+import org.apache.streampipes.storage.api.IPermissionStorage;
+import org.apache.streampipes.storage.couchdb.dao.CrudDao;
+import org.apache.streampipes.storage.couchdb.utils.Utils;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class PermissionStorageImpl extends CrudDao implements IPermissionStorage {
+
+  private String viewName = "users/permissions";
+
+  public PermissionStorageImpl() {
+    super(Utils::getCouchDbUserClient);
+  }
+
+  @Override
+  public List<Permission> getAllPermissions() {
+    return findAll(viewName, Permission.class);
+  }
+
+  @Override
+  public Permission getPermissionById(String permissionId) {
+    return findWithNullIfEmpty(permissionId, Permission.class);
+  }
+
+  @Override
+  public void addPermission(Permission permission) {
+    persist(permission, Permission.class);
+  }
+
+  @Override
+  public void updatePermission(Permission permission) {
+    update(permission, Permission.class);
+  }
+
+  @Override
+  public void deletePermission(String permissionId) {
+    delete(permissionId, Permission.class);
+  }
+
+  public Set<String> getObjectPermissions(List<String> principalSids) {
+    List<Permission> objectInstanceSids = couchDbClientSupplier
+            .get()
+            .view("users/userpermissions")
+            .keys(principalSids)
+            .includeDocs(true)
+            .query(Permission.class);
+
+    return toPermissionSet(objectInstanceSids);
+  }
+
+  private Set<String> toPermissionSet(List<Permission> permissions) {
+    return permissions.stream().map(Permission::getObjectInstanceId).collect(Collectors.toSet());
+  }
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserGroupStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserGroupStorageImpl.java
index ef1db56..992f773 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserGroupStorageImpl.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserGroupStorageImpl.java
@@ -19,40 +19,42 @@ package org.apache.streampipes.storage.couchdb.impl;
 
 import org.apache.streampipes.model.client.user.Group;
 import org.apache.streampipes.storage.api.IUserGroupStorage;
-import org.apache.streampipes.storage.couchdb.dao.AbstractDao;
+import org.apache.streampipes.storage.couchdb.dao.CrudDao;
 import org.apache.streampipes.storage.couchdb.utils.Utils;
 
 import java.util.List;
 
-public class UserGroupStorageImpl extends AbstractDao<Group> implements IUserGroupStorage {
+public class UserGroupStorageImpl extends CrudDao implements IUserGroupStorage {
+
+  private static final String viewName = "users/groups";
 
   public UserGroupStorageImpl() {
-    super(Utils::getCouchDbUserGroupStorage, Group.class);
+    super(Utils::getCouchDbUserClient);
   }
 
   @Override
   public List<Group> getAll() {
-    return findAll();
+    return findAll(viewName, Group.class);
   }
 
   @Override
   public void createElement(Group element) {
-    persist(element);
+    persist(element, Group.class);
   }
 
   @Override
   public Group getElementById(String s) {
-   return findWithNullIfEmpty(s);
+   return findWithNullIfEmpty(s, Group.class);
   }
 
   @Override
   public Group updateElement(Group element) {
-    update(element);
+    update(element, Group.class);
     return getElementById(element.getGroupId());
   }
 
   @Override
   public void deleteElement(Group element) {
-    delete(element.getGroupId());
+    delete(element.getGroupId(), Group.class);
   }
 }
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java
index 5e1b157..a9e8c40 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/UserStorage.java
@@ -22,13 +22,11 @@ import org.apache.streampipes.model.client.user.Principal;
 import org.apache.streampipes.model.client.user.ServiceAccount;
 import org.apache.streampipes.model.client.user.UserAccount;
 import org.apache.streampipes.storage.api.IUserStorage;
-import org.apache.streampipes.storage.couchdb.dao.AbstractDao;
+import org.apache.streampipes.storage.couchdb.dao.CrudViewDao;
 import org.apache.streampipes.storage.couchdb.utils.Utils;
-import org.lightcouch.CouchDbClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -36,22 +34,18 @@ import java.util.stream.Collectors;
  * User Storage.
  * Handles operations on user including user-specified pipelines.
  */
-public class UserStorage extends AbstractDao<Principal> implements IUserStorage {
+public class UserStorage extends CrudViewDao implements IUserStorage {
 
-  Logger LOG = LoggerFactory.getLogger(UserStorage.class);
+  private static final Logger LOG = LoggerFactory.getLogger(UserStorage.class);
+  private static final String viewName = "users/username";
 
   public UserStorage() {
-    super(Utils::getCouchDbUserClient, Principal.class);
+    super(Utils::getCouchDbUserClient);
   }
 
   @Override
   public List<Principal> getAllUsers() {
-    List<Principal> users = couchDbClientSupplier
-            .get()
-            .view("users/username")
-            .includeDocs(true)
-            .query(Principal.class);
-    return new ArrayList<>(users);
+    return findAll(viewName, Principal.class);
   }
 
   @Override
@@ -74,13 +68,7 @@ public class UserStorage extends AbstractDao<Principal> implements IUserStorage
 
   @Override
   public Principal getUser(String username) {
-    // TODO improve
-    CouchDbClient couchDbClient = couchDbClientSupplier.get();
-    List<Principal> users = couchDbClient
-            .view("users/username")
-            .key(username)
-            .includeDocs(true)
-            .query(Principal.class);
+    List<Principal> users = findByKey(viewName, username, Principal.class);
     if (users.size() != 1) {
       LOG.error("None or to many users with matching username");
     }
@@ -99,12 +87,12 @@ public class UserStorage extends AbstractDao<Principal> implements IUserStorage
 
   @Override
   public void storeUser(Principal user) {
-    persist(user);
+    persist(user, Principal.class);
   }
 
   @Override
   public void updateUser(Principal user) {
-    update(user);
+    update(user, Principal.class);
   }
 
   @Override
@@ -122,24 +110,19 @@ public class UserStorage extends AbstractDao<Principal> implements IUserStorage
    */
   @Override
   public boolean checkUser(String username) {
-    List<Principal> users = couchDbClientSupplier
-            .get()
-            .view("users/username")
-            .key(username)
-            .includeDocs(true)
-            .query(Principal.class);
+    List<Principal> users = findByKey(viewName, username, Principal.class);
 
     return users.size() == 1;
   }
 
   @Override
   public void deleteUser(String principalId) {
-    delete(principalId);
+    delete(principalId, Principal.class);
   }
 
   @Override
   public Principal getUserById(String principalId) {
-    return findWithNullIfEmpty(principalId);
+    return findWithNullIfEmpty(principalId, Principal.class);
   }
 
 }
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/PrincipalUserDetails.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/PrincipalUserDetails.java
index 6810f6a..fc4e20c 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/PrincipalUserDetails.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/model/PrincipalUserDetails.java
@@ -19,7 +19,8 @@ package org.apache.streampipes.user.management.model;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.apache.streampipes.model.client.user.Principal;
-import org.apache.streampipes.user.management.util.AuthorityBuilder;
+import org.apache.streampipes.user.management.util.GrantedAuthoritiesBuilder;
+import org.apache.streampipes.user.management.util.GrantedPermissionsBuilder;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 
@@ -31,10 +32,12 @@ public abstract class PrincipalUserDetails<T extends Principal> implements UserD
 
   protected T details;
   private Set<String> allAuthorities;
+  private Set<String> allObjectPermissions;
 
   public PrincipalUserDetails(T details) {
     this.details = details;
-    this.allAuthorities = new AuthorityBuilder(details).buildAllAuthorities();
+    this.allAuthorities = new GrantedAuthoritiesBuilder(details).buildAllAuthorities();
+    this.allObjectPermissions = new GrantedPermissionsBuilder(details).buildAllPermissions();
   }
 
   public T getDetails() {
@@ -76,4 +79,8 @@ public abstract class PrincipalUserDetails<T extends Principal> implements UserD
     return allAuthorities.stream().map(r -> (GrantedAuthority) () -> r).collect(Collectors.toList());
   }
 
+  @JsonIgnore
+  public Set<String> getAllObjectPermissions() {
+    return allObjectPermissions;
+  }
 }
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/AuthorityBuilder.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/GrantedAuthoritiesBuilder.java
similarity index 95%
rename from streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/AuthorityBuilder.java
rename to streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/GrantedAuthoritiesBuilder.java
index 9d9e13c..0eb2d5c 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/AuthorityBuilder.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/GrantedAuthoritiesBuilder.java
@@ -24,12 +24,12 @@ import org.apache.streampipes.storage.management.StorageDispatcher;
 import java.util.HashSet;
 import java.util.Set;
 
-public class AuthorityBuilder {
+public class GrantedAuthoritiesBuilder {
 
   private Set<String> allAuthorities;
   private Principal principal;
 
-  public AuthorityBuilder(Principal principal) {
+  public GrantedAuthoritiesBuilder(Principal principal) {
     this.allAuthorities = new HashSet<>();
     this.principal = principal;
   }
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/GrantedPermissionsBuilder.java
similarity index 53%
copy from streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
copy to streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/GrantedPermissionsBuilder.java
index d7f996a..fa1d673 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IUserStorage.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/GrantedPermissionsBuilder.java
@@ -15,36 +15,36 @@
  * limitations under the License.
  *
  */
-package org.apache.streampipes.storage.api;
+package org.apache.streampipes.user.management.util;
 
 import org.apache.streampipes.model.client.user.Principal;
-import org.apache.streampipes.model.client.user.ServiceAccount;
-import org.apache.streampipes.model.client.user.UserAccount;
+import org.apache.streampipes.storage.management.StorageDispatcher;
 
-import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
 
-public interface IUserStorage {
-  List<Principal> getAllUsers();
+public class GrantedPermissionsBuilder {
 
-  List<UserAccount> getAllUserAccounts();
+  private Principal principal;
 
-  List<ServiceAccount> getAllServiceAccounts();
+  public GrantedPermissionsBuilder(Principal principal) {
+    this.principal = principal;
+  }
 
-  Principal getUser(String username);
+  public Set<String> buildAllPermissions() {
+    Set<String> sids = extractSids();
 
-  UserAccount getUserAccount(String username);
+    return StorageDispatcher
+            .INSTANCE
+            .getNoSqlStore()
+            .getPermissionStorage()
+            .getObjectPermissions(new ArrayList<>(sids));
+  }
 
-  ServiceAccount getServiceAccount(String username);
+  private Set<String> extractSids() {
+    Set<String> groupSids = principal.getGroups();
+    groupSids.add(principal.getPrincipalId());
 
-  void storeUser(Principal user);
-
-  void updateUser(Principal user);
-
-  boolean emailExists(String email);
-
-  boolean checkUser(String username);
-
-  void deleteUser(String principalId);
-
-  Principal getUserById(String principalId);
+    return groupSids;
+  }
 }