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

riemer pushed a commit to branch 
3904-allow-resource-owners-to-manage-permissions
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to 
refs/heads/3904-allow-resource-owners-to-manage-permissions by this push:
     new 35b56b8d4f feat(#3904): Resource owners can manage permissions
35b56b8d4f is described below

commit 35b56b8d4f20f31938f4baf00144d25958702c4e
Author: Dominik Riemer <[email protected]>
AuthorDate: Wed Nov 12 11:31:58 2025 +0100

    feat(#3904): Resource owners can manage permissions
---
 .../apache/streampipes/model/ShortUserInfo.java    |  17 ++-
 .../apache/streampipes/rest/impl/UserResource.java |  32 +++++-
 .../rest/impl/admin/PermissionResource.java        |  36 +++++--
 .../rest/impl/admin/UserGroupResource.java         |   1 -
 .../platform-services/src/lib/apis/user.service.ts |   9 +-
 .../src/lib/model/gen/streampipes-model.ts         |  14 ++-
 .../object-permission-dialog.component.html        |  73 ++++++++-----
 .../object-permission-dialog.component.scss        |   0
 .../object-permission-dialog.component.ts          | 117 ++++++++++++---------
 .../shared-ui/src/lib/shared-ui.module.ts          |  13 ++-
 .../streampipes/shared-ui/src/public-api.ts        |   1 +
 .../endpoint-item/endpoint-item.component.ts       |   7 +-
 .../existing-adapters.component.html               |   1 -
 .../existing-adapters.component.ts                 |   5 +-
 ui/src/app/core-ui/core-ui.module.ts               |   2 -
 .../dashboard-overview-table.component.html        |   1 -
 .../dashboard-overview-table.component.ts          |   3 -
 .../overview/dashboard-overview.component.html     |   1 -
 .../overview/dashboard-overview.component.ts       |   4 -
 .../services/data-explorer-shared.service.ts       |   2 +-
 .../data-explorer-overview-table.component.html    |   6 +-
 .../data-explorer-overview-table.component.ts      |   3 -
 .../overview/data-explorer-overview.component.html |   1 -
 .../overview/data-explorer-overview.component.ts   |   4 -
 .../pipeline-overview.component.html               |   1 -
 .../pipeline-overview.component.ts                 |   4 -
 .../services/pipeline-operations.service.ts        |  17 ++-
 27 files changed, 233 insertions(+), 142 deletions(-)

diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/ShortUserInfo.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/ShortUserInfo.java
index bb2db4d0f5..b7fdfdcedf 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/ShortUserInfo.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/ShortUserInfo.java
@@ -24,13 +24,15 @@ import 
org.apache.streampipes.model.shared.annotation.TsModel;
 public class ShortUserInfo {
 
   private String principalId;
+  private String principalType;
   private String email;
   private String displayName;
 
   public static ShortUserInfo create(String principalId,
                                      String email,
-                                     String displayName) {
-    return new ShortUserInfo(principalId, email, displayName);
+                                     String displayName,
+                                     String principalType) {
+    return new ShortUserInfo(principalId, email, displayName, principalType);
   }
 
   public ShortUserInfo() {
@@ -38,7 +40,8 @@ public class ShortUserInfo {
 
   public ShortUserInfo(String principalId,
                        String email,
-                       String displayName) {
+                       String displayName,
+                       String principalType) {
     this.principalId = principalId;
     this.email = email;
     this.displayName = displayName;
@@ -67,4 +70,12 @@ public class ShortUserInfo {
   public void setDisplayName(String displayName) {
     this.displayName = displayName;
   }
+
+  public String getPrincipalType() {
+    return principalType;
+  }
+
+  public void setPrincipalType(String principalType) {
+    this.principalType = principalType;
+  }
 }
diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
index 462153118d..91ff8f4ed6 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/UserResource.java
@@ -46,11 +46,13 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -59,12 +61,32 @@ import java.util.stream.Collectors;
 public class UserResource extends AbstractAuthGuardedRestResource {
 
   @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
-  public ResponseEntity<List<ShortUserInfo>> listUsers() {
-    var users = getUserStorage()
-        .getAllUserAccounts()
+  public ResponseEntity<List<ShortUserInfo>> listUsers(
+      @RequestParam("includeServiceAccounts") boolean includeServiceAccounts
+  ) {
+    var userStorage = getUserStorage();
+
+    var users = userStorage.getAllUserAccounts()
         .stream()
-        .map(u -> ShortUserInfo.create(u.getPrincipalId(), u.getUsername(), 
u.getFullName()))
-        .collect(Collectors.toList());
+        .map(u -> ShortUserInfo.create(
+            u.getPrincipalId(),
+            u.getUsername(),
+            u.getFullName(),
+            u.getPrincipalType().name())
+        )
+        .collect(Collectors.toCollection(ArrayList::new));
+
+    if (includeServiceAccounts) {
+      var services = userStorage.getAllServiceAccounts()
+          .stream()
+          .map(s -> ShortUserInfo.create(
+              s.getPrincipalId(),
+              s.getUsername(),
+              s.getUsername(),
+              s.getPrincipalType().name()))
+          .toList();
+      users.addAll(services);
+    }
 
     return ok(users);
   }
diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/PermissionResource.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/PermissionResource.java
index dcd9beadfa..91d1b1e72f 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/PermissionResource.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/PermissionResource.java
@@ -19,37 +19,61 @@ package org.apache.streampipes.rest.impl.admin;
 
 import org.apache.streampipes.model.client.user.Permission;
 import 
org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
-import org.apache.streampipes.rest.security.AuthConstants;
 
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.server.ResponseStatusException;
 
 import java.util.List;
+import java.util.Objects;
 
 @RestController
 @RequestMapping("/api/v2/admin/permissions")
 public class PermissionResource extends AbstractAuthGuardedRestResource {
 
   @GetMapping(path = "objects/{objectInstanceId}", produces = 
MediaType.APPLICATION_JSON_VALUE)
-  @PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
   public List<Permission> 
getPermissionForObject(@PathVariable("objectInstanceId") String 
objectInstanceId) {
-    return 
getSpResourceManager().managePermissions().findForObjectId(objectInstanceId);
+    var principalId = getAuthenticatedUserSid();
+    var permission = 
getSpResourceManager().managePermissions().findForObjectId(objectInstanceId);
+    if (isAdminOrOwner(principalId, permission)) {
+      return permission;
+    } else {
+      throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Only admins or 
owners can receive permissions");
+    }
   }
 
   @PutMapping(path = "{permissionId}", consumes = 
MediaType.APPLICATION_JSON_VALUE)
-  @PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
   public void updatePermission(@PathVariable("permissionId") String 
permissionId,
                                @RequestBody Permission permission) {
-    if (permissionId.equals(permission.getPermissionId())) {
+    var principalId = getAuthenticatedUserSid();
+    var existingPermission = 
getSpResourceManager().managePermissions().findForObjectId(permission.getObjectInstanceId());
+    if (
+        permissionId.equals(permission.getPermissionId())
+            && isObjectInstanceCorrect(existingPermission, permission)
+            && isAdminOrOwner(principalId, existingPermission)) {
       getSpResourceManager().managePermissions().update(permission);
+    } else {
+      throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Only admins or 
owners can update permissions");
     }
   }
 
+  private boolean isAdminOrOwner(String principalId, List<Permission> 
permission) {
+    if (Objects.isNull(permission) || permission.isEmpty()) {
+      return false;
+    }
+    return isAdminOrHasAnyAuthority()
+        || permission.stream().anyMatch(p -> 
p.getOwnerSid().equals(principalId));
+  }
 
+  private boolean isObjectInstanceCorrect(List<Permission> existingPermission, 
Permission permission) {
+    return existingPermission
+        .stream()
+        .anyMatch(p -> 
p.getPermissionId().equals(permission.getPermissionId()));
+  }
 }
diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/UserGroupResource.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/UserGroupResource.java
index 3ceab35c1e..63ec62f810 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/UserGroupResource.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/UserGroupResource.java
@@ -44,7 +44,6 @@ import java.util.List;
 public class UserGroupResource extends AbstractAuthGuardedRestResource {
 
   @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
-  @PreAuthorize(AuthConstants.IS_ADMIN_ROLE)
   public ResponseEntity<List<Group>> getAllUserGroups() {
     return ok(getUserGroupStorage().findAll());
   }
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/apis/user.service.ts 
b/ui/projects/streampipes/platform-services/src/lib/apis/user.service.ts
index a953c2dba1..2bc7e86bda 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/user.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/user.service.ts
@@ -35,8 +35,13 @@ export class UserService {
     private http = inject(HttpClient);
     private platformServicesCommons = inject(PlatformServicesCommons);
 
-    public listUsers(): Observable<ShortUserInfo[]> {
-        return this.http.get(this.usersPath).pipe(
+    public listUsers(
+        includeServiceAccounts = false,
+    ): Observable<ShortUserInfo[]> {
+        const params = {
+            includeServiceAccounts: includeServiceAccounts.toString(),
+        };
+        return this.http.get(this.usersPath, { params }).pipe(
             map(response => {
                 return (response as any[]).map(p => ShortUserInfo.fromData(p));
             }),
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 6f9793ff2f..498a22c86c 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -20,7 +20,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2025-10-23 
20:03:42.
+// Generated using typescript-generator version 3.2.1263 on 2025-11-12 
10:22:54.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -2462,6 +2462,7 @@ export class MatchingStaticProperty extends 
StaticProperty {
 export class MessageCounter {
     counter: number;
     lastTimestamp: number;
+    size: number;
 
     static fromData(
         data: MessageCounter,
@@ -2473,6 +2474,7 @@ export class MessageCounter {
         const instance = target || new MessageCounter();
         instance.counter = data.counter;
         instance.lastTimestamp = data.lastTimestamp;
+        instance.size = data.size;
         return instance;
     }
 }
@@ -2676,6 +2678,8 @@ export class Pipeline implements Storable {
     description: string;
     elementId: string;
     healthStatus: PipelineHealthStatus;
+    labels: string[];
+    lastMigratedAt: number;
     name: string;
     pipelineNotifications: string[];
     publicElement: boolean;
@@ -2702,6 +2706,8 @@ export class Pipeline implements Storable {
         instance.description = data.description;
         instance.elementId = data.elementId;
         instance.healthStatus = data.healthStatus;
+        instance.labels = __getCopyArrayFn(__identity<string>())(data.labels);
+        instance.lastMigratedAt = data.lastMigratedAt;
         instance.name = data.name;
         instance.pipelineNotifications = 
__getCopyArrayFn(__identity<string>())(
             data.pipelineNotifications,
@@ -3614,6 +3620,7 @@ export class ShortUserInfo {
     displayName: string;
     email: string;
     principalId: string;
+    principalType: string;
 
     static fromData(
         data: ShortUserInfo,
@@ -3626,6 +3633,7 @@ export class ShortUserInfo {
         instance.displayName = data.displayName;
         instance.email = data.email;
         instance.principalId = data.principalId;
+        instance.principalType = data.principalType;
         return instance;
     }
 }
@@ -3844,6 +3852,7 @@ export class SpServiceRegistration implements Storable {
     firstTimeSeenUnhealthy: number;
     healthCheckPath: string;
     host: string;
+    labels: string[];
     port: number;
     providedExtensions: ExtensionItemDescription[];
     rev: string;
@@ -3854,6 +3863,7 @@ export class SpServiceRegistration implements Storable {
     svcId: string;
     svcType: string;
     tags: SpServiceTag[];
+    weight: number;
 
     static fromData(
         data: SpServiceRegistration,
@@ -3867,6 +3877,7 @@ export class SpServiceRegistration implements Storable {
         instance.firstTimeSeenUnhealthy = data.firstTimeSeenUnhealthy;
         instance.healthCheckPath = data.healthCheckPath;
         instance.host = data.host;
+        instance.labels = __getCopyArrayFn(__identity<string>())(data.labels);
         instance.port = data.port;
         instance.providedExtensions = __getCopyArrayFn(
             ExtensionItemDescription.fromData,
@@ -3879,6 +3890,7 @@ export class SpServiceRegistration implements Storable {
         instance.svcId = data.svcId;
         instance.svcType = data.svcType;
         instance.tags = __getCopyArrayFn(SpServiceTag.fromData)(data.tags);
+        instance.weight = data.weight;
         return instance;
     }
 }
diff --git 
a/ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
similarity index 85%
rename from 
ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.html
rename to 
ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
index ff268e0186..6e1cdf3c61 100644
--- 
a/ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
@@ -17,7 +17,14 @@
   -->
 
 <div class="sp-dialog-container">
-    @if (usersLoaded) {
+    @if (loading) {
+        <div class="sp-dialog-content">
+            <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
+                <mat-progress-spinner [diameter]="25"></mat-progress-spinner>
+                <h5>{{ 'Loading' | translate }}</h5>
+            </div>
+        </div>
+    } @else if (!permissionDenied) {
         <div class="sp-dialog-content">
             <div fxFlex="100" fxLayout="column" class="p-15">
                 <h4>{{ headerTitle }}</h4>
@@ -32,8 +39,8 @@
                                 <mat-option
                                     *ngFor="let user of allUsers"
                                     [value]="user.principalId"
-                                    >{{ user.username }}</mat-option
-                                >
+                                    >{{ user.email }}
+                                </mat-option>
                             </mat-select>
                         </mat-form-field>
                         <mat-checkbox
@@ -51,9 +58,9 @@
                                 'Users' | translate
                             }}</span>
                             <mat-form-field color="accent">
-                                <mat-label>{{
-                                    'Authorized Users' | translate
-                                }}</mat-label>
+                                <mat-label
+                                    >{{ 'Authorized Users' | translate }}
+                                </mat-label>
                                 <mat-chip-grid
                                     #chipList
                                     [attr.aria-label]="
@@ -68,7 +75,7 @@
                                         removable="true"
                                         (removed)="removeUser(user)"
                                     >
-                                        {{ user.username }}
+                                        {{ user.email }}
                                         <button matChipRemove>
                                             <mat-icon>cancel</mat-icon>
                                         </button>
@@ -93,14 +100,14 @@
                                 >
                                     <mat-option
                                         *ngFor="
-                                            let user of filteredUsers | async
+                                            let user of filteredUsers$ | async
                                         "
                                         [value]="user"
                                         [attr.data-cy]="
-                                            'user-option-' + user.username
+                                            'user-option-' + user.email
                                         "
                                     >
-                                        {{ user.username }}
+                                        {{ user.email }}
                                     </mat-option>
                                 </mat-autocomplete>
                             </mat-form-field>
@@ -112,9 +119,9 @@
                                 'Groups' | translate
                             }}</span>
                             <mat-form-field color="accent">
-                                <mat-label data-cy="authorized-groups-label">{{
-                                    'Authorized Groups' | translate
-                                }}</mat-label>
+                                <mat-label data-cy="authorized-groups-label"
+                                    >{{ 'Authorized Groups' | translate }}
+                                </mat-label>
                                 <mat-chip-grid
                                     #chipList
                                     [attr.aria-label]="
@@ -155,7 +162,7 @@
                                 >
                                     <mat-option
                                         *ngFor="
-                                            let group of filteredGroups | async
+                                            let group of filteredGroups$ | 
async
                                         "
                                         [value]="group"
                                     >
@@ -211,22 +218,36 @@
                 </form>
             </div>
         </div>
+    } @else {
+        <div class="sp-dialog-content">
+            <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
+                <mat-icon>block</mat-icon>
+                <h5>
+                    {{
+                        'Only admins and owners can manage permissions for 
this resource.'
+                            | translate
+                    }}
+                </h5>
+            </div>
+        </div>
     }
     <mat-divider></mat-divider>
     <div class="sp-dialog-actions">
         <div fxLayout="row">
-            <button
-                mat-button
-                mat-flat-button
-                color="accent"
-                (click)="save()"
-                style="margin-right: 10px"
-                [disabled]="parentForm.invalid"
-                data-cy="sp-manage-permissions-save"
-            >
-                <i class="material-icons">save</i
-                ><span>&nbsp;{{ 'Save' | translate }}</span>
-            </button>
+            @if (!loading && !permissionDenied) {
+                <button
+                    mat-button
+                    mat-flat-button
+                    color="accent"
+                    (click)="save()"
+                    style="margin-right: 10px"
+                    [disabled]="parentForm.invalid"
+                    data-cy="sp-manage-permissions-save"
+                >
+                    <i class="material-icons">save</i
+                    ><span>&nbsp;{{ 'Save' | translate }}</span>
+                </button>
+            }
             <button
                 mat-button
                 mat-flat-button
diff --git 
a/ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.scss
 
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.scss
similarity index 100%
rename from 
ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.scss
rename to 
ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.scss
diff --git 
a/ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.ts
 
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.ts
similarity index 74%
rename from 
ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.ts
rename to 
ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.ts
index 2dbda6e745..aa193aaee6 100644
--- 
a/ui/src/app/core-ui/object-permission-dialog/object-permission-dialog.component.ts
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.ts
@@ -17,8 +17,15 @@
  */
 
 import { COMMA, ENTER } from '@angular/cdk/keycodes';
-import { Component, ElementRef, Input, OnInit, ViewChild } from 
'@angular/core';
-import { DialogRef } from '@streampipes/shared-ui';
+import {
+    Component,
+    ElementRef,
+    inject,
+    Input,
+    OnInit,
+    ViewChild,
+} from '@angular/core';
+import { DialogRef } from '../base-dialog/dialog-ref';
 import {
     UntypedFormBuilder,
     UntypedFormControl,
@@ -30,13 +37,13 @@ import {
     Permission,
     PermissionEntry,
     PermissionsService,
-    ServiceAccount,
-    UserAccount,
-    UserAdminService,
+    PrincipalType,
+    ShortUserInfo,
     UserGroupService,
+    UserService,
 } from '@streampipes/platform-services';
 import { MatChipInputEvent } from '@angular/material/chips';
-import { Observable, zip } from 'rxjs';
+import { combineLatest, Observable, shareReplay, zip } from 'rxjs';
 import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
 import { map, startWith } from 'rxjs/operators';
 
@@ -65,33 +72,29 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
 
     permission: Permission;
 
-    owner: UserAccount | ServiceAccount;
-    grantedUserAuthorities: (UserAccount | ServiceAccount)[];
-    grantedGroupAuthorities: Group[];
+    owner: ShortUserInfo;
+    grantedUserAuthorities: ShortUserInfo[] = [];
+    grantedGroupAuthorities: Group[] = [];
 
-    allUsers: (UserAccount | ServiceAccount)[];
+    allUsers: ShortUserInfo[];
     allGroups: Group[];
 
-    filteredUsers: Observable<(UserAccount | ServiceAccount)[]>;
-    filteredGroups: Observable<Group[]>;
+    filteredUsers$: Observable<ShortUserInfo[]>;
+    filteredGroups$: Observable<Group[]>;
 
-    usersLoaded = false;
+    loading = true;
+    permissionDenied = false;
 
     @ViewChild('userInput') userInput: ElementRef<HTMLInputElement>;
     @ViewChild('groupInput') groupInput: ElementRef<HTMLInputElement>;
     userCtrl = new UntypedFormControl();
     groupCtrl = new UntypedFormControl();
 
-    constructor(
-        private fb: UntypedFormBuilder,
-        private dialogRef: DialogRef<ObjectPermissionDialogComponent>,
-        private permissionsService: PermissionsService,
-        private userAdminService: UserAdminService,
-        private groupService: UserGroupService,
-    ) {
-        this.grantedGroupAuthorities = [];
-        this.grantedUserAuthorities = [];
-    }
+    private fb = inject(UntypedFormBuilder);
+    private dialogRef = inject(DialogRef<ObjectPermissionDialogComponent>);
+    private permissionsService = inject(PermissionsService);
+    private userService = inject(UserService);
+    private groupService = inject(UserGroupService);
 
     ngOnInit(): void {
         this.loadUsersAndGroups();
@@ -99,20 +102,26 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
     }
 
     loadUsersAndGroups() {
+        this.loading = true;
         zip(
-            this.userAdminService.getAllUserAccounts(),
-            this.userAdminService.getAllServiceAccounts(),
+            this.userService.listUsers(true),
             this.groupService.getAllUserGroups(),
             this.permissionsService.getPermissionsForObject(
                 this.objectInstanceId,
             ),
-        ).subscribe(results => {
-            this.allUsers = results[0];
-            this.allUsers.concat(results[1]);
-            this.allGroups = results[2];
-            this.processPermissions(results[3]);
-            this.usersLoaded = true;
-        });
+        ).subscribe(
+            results => {
+                this.allUsers = results[0];
+                this.allGroups = results[1];
+                this.processPermissions(results[2]);
+                this.permissionDenied = false;
+                this.loading = false;
+            },
+            error => {
+                this.permissionDenied = true;
+                this.loading = false;
+            },
+        );
     }
 
     processPermissions(permissions: Permission[]) {
@@ -138,18 +147,24 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
                     new UntypedFormControl(this.permission.readAnonymous),
                 );
             }
-            this.filteredUsers = this.userCtrl.valueChanges.pipe(
-                startWith(null),
-                map((username: string | null) => {
-                    return username
-                        ? this._filter(username)
-                        : this.allUsers
-                              .filter(u => !this.isOwnerOrAdded(u))
-                              .slice();
+            this.filteredUsers$ = combineLatest([
+                this.userCtrl.valueChanges.pipe(startWith(null)),
+                this.parentForm
+                    .get('owner')!
+                    .valueChanges.pipe(
+                        startWith(this.parentForm.get('owner')!.value),
+                    ),
+            ]).pipe(
+                map(([username]) => {
+                    const base = this.allUsers.filter(
+                        u => !this.isOwnerOrAdded(u),
+                    );
+                    return username ? this._filter(username) : base.slice();
                 }),
+                shareReplay({ bufferSize: 1, refCount: true }),
             );
 
-            this.filteredGroups = this.groupCtrl.valueChanges.pipe(
+            this.filteredGroups$ = this.groupCtrl.valueChanges.pipe(
                 startWith(null),
                 map((groupName: string | null) => {
                     return groupName
@@ -188,7 +203,10 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
 
         this.permission.grantedAuthorities = this.grantedUserAuthorities
             .map(u => {
-                return { principalType: u.principalType, sid: u.principalId };
+                return {
+                    principalType: u.principalType as PrincipalType,
+                    sid: u.principalId,
+                };
             })
             .concat(
                 this.grantedGroupAuthorities.map(g => {
@@ -206,7 +224,7 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
         this.dialogRef.close(refresh);
     }
 
-    removeUser(user: UserAccount | ServiceAccount) {
+    removeUser(user: ShortUserInfo) {
         const currentIndex = this.grantedUserAuthorities.findIndex(
             u => u.principalId === user.principalId,
         );
@@ -256,15 +274,14 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
         this.grantedGroupAuthorities.push(group);
     }
 
-    private _filter(value: any): (UserAccount | ServiceAccount)[] {
-        const isUserAccount =
-            value instanceof UserAccount || value instanceof ServiceAccount;
+    private _filter(value: any): ShortUserInfo[] {
+        const isUserAccount = value instanceof ShortUserInfo;
         const filterValue = isUserAccount
-            ? value.username.toLowerCase()
+            ? value.email.toLowerCase()
             : value.toLowerCase();
         return this.allUsers.filter(u => {
             return (
-                u.username.toLowerCase().startsWith(filterValue) &&
+                u.email.toLowerCase().startsWith(filterValue) &&
                 !this.isOwnerOrAdded(u)
             );
         });
@@ -283,9 +300,9 @@ export class ObjectPermissionDialogComponent implements 
OnInit {
         });
     }
 
-    private isOwnerOrAdded(user: UserAccount | ServiceAccount): boolean {
+    private isOwnerOrAdded(user: ShortUserInfo): boolean {
         return (
-            this.permission.ownerSid === user.principalId ||
+            this.parentForm.get('owner').getRawValue() === user.principalId ||
             this.grantedUserAuthorities.find(
                 authority => authority.principalId === user.principalId,
             ) !== undefined
diff --git a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts 
b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
index e82ad6620b..68b7463f2d 100644
--- a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
@@ -69,7 +69,7 @@ import { SidebarResizeComponent } from 
'./components/sidebar-resize/sidebar-resi
 import { MatSelectModule } from '@angular/material/select';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatMenuModule } from '@angular/material/menu';
-import { FormsModule } from '@angular/forms';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { MatTreeModule } from '@angular/material/tree';
 import { DataDownloadDialogComponent } from 
'./dialog/data-download-dialog/data-download-dialog.component';
 import { MatStepperModule } from '@angular/material/stepper';
@@ -101,6 +101,10 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
 import { SpTableActionsDirective } from 
'./components/sp-table/sp-table-actions.directive';
 import { AssetLinkConfigurationComponent } from 
'./components/asset-link-configuration/asset-link-configuration.component';
 import { AssetBrowserFilterAssetModelComponent } from 
'./components/asset-browser/asset-browser-toolbar/asset-browser-filter/asset-browser-filter-asset-model/asset-browser-filter-asset-model.component';
+import { ObjectPermissionDialogComponent } from 
'./dialog/object-permission-dialog/object-permission-dialog.component';
+import { MatChipsModule } from '@angular/material/chips';
+import { MatAutocompleteModule } from '@angular/material/autocomplete';
+import { CdkCopyToClipboard } from '@angular/cdk/clipboard';
 
 @NgModule({
     declarations: [
@@ -155,6 +159,7 @@ import { AssetBrowserFilterAssetModelComponent } from 
'./components/asset-browse
         SpTableActionsDirective,
         AssetLinkConfigurationComponent,
         AssetBrowserFilterAssetModelComponent,
+        ObjectPermissionDialogComponent,
     ],
     imports: [
         CommonModule,
@@ -186,6 +191,11 @@ import { AssetBrowserFilterAssetModelComponent } from 
'./components/asset-browse
         TranslateModule.forChild({}),
         DragDropModule,
         MarkdownModule.forRoot(),
+        MatChipsModule,
+        FormsModule,
+        ReactiveFormsModule,
+        MatAutocompleteModule,
+        CdkCopyToClipboard,
     ],
     providers: [
         DefaultMatCalendarRangeStrategy,
@@ -225,6 +235,7 @@ import { AssetBrowserFilterAssetModelComponent } from 
'./components/asset-browse
         InputSchemaPanelComponent,
         SidebarResizeComponent,
         SpTableActionsDirective,
+        ObjectPermissionDialogComponent,
     ],
 })
 export class SharedUiModule {}
diff --git a/ui/projects/streampipes/shared-ui/src/public-api.ts 
b/ui/projects/streampipes/shared-ui/src/public-api.ts
index 4fab61f8d4..5d89e09203 100644
--- a/ui/projects/streampipes/shared-ui/src/public-api.ts
+++ b/ui/projects/streampipes/shared-ui/src/public-api.ts
@@ -27,6 +27,7 @@ export * from 
'./lib/dialog/confirm-dialog/confirm-dialog.component';
 export * from './lib/dialog/panel-dialog/panel-dialog.component';
 export * from './lib/dialog/standard-dialog/standard-dialog.component';
 export * from 
'./lib/dialog/pipeline-element-help/pipeline-element-help.component';
+export * from 
'./lib/dialog/object-permission-dialog/object-permission-dialog.component';
 
 export * from './lib/components/asset-browser/asset-browser.component';
 export * from 
'./lib/components/asset-browser/asset-browser-toolbar/asset-browser-toolbar.component';
diff --git 
a/ui/src/app/configuration/extensions-installation/endpoint-item/endpoint-item.component.ts
 
b/ui/src/app/configuration/extensions-installation/endpoint-item/endpoint-item.component.ts
index e76baac7e0..2fe23803e8 100644
--- 
a/ui/src/app/configuration/extensions-installation/endpoint-item/endpoint-item.component.ts
+++ 
b/ui/src/app/configuration/extensions-installation/endpoint-item/endpoint-item.component.ts
@@ -25,8 +25,11 @@ import {
     ExtensionItemInstallationRequest,
 } from '@streampipes/platform-services';
 import { AppConstants } from '../../../services/app.constants';
-import { ObjectPermissionDialogComponent } from 
'../../../core-ui/object-permission-dialog/object-permission-dialog.component';
-import { DialogService, PanelType } from '@streampipes/shared-ui';
+import {
+    DialogService,
+    ObjectPermissionDialogComponent,
+    PanelType,
+} from '@streampipes/shared-ui';
 import { ExtensionsInstallationService } from 
'../extensions-installation.service';
 import { TranslateService } from '@ngx-translate/core';
 
diff --git 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
index 9ca03d6a26..94560c96f4 100644
--- 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
+++ 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
@@ -266,7 +266,6 @@
                     <button
                         mat-menu-item
                         data-cy="open-manage-permissions"
-                        *ngIf="isAdmin"
                         (click)="showPermissionsDialog(element)"
                     >
                         <mat-icon>share</mat-icon>
diff --git 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
index 6005432dfe..9a62e54ab8 100644
--- 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
+++ 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
@@ -30,6 +30,7 @@ import {
     CurrentUserService,
     DialogRef,
     DialogService,
+    ObjectPermissionDialogComponent,
     PanelType,
     SpAssetBrowserService,
     SpBreadcrumbService,
@@ -38,8 +39,6 @@ import {
 import { DeleteAdapterDialogComponent } from 
'../../dialog/delete-adapter-dialog/delete-adapter-dialog.component';
 import { AllAdapterActionsComponent } from 
'../../dialog/start-all-adapters/all-adapter-actions-dialog.component';
 import { MatSort } from '@angular/material/sort';
-import { ObjectPermissionDialogComponent } from 
'../../../core-ui/object-permission-dialog/object-permission-dialog.component';
-import { UserRole } from '../../../_enums/user-role.enum';
 import { Router } from '@angular/router';
 import { AdapterFilterSettingsModel } from 
'../../model/adapter-filter-settings.model';
 import { AdapterFilterPipe } from '../../filter/adapter-filter.pipe';
@@ -77,7 +76,6 @@ export class ExistingAdaptersComponent implements OnInit, 
OnDestroy {
 
     dataSource: MatTableDataSource<AdapterDescription> =
         new MatTableDataSource();
-    isAdmin = false;
 
     adapterMetrics: Record<string, SpMetricsEntry> = {};
     tutorialActive = false;
@@ -114,7 +112,6 @@ export class ExistingAdaptersComponent implements OnInit, 
OnDestroy {
             this.breadcrumbService.getRootLink(SpConnectRoutes.BASE),
         );
         this.user$ = this.currentUserService.user$.subscribe(user => {
-            this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
             this.getAdaptersRunning();
         });
         this.tutorial$ = this.shepherdService.tutorialActive$.subscribe(
diff --git a/ui/src/app/core-ui/core-ui.module.ts 
b/ui/src/app/core-ui/core-ui.module.ts
index 9d2886d92d..1bec1335d0 100644
--- a/ui/src/app/core-ui/core-ui.module.ts
+++ b/ui/src/app/core-ui/core-ui.module.ts
@@ -55,7 +55,6 @@ import { MatAutocompleteModule } from 
'@angular/material/autocomplete';
 import { ErrorHintComponent } from './error-hint/error-hint.component';
 import { AddToCollectionComponent } from 
'./static-properties/static-collection/add-to-collection/add-to-collection.component';
 import { PipelineStartedStatusComponent } from 
'./pipeline/pipeline-started-status/pipeline-started-status.component';
-import { ObjectPermissionDialogComponent } from 
'./object-permission-dialog/object-permission-dialog.component';
 import { StaticSlideToggleComponent } from 
'./static-properties/static-slide-toggle/static-slide-toggle.component';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
 import { StaticRuntimeResolvableTreeInputComponent } from 
'./static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component';
@@ -164,7 +163,6 @@ import { TextFieldModule } from '@angular/cdk/text-field';
     declarations: [
         ConfigurationCodePanelComponent,
         DisplayRecommendedPipe,
-        ObjectPermissionDialogComponent,
         PipelineElementTemplateConfigComponent,
         PipelineElementTemplateConfigItemComponent,
         PipelineElementTemplatePipe,
diff --git 
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
 
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
index 072d159701..0d339c3c21 100644
--- 
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
+++ 
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
@@ -123,7 +123,6 @@
                 }
                 <button
                     mat-menu-item
-                    *ngIf="isAdmin"
                     [attr.data-cy]="
                         'manage-dashboard-permissions-' + element.name
                     "
diff --git 
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
 
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
index 5b7b7b231e..713128e691 100644
--- 
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
+++ 
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
@@ -47,9 +47,6 @@ export class DashboardOverviewTableComponent implements 
OnInit, OnDestroy {
     @Input()
     hasDashboardWritePrivileges: boolean;
 
-    @Input()
-    admin: boolean;
-
     dataSource = new MatTableDataSource<Dashboard>();
     displayedColumns: string[] = [
         'name',
diff --git 
a/ui/src/app/dashboard/components/overview/dashboard-overview.component.html 
b/ui/src/app/dashboard/components/overview/dashboard-overview.component.html
index 92776f0d6a..a52a9c7721 100644
--- a/ui/src/app/dashboard/components/overview/dashboard-overview.component.html
+++ b/ui/src/app/dashboard/components/overview/dashboard-overview.component.html
@@ -39,7 +39,6 @@
     </div>
     <div fxFlex="100" fxLayout="column">
         <sp-dashboard-overview-table
-            [admin]="isAdmin"
             [hasDashboardWritePrivileges]="hasDashboardWritePrivileges"
         ></sp-dashboard-overview-table>
     </div>
diff --git 
a/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts 
b/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts
index a8a4413369..ed4f961172 100644
--- a/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts
+++ b/ui/src/app/dashboard/components/overview/dashboard-overview.component.ts
@@ -22,7 +22,6 @@ import {
     CurrentUserService,
     SpBreadcrumbService,
 } from '@streampipes/shared-ui';
-import { UserRole } from '../../../_enums/user-role.enum';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import { SpDashboardRoutes } from '../../dashboard.routes';
@@ -40,8 +39,6 @@ import { Subscription } from 'rxjs';
 })
 export class DashboardOverviewComponent implements OnInit, OnDestroy {
     displayedColumns: string[] = ['name', 'actions'];
-
-    isAdmin = false;
     hasDashboardWritePrivileges = false;
 
     @ViewChild(DashboardOverviewTableComponent)
@@ -61,7 +58,6 @@ export class DashboardOverviewComponent implements OnInit, 
OnDestroy {
             this.breadcrumbService.getRootLink(SpDashboardRoutes.BASE),
         );
         this.user$ = this.currentUserService.user$.subscribe(user => {
-            this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
             this.hasDashboardWritePrivileges = this.authService.hasRole(
                 UserPrivilege.PRIVILEGE_WRITE_DASHBOARD,
             );
diff --git 
a/ui/src/app/data-explorer-shared/services/data-explorer-shared.service.ts 
b/ui/src/app/data-explorer-shared/services/data-explorer-shared.service.ts
index 12e555ebb4..da1c5215cd 100644
--- a/ui/src/app/data-explorer-shared/services/data-explorer-shared.service.ts
+++ b/ui/src/app/data-explorer-shared/services/data-explorer-shared.service.ts
@@ -27,9 +27,9 @@ import {
 import {
     DataDownloadDialogComponent,
     DialogService,
+    ObjectPermissionDialogComponent,
     PanelType,
 } from '@streampipes/shared-ui';
-import { ObjectPermissionDialogComponent } from 
'../../core-ui/object-permission-dialog/object-permission-dialog.component';
 import { TranslateService } from '@ngx-translate/core';
 import { ObservableGenerator } from '../models/dataview-dashboard.model';
 
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
index 49dfcc98ab..a6e163b5c5 100644
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
@@ -90,11 +90,7 @@
                     <mat-icon>edit</mat-icon>
                     <span>{{ 'Edit chart' | translate }}</span>
                 </button>
-                <button
-                    mat-menu-item
-                    *ngIf="isAdmin"
-                    (click)="showPermissionsDialog(element)"
-                >
+                <button mat-menu-item (click)="showPermissionsDialog(element)">
                     <mat-icon>share</mat-icon>
                     <span>{{ 'Manage permissions' | translate }}</span>
                 </button>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts
index d8f6a2d3d3..e28ddf8c81 100644
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts
@@ -43,9 +43,6 @@ export class SpDataExplorerDataViewOverviewComponent 
implements OnInit {
     @Input()
     hasDataExplorerWritePrivileges: boolean;
 
-    @Input()
-    admin: boolean;
-
     dataSource = new MatTableDataSource<DataExplorerWidgetModel>();
     displayedColumns: string[] = [
         'name',
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
index df3ae65c13..bbc7f1feec 100644
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
@@ -39,7 +39,6 @@
     </div>
     <div fxFlex="100" fxLayout="column">
         <sp-data-explorer-overview-table
-            [admin]="isAdmin"
             [hasDataExplorerWritePrivileges]="hasDataExplorerWritePrivileges"
         ></sp-data-explorer-overview-table>
     </div>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
index 374a70d231..915bfcfd82 100644
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
@@ -26,7 +26,6 @@ import { SpDataExplorerRoutes } from 
'../../data-explorer.routes';
 import { DataExplorerRoutingService } from 
'../../../data-explorer-shared/services/data-explorer-routing.service';
 import { SpDataExplorerDataViewOverviewComponent } from 
'./data-explorer-overview-table/data-explorer-overview-table.component';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
-import { UserRole } from '../../../_enums/user-role.enum';
 import { Subscription } from 'rxjs';
 
 @Component({
@@ -40,8 +39,6 @@ export class DataExplorerOverviewComponent implements OnInit, 
OnDestroy {
     chartsOverview: SpDataExplorerDataViewOverviewComponent;
 
     auth$: Subscription;
-
-    isAdmin = false;
     hasDataExplorerWritePrivileges = false;
 
     private breadcrumbService = inject(SpBreadcrumbService);
@@ -57,7 +54,6 @@ export class DataExplorerOverviewComponent implements OnInit, 
OnDestroy {
             this.hasDataExplorerWritePrivileges = this.authService.hasRole(
                 UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW,
             );
-            this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
         });
     }
 
diff --git 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
index 5c71069499..6ada52ff09 100644
--- 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
+++ 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
@@ -190,7 +190,6 @@
         </button>
         <button
             mat-menu-item
-            *ngIf="isAdmin"
             (click)="
                 pipelineOperationsService.showPermissionsDialog(
                     element,
diff --git 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
index aadc7548eb..c1731c7e63 100644
--- 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
+++ 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
@@ -30,7 +30,6 @@ import { PipelineOperationsService } from 
'../../services/pipeline-operations.se
 import { MatTableDataSource } from '@angular/material/table';
 import { MatSort } from '@angular/material/sort';
 import { AuthService } from '../../../services/auth.service';
-import { UserRole } from '../../../_enums/user-role.enum';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import { CurrentUserService } from '@streampipes/shared-ui';
 import { Subscription } from 'rxjs';
@@ -61,8 +60,6 @@ export class PipelineOverviewComponent implements OnInit, 
OnDestroy {
 
     starting: any;
     stopping: any;
-
-    isAdmin = false;
     hasPipelineWritePrivileges = false;
 
     userSub: Subscription;
@@ -78,7 +75,6 @@ export class PipelineOverviewComponent implements OnInit, 
OnDestroy {
 
     ngOnInit() {
         this.userSub = this.currentUserService.user$.subscribe(user => {
-            this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
             this.hasPipelineWritePrivileges = this.authService.hasRole(
                 UserPrivilege.PRIVILEGE_WRITE_PIPELINE,
             );
diff --git a/ui/src/app/pipelines/services/pipeline-operations.service.ts 
b/ui/src/app/pipelines/services/pipeline-operations.service.ts
index d6f39030f5..19103f1cc8 100644
--- a/ui/src/app/pipelines/services/pipeline-operations.service.ts
+++ b/ui/src/app/pipelines/services/pipeline-operations.service.ts
@@ -16,16 +16,19 @@
  *
  */
 
-import { ShepherdService } from '../../services/tour/shepherd.service';
 import { EventEmitter, Injectable } from '@angular/core';
-import { Pipeline, PipelineService } from '@streampipes/platform-services';
-import { PanelType, DialogService, DialogRef } from '@streampipes/shared-ui';
+import { Pipeline } from '@streampipes/platform-services';
+import {
+    PanelType,
+    DialogService,
+    DialogRef,
+    ObjectPermissionDialogComponent,
+} from '@streampipes/shared-ui';
 import { PipelineStatusDialogComponent } from 
'../dialog/pipeline-status/pipeline-status-dialog.component';
 import { DeletePipelineDialogComponent } from 
'../dialog/delete-pipeline/delete-pipeline-dialog.component';
 import { Router } from '@angular/router';
 import { PipelineAction } from '../model/pipeline-model';
 import { PipelineNotificationsComponent } from 
'../dialog/pipeline-notifications/pipeline-notifications.component';
-import { ObjectPermissionDialogComponent } from 
'../../core-ui/object-permission-dialog/object-permission-dialog.component';
 
 @Injectable({ providedIn: 'root' })
 export class PipelineOperationsService {
@@ -33,8 +36,6 @@ export class PipelineOperationsService {
     stopping: any;
 
     constructor(
-        private shepherdService: ShepherdService,
-        private pipelineService: PipelineService,
         private dialogService: DialogService,
         private router: Router,
     ) {}
@@ -187,8 +188,4 @@ export class PipelineOperationsService {
     modifyPipeline(pipeline) {
         this.showPipelineInEditor(pipeline);
     }
-
-    showLogs(id) {
-        // this.$state.go("streampipes.pipelinelogs", {pipeline: id});
-    }
 }

Reply via email to