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/03 18:36:33 UTC

[incubator-streampipes] 01/03: [STREAMPIPES-437] Add initial authorization support

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 7c233106458466299945b4e4e81f92b1d942d69c
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Sun Oct 3 18:00:31 2021 +0200

    [STREAMPIPES-437] Add initial authorization support
---
 .../client/user/JwtAuthenticationResponse.java     |  17 +--
 .../apache/streampipes/model/client/user/Role.java |  15 ++-
 .../streampipes/model/client/user/UserAccount.java |   4 +-
 .../streampipes/model/client/user/UserInfo.java    |   7 +-
 .../setup/UserRegistrationInstallationStep.java    |   3 +-
 .../streampipes/rest/impl/Authentication.java      |  28 ++---
 .../streampipes/security/jwt/JwtTokenUtils.java    |  20 +++-
 .../user/management/jwt/JwtTokenProvider.java      |  37 ++++++-
 ui/deployment/app-routing.module.mst               |   7 +-
 ui/deployment/base-navigation.component.mst        |  95 +++++++++-------
 ui/deployment/home.service.mst                     |  12 +-
 ui/deployment/modules.yml                          |  11 +-
 ui/deployment/prebuild.js                          |   1 +
 .../src/app/_enums/page-name.enum.ts               |  24 ++--
 .../src/app/_enums/user-role.enum.ts               |  20 ++--
 .../src/app/_guards/page-auth.can-active.guard.ts  |  22 ++--
 ui/src/app/app-routing.module.ts                   |  23 ++--
 .../core/components/base-navigation.component.ts   | 123 +++++++++++++--------
 .../core/components/iconbar/iconbar.component.html |  26 +++--
 .../core/components/iconbar/iconbar.component.ts   |   4 +-
 .../core/components/toolbar/toolbar.component.ts   |  15 +--
 ui/src/app/home/home.component.ts                  |   2 +-
 ui/src/app/services/auth.service.ts                |  75 ++++++++++++-
 23 files changed, 392 insertions(+), 199 deletions(-)

diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/JwtAuthenticationResponse.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/JwtAuthenticationResponse.java
index f3d1bce..ace0e87 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/JwtAuthenticationResponse.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/JwtAuthenticationResponse.java
@@ -3,17 +3,13 @@ package org.apache.streampipes.model.client.user;
 public class JwtAuthenticationResponse {
 
 	private String accessToken;
-	private UserInfo userInfo;
 
-	public static JwtAuthenticationResponse from(String accessToken,
-																							 UserInfo userInfo) {
-		return new JwtAuthenticationResponse(accessToken, userInfo);
+	public static JwtAuthenticationResponse from(String accessToken) {
+		return new JwtAuthenticationResponse(accessToken);
 	}
 
-	private JwtAuthenticationResponse(String accessToken,
-																		UserInfo userInfo) {
+	private JwtAuthenticationResponse(String accessToken) {
 		this.accessToken = accessToken;
-		this.userInfo = userInfo;
 	}
 
 	public String getAccessToken() {
@@ -24,11 +20,4 @@ public class JwtAuthenticationResponse {
 		this.accessToken = accessToken;
 	}
 
-	public UserInfo getUserInfo() {
-		return userInfo;
-	}
-
-	public void setUserInfo(UserInfo userInfo) {
-		this.userInfo = userInfo;
-	}
 }
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 da1f2d2..ca87883 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
@@ -19,11 +19,14 @@
 package org.apache.streampipes.model.client.user;
 
 public enum Role {
-  SYSTEM_ADMINISTRATOR,
-  MANAGER,
-  OPERATOR,
-  DIMENSION_OPERATOR,
-  USER_DEMO,
-  BUSINESS_ANALYST
+  ADMIN,
+  PIPELINE_ADMIN,
+  DASHBOARD_ADMIN,
+  DATA_EXPLORER_ADMIN,
+  CONNECT_ADMIN,
+  DASHBOARD_USER,
+  DATA_EXPLORER_USER,
+  PIPELINE_USER,
+  APP_USER
 
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java
index c082dd6..c6bfd34 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserAccount.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 @TsModel
 public class UserAccount extends Principal {
@@ -162,7 +163,6 @@ public class UserAccount extends Principal {
 		this.hideTutorial = hideTutorial;
 	}
 
-
 	public boolean isDarkMode() {
 		return darkMode;
 	}
@@ -173,7 +173,7 @@ public class UserAccount extends Principal {
 
 	@Override
 	public Collection<? extends GrantedAuthority> getAuthorities() {
-		return null;
+		return roles.stream().map(Enum::toString).map(r -> (GrantedAuthority) () -> r).collect(Collectors.toList());
 	}
 
 	@Override
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java
index 0f8bc98..d12a1ec 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java
@@ -21,6 +21,7 @@ package org.apache.streampipes.model.client.user;
 import org.apache.streampipes.model.shared.annotation.TsModel;
 
 import java.util.List;
+import java.util.Set;
 
 @TsModel
 public class UserInfo {
@@ -28,7 +29,7 @@ public class UserInfo {
   private String userId;
   private String displayName;
   private String email;
-  private List<String> roles;
+  private Set<String> roles;
   private boolean showTutorial;
   private boolean darkMode;
 
@@ -59,11 +60,11 @@ public class UserInfo {
     this.email = email;
   }
 
-  public List<String> getRoles() {
+  public Set<String> getRoles() {
     return roles;
   }
 
-  public void setRoles(List<String> roles) {
+  public void setRoles(Set<String> roles) {
     this.roles = roles;
   }
 
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java
index 90e70f5..92737b1 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/UserRegistrationInstallationStep.java
@@ -47,8 +47,7 @@ public class UserRegistrationInstallationStep extends InstallationStep {
 		this.initialServiceAccountName = initialServiceAccountName;
 		this.initialServiceAccountSecret = initialServiceAccountSecret;
 		roles = new HashSet<>();
-		roles.add(Role.SYSTEM_ADMINISTRATOR);
-		roles.add(Role.USER_DEMO);
+		roles.add(Role.ADMIN);
 	}
 
 	@Override
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
index fdd0824..0ac40fb 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
@@ -55,8 +55,7 @@ public class Authentication extends AbstractRestResource {
     try {
       org.springframework.security.core.Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(token.getUsername(), token.getPassword()));
       SecurityContextHolder.getContext().setAuthentication(authentication);
-      JwtAuthenticationResponse tokenResp = makeJwtResponse(authentication);
-      return ok(tokenResp);
+      return processAuth(authentication);
     } catch (BadCredentialsException e) {
       return unauthorized();
     }
@@ -70,8 +69,7 @@ public class Authentication extends AbstractRestResource {
   public Response doLogin() {
     try {
       org.springframework.security.core.Authentication auth = SecurityContextHolder.getContext().getAuthentication();
-      JwtAuthenticationResponse tokenResp = makeJwtResponse(auth);
-      return ok(tokenResp);
+      return processAuth(auth);
     } catch (BadCredentialsException e) {
       return ok(new ErrorMessage(NotificationType.LOGIN_FAILED.uiNotification()));
     }
@@ -94,18 +92,20 @@ public class Authentication extends AbstractRestResource {
     }
   }
 
+  private Response processAuth(org.springframework.security.core.Authentication auth) {
+    Principal principal = (Principal) auth.getPrincipal();
+    if (principal instanceof UserAccount) {
+      JwtAuthenticationResponse tokenResp = makeJwtResponse(auth);
+      return ok(tokenResp);
+    } else {
+      throw new BadCredentialsException("Could not create auth token");
+    }
+  }
+
   private JwtAuthenticationResponse makeJwtResponse(org.springframework.security.core.Authentication auth) {
     String jwt = new JwtTokenProvider().createToken(auth);
-    UserAccount localUser = (UserAccount) auth.getPrincipal();
-    return JwtAuthenticationResponse.from(jwt, toUserInfo(localUser));
+    return JwtAuthenticationResponse.from(jwt);
   }
 
-  private UserInfo toUserInfo(UserAccount localUser) {
-    UserInfo userInfo = new UserInfo();
-    userInfo.setUserId("id");
-    userInfo.setEmail(localUser.getEmail());
-    userInfo.setDisplayName(localUser.getUsername());
-    userInfo.setShowTutorial(!localUser.isHideTutorial());
-    return userInfo;
-  }
+
 }
diff --git a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
index 5efe10a..beafb4b 100644
--- a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
+++ b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
 import javax.crypto.SecretKey;
 import java.nio.charset.StandardCharsets;
 import java.util.Date;
+import java.util.Map;
 
 public class JwtTokenUtils {
 
@@ -35,6 +36,23 @@ public class JwtTokenUtils {
                                     String tokenSecret,
                                     Date expirationDate) {
 
+    return prepareJwtToken(subject, tokenSecret, expirationDate).compact();
+
+  }
+
+  public static String makeJwtToken(String subject,
+                                    String tokenSecret,
+                                    Map<String, Object> claims,
+                                    Date expirationDate) {
+
+    JwtBuilder builder = prepareJwtToken(subject, tokenSecret, expirationDate);
+
+    return builder.addClaims(claims).compact();
+  }
+
+  private static JwtBuilder prepareJwtToken(String subject,
+                                            String tokenSecret,
+                                            Date expirationDate) {
     SecretKey key = Keys.hmacShaKeyFor(tokenSecret.getBytes(StandardCharsets.UTF_8));
 
     return Jwts
@@ -42,7 +60,7 @@ public class JwtTokenUtils {
             .setSubject(subject)
             .setIssuedAt(new Date())
             .setExpiration(expirationDate)
-            .signWith(key).compact();
+            .signWith(key);
   }
 
   public static String getUserIdFromToken(String tokenSecret,
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java
index e22f51b..3dc0857 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/jwt/JwtTokenProvider.java
@@ -3,13 +3,22 @@ package org.apache.streampipes.user.management.jwt;
 import org.apache.streampipes.config.backend.BackendConfig;
 import org.apache.streampipes.config.backend.model.LocalAuthConfig;
 import org.apache.streampipes.model.client.user.Principal;
+import org.apache.streampipes.model.client.user.UserAccount;
+import org.apache.streampipes.model.client.user.UserInfo;
 import org.apache.streampipes.security.jwt.JwtTokenUtils;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
 
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 public class JwtTokenProvider {
 
+	public static final String CLAIM_USER = "user";
+
 	private BackendConfig config;
 
 	public JwtTokenProvider() {
@@ -18,9 +27,24 @@ public class JwtTokenProvider {
 
 	public String createToken(Authentication authentication) {
 		Principal userPrincipal = (Principal) authentication.getPrincipal();
+		Set<String> roles = authentication
+						.getAuthorities()
+						.stream()
+						.map(GrantedAuthority::getAuthority)
+						.collect(Collectors.toSet());
+
 		Date tokenExpirationDate = makeExpirationDate();
+		Map<String, Object> claims = makeClaims(userPrincipal, roles);
 
-		return JwtTokenUtils.makeJwtToken(userPrincipal.getPrincipalName(), tokenSecret(), tokenExpirationDate);
+		return JwtTokenUtils.makeJwtToken(userPrincipal.getPrincipalName(), tokenSecret(), claims, tokenExpirationDate);
+	}
+
+	private Map<String, Object> makeClaims(Principal principal,
+																				 Set<String> roles) {
+		Map<String, Object> claims = new HashMap<>();
+		claims.put(CLAIM_USER, toUserInfo((UserAccount) principal, roles));
+
+		return claims;
 	}
 
 	public String getUserIdFromToken(String token) {
@@ -48,4 +72,15 @@ public class JwtTokenProvider {
 		Date now = new Date();
 		return new Date(now.getTime() + authConfig().getTokenExpirationTimeMillis());
 	}
+
+	private UserInfo toUserInfo(UserAccount localUser,
+															Set<String> roles) {
+		UserInfo userInfo = new UserInfo();
+		userInfo.setUserId("id");
+		userInfo.setEmail(localUser.getEmail());
+		userInfo.setDisplayName(localUser.getUsername());
+		userInfo.setShowTutorial(!localUser.isHideTutorial());
+		userInfo.setRoles(roles);
+		return userInfo;
+	}
 }
diff --git a/ui/deployment/app-routing.module.mst b/ui/deployment/app-routing.module.mst
index 4ddc5e2..b313701 100644
--- a/ui/deployment/app-routing.module.mst
+++ b/ui/deployment/app-routing.module.mst
@@ -32,6 +32,8 @@ import {InfoComponent} from "./info/info.component";
 import {NotificationsComponent} from "./notifications/notifications.component";
 import {ProfileComponent} from "./profile/profile.component";
 import {ApidocsComponent} from "./apidocs/apidocs.component";
+import { PageName } from './_enums/page-name.enum';
+import { PageAuthGuard } from './_guards/page-auth.can-active.guard';
 
 {{#modulesActive}}
 {{#ng5}}
@@ -50,14 +52,14 @@ const routes: Routes = [
       { path: '', component: HomeComponent, canActivate: [ConfiguredCanActivateGuard] },
       {{#modulesActive}}
       {{#ng5}}
-      { path: '{{{link}}}', component: {{{ng5_component}}} },
+      { path: '{{{link}}}', component: {{{ng5_component}}}, data: { authPageNames: [{{{pageNames}}}]}},
       {{/ng5}}
       {{/modulesActive}}
       { path: 'notifications', component: NotificationsComponent },
       { path: 'info', component: InfoComponent },
       { path: 'pipeline-details', component: PipelineDetailsComponent },
       { path: 'profile', component: ProfileComponent},
-    ], canActivateChild: [AuthCanActivateChildrenGuard] }
+    ], canActivateChild: [AuthCanActivateChildrenGuard, PageAuthGuard] }
 ];
 
 @NgModule({
@@ -67,6 +69,7 @@ const routes: Routes = [
       AuthCanActivateChildrenGuard,
       AlreadyConfiguredCanActivateGuard,
       ConfiguredCanActivateGuard,
+      PageAuthGuard
   ]
 })
 export class AppRoutingModule { }
diff --git a/ui/deployment/base-navigation.component.mst b/ui/deployment/base-navigation.component.mst
index 457c9cf..0ba3d1e 100644
--- a/ui/deployment/base-navigation.component.mst
+++ b/ui/deployment/base-navigation.component.mst
@@ -18,6 +18,8 @@
 
 
 import {NavigationEnd, Router} from "@angular/router";
+import { PageName } from '../../_enums/page-name.enum';
+import { AuthService } from '../../services/auth.service';
 
 export abstract class BaseNavigationComponent {
 
@@ -30,14 +32,18 @@ export abstract class BaseNavigationComponent {
     {
       link: '',
       title: 'Home',
-      icon: 'home'
+      icon: 'home',
+      pagesNames: [PageName.HOME],
+      visible: false
     },
     {{#modulesActive}}
     {{^admin}}
     {
         link: '{{{link}}}',
         title: '{{{title}}}',
-        icon: '{{{icon}}}'
+        icon: '{{{icon}}}',
+        pageNames: [{{{pageNames}}}],
+        visible: false
     },
     {{/admin}}
     {{/modulesActive}}
@@ -49,54 +55,65 @@ export abstract class BaseNavigationComponent {
     {
         link: '{{{link}}}',
         title: '{{{title}}}',
-        icon: '{{{icon}}}'
+        icon: '{{{icon}}}',
+        pageNames: [{{{pageNames}}}],
+        visible: false
     },
     {{/admin}}
     {{/modulesActive}}
   ];
 
-  constructor(protected Router: Router) {
+  constructor(protected authService: AuthService,
+                protected router: Router) {
 
-  }
+    }
 
-  onInit() {
-    this.activePage = this.Router.url.replace("/", "");
-    this.activePageName = this.getPageTitle(this.activePage);
-    this.Router.events.subscribe(event => {
-      if (event instanceof NavigationEnd) {
-        this.activePage = event.url.replace("/", "");
-        this.activePageName = this.getPageTitle(this.activePage);
-      }
-    });
-  }
+    onInit() {
+      this.authService.user$.subscribe(user => {
+        this.menu.forEach(m => m.visible = this.isNavItemVisible(m.pageNames));
+        this.admin.forEach(m => m.visible = this.isNavItemVisible(m.pageNames));
+      });
+      this.activePage = this.router.url.replace('/', '');
+      this.activePageName = this.getPageTitle(this.activePage);
+      this.router.events.subscribe(event => {
+        if (event instanceof NavigationEnd) {
+          this.activePage = event.url.replace('/', '');
+          this.activePageName = this.getPageTitle(this.activePage);
+        }
+      });
+    }
 
-  getActivePage() {
-    return this.activePage;
-  }
+    getActivePage() {
+      return this.activePage;
+    }
+
+    getPageTitle(path) {
+      const allMenuItems = this.menu.concat(this.admin);
+      let currentTitle = 'StreamPipes';
+      allMenuItems.forEach(m => {
+        if (m.link === path) {
+          currentTitle = m.title;
+        }
+      });
+      if (path === 'pipeline-details') {
+        currentTitle = 'Pipeline Details';
+      }
+      return currentTitle;
+    }
 
-  getPageTitle(path) {
-    var allMenuItems = this.menu.concat(this.admin);
-    var currentTitle = 'StreamPipes';
-    allMenuItems.forEach(m => {
-      if (m.link === path) {
-        currentTitle = m.title;
+    go(path, payload?) {
+      if (payload === undefined) {
+        this.router.navigateByUrl(path);
+        this.activePage = path;
+      } else {
+        this.router.navigateByUrl(path, payload);
+        this.activePage = path;
       }
-    });
-    if (path == 'pipeline-details') {
-      currentTitle = 'Pipeline Details';
+      this.activePageName = this.getPageTitle(this.activePage);
     }
-    return currentTitle;
-  }
 
-  go(path, payload?) {
-    if (payload === undefined) {
-      this.Router.navigateByUrl(path);
-      this.activePage = path;
-    } else {
-      this.Router.navigateByUrl(path, payload);
-      this.activePage = path;
+    public isNavItemVisible(pageNames?: PageName[]): boolean {
+      return this.authService.isAnyAccessGranted(pageNames);
     }
-    this.activePageName = this.getPageTitle(this.activePage);
-  };
 
-}
\ No newline at end of file
+}
diff --git a/ui/deployment/home.service.mst b/ui/deployment/home.service.mst
index eab84e7..8d69d72 100644
--- a/ui/deployment/home.service.mst
+++ b/ui/deployment/home.service.mst
@@ -17,11 +17,17 @@
  */
 
 import { Injectable } from '@angular/core';
+import { PageName } from '../_enums/page-name.enum';
+import { AuthService } from '../services/auth.service';
 
 @Injectable()
 export class HomeService {
 
-    constructor() {
+    constructor(private authService: AuthService) {
+    }
+
+    getFilteredServiceLinks() {
+        return this.getServiceLinks().filter(s => this.authService.isAnyAccessGranted(s.pageNames));
     }
 
     getServiceLinks() {
@@ -32,6 +38,7 @@ export class HomeService {
                description: "{{description}}",
                imageUrl: "{{{homeImage}}}",
                icon: "{{{icon}}}",
+               pageNames: [{{{pageNames}}}],
                link: {
                    newWindow: false,
                    value: "{{{link}}}"
@@ -43,6 +50,7 @@ export class HomeService {
                description: "The notification module lets you view all notifications generated by pipelines.",
                imageUrl: "assets/img/home/notifications.png",
                icon: "chat",
+               pageNames: [PageName.NOTIFICATIONS],
                link: {
                    newWindow: false,
                    value: "notifications"
@@ -50,4 +58,4 @@ export class HomeService {
            }
        ];
     }
-}
\ No newline at end of file
+}
diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index 74f1189..63e1b52 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -28,6 +28,7 @@ spEditor:
   icon: 'dashboard'
   homeImage: '/assets/img/home/editor.png'
   admin: false
+  pageNames: 'PageName.PIPELINE_EDITOR'
 spConnect:
   ng5: True
   ng1_templateUrl: ''
@@ -42,6 +43,7 @@ spConnect:
   icon: 'power'
   homeImage: '/assets/img/home/editor.png'
   admin: False
+  pageNames: 'PageName.CONNECT'
 spPipelines:
   ng5: True
   ng1_templateUrl: ''
@@ -56,6 +58,7 @@ spPipelines:
   icon: 'play_arrow'
   homeImage: '/assets/img/home/pipelines.png'
   admin: False
+  pageNames: 'PageName.PIPELINE_OVERVIEW'
 spSensors:
   ng5: False
   ng1_templateUrl: '../sensors/sensors.html'
@@ -83,6 +86,7 @@ spAdd:
   icon: 'cloud_download'
   homeImage: '/assets/img/home/add.png'
   admin: True
+  pageNames: 'PageName.INSTALL_PIPELINE_ELEMENTS'
 spConfiguration:
   ng5: True
   ng1_templateUrl: ''
@@ -97,6 +101,7 @@ spConfiguration:
   description: 'In the configuration module, basic StreamPipes settings and services can be configured.'
   icon: 'settings'
   homeImage: '/assets/img/home/configuration.png'
+  pageNames: 'PageName.SETTINGS'
   admin: True
 spAppOverview:
   ng5: True
@@ -113,6 +118,7 @@ spAppOverview:
   icon: 'apps'
   homeImage: '/assets/img/home/configuration.png'
   admin: false
+  pageNames: 'PageName.APPS'
 spDashboard:
   ng5: True
   ng1_templateUrl: ''
@@ -128,6 +134,7 @@ spDashboard:
   icon: 'insert_chart'
   homeImage: '/assets/img/home/configuration.png'
   admin: false
+  pageNames: 'PageName.DASHBOARD'
 spDataExplorer:
   ng5: True
   ng1_templateUrl: ''
@@ -143,6 +150,7 @@ spDataExplorer:
   icon: 'search'
   homeImage: '/assets/img/home/configuration.png'
   admin: false
+  pageNames: 'PageName.DATA_EXPLORER'
 spFiles:
   ng5: True
   ng1_templateUrl: ''
@@ -157,4 +165,5 @@ spFiles:
   description: 'The file management module lets you upload and manage files that are used by adapters or pipeline elements.'
   icon: 'folder'
   homeImage: '/assets/img/home/configuration.png'
-  admin: true
\ No newline at end of file
+  admin: true
+  pageNames: 'PageName.FILE_UPLOAD'
diff --git a/ui/deployment/prebuild.js b/ui/deployment/prebuild.js
index fcde036..87b0f46 100644
--- a/ui/deployment/prebuild.js
+++ b/ui/deployment/prebuild.js
@@ -69,6 +69,7 @@ for (let module of config.modules) {
         ng5_componentPath: modules[module]['ng5_componentPath'],
         path: modules[module]['path'],
         link: modules[module]['link'],
+        pageNames: modules[module]['pageNames'],
         url: modules[module]['url'],
         title: modules[module]['title'],
         icon: modules[module]['icon'],
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java b/ui/src/app/_enums/page-name.enum.ts
similarity index 78%
copy from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
copy to ui/src/app/_enums/page-name.enum.ts
index da1f2d2..472780a 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
+++ b/ui/src/app/_enums/page-name.enum.ts
@@ -16,14 +16,18 @@
  *
  */
 
-package org.apache.streampipes.model.client.user;
-
-public enum Role {
-  SYSTEM_ADMINISTRATOR,
-  MANAGER,
-  OPERATOR,
-  DIMENSION_OPERATOR,
-  USER_DEMO,
-  BUSINESS_ANALYST
-
+export enum PageName {
+  HOME,
+  PIPELINE_EDITOR,
+  CONNECT,
+  PIPELINE_OVERVIEW,
+  PIPELINE_DETAILS,
+  DASHBOARD,
+  DATA_EXPLORER,
+  APPS,
+  NOTIFICATIONS,
+  INSTALL_PIPELINE_ELEMENTS,
+  FILE_UPLOAD,
+  PROFILE,
+  SETTINGS,
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java b/ui/src/app/_enums/user-role.enum.ts
similarity index 82%
copy from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
copy to ui/src/app/_enums/user-role.enum.ts
index da1f2d2..681f625 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
+++ b/ui/src/app/_enums/user-role.enum.ts
@@ -16,14 +16,14 @@
  *
  */
 
-package org.apache.streampipes.model.client.user;
-
-public enum Role {
-  SYSTEM_ADMINISTRATOR,
-  MANAGER,
-  OPERATOR,
-  DIMENSION_OPERATOR,
-  USER_DEMO,
-  BUSINESS_ANALYST
-
+export enum UserRole {
+  ADMIN,
+  PIPELINE_ADMIN,
+  DASHBOARD_ADMIN,
+  DATA_EXPLORER_ADMIN,
+  CONNECT_ADMIN,
+  DASHBOARD_USER,
+  DATA_EXPLORER_USER,
+  PIPELINE_USER,
+  APP_USER
 }
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java b/ui/src/app/_guards/page-auth.can-active.guard.ts
similarity index 56%
copy from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
copy to ui/src/app/_guards/page-auth.can-active.guard.ts
index da1f2d2..0fe5f05 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java
+++ b/ui/src/app/_guards/page-auth.can-active.guard.ts
@@ -16,14 +16,20 @@
  *
  */
 
-package org.apache.streampipes.model.client.user;
+import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router } from '@angular/router';
+import { AuthService } from '../services/auth.service';
+import { PageName } from '../_enums/page-name.enum';
+import { Injectable } from '@angular/core';
 
-public enum Role {
-  SYSTEM_ADMINISTRATOR,
-  MANAGER,
-  OPERATOR,
-  DIMENSION_OPERATOR,
-  USER_DEMO,
-  BUSINESS_ANALYST
+@Injectable()
+export class PageAuthGuard implements CanActivateChild {
 
+  constructor(private router: Router,
+              private authService: AuthService) {}
+
+  canActivateChild(activatedRouteSnapshot: ActivatedRouteSnapshot): boolean {
+    const pageNames: PageName[] = activatedRouteSnapshot.data.authPageNames;
+
+    return this.authService.isAnyAccessGranted(pageNames);
+  }
 }
diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts
index 251238f..b9d63bb 100644
--- a/ui/src/app/app-routing.module.ts
+++ b/ui/src/app/app-routing.module.ts
@@ -32,6 +32,8 @@ import {InfoComponent} from "./info/info.component";
 import {NotificationsComponent} from "./notifications/notifications.component";
 import {ProfileComponent} from "./profile/profile.component";
 import {ApidocsComponent} from "./apidocs/apidocs.component";
+import { PageName } from './_enums/page-name.enum';
+import { PageAuthGuard } from './_guards/page-auth.can-active.guard';
 
 import { EditorComponent } from './editor/editor.component';
 import { PipelinesComponent } from './pipelines/pipelines.component';
@@ -52,20 +54,20 @@ const routes: Routes = [
   { path: 'standalone/:dashboardId', component: StandaloneDashboardComponent },
   { path: '', component: StreampipesComponent, children: [
       { path: '', component: HomeComponent, canActivate: [ConfiguredCanActivateGuard] },
-      { path: 'editor', component: EditorComponent },
-      { path: 'pipelines', component: PipelinesComponent },
-      { path: 'connect', component: ConnectComponent },
-      { path: 'dashboard', component: DashboardComponent },
-      { path: 'dataexplorer', component: DataExplorerComponent },
-      { path: 'app-overview', component: AppOverviewComponent },
-      { path: 'add', component: AddComponent },
-      { path: 'files', component: FilesComponent },
-      { path: 'configuration', component: ConfigurationComponent },
+      { path: 'editor', component: EditorComponent, data: { authPageNames: [PageName.PIPELINE_EDITOR]}},
+      { path: 'pipelines', component: PipelinesComponent, data: { authPageNames: [PageName.PIPELINE_OVERVIEW]}},
+      { path: 'connect', component: ConnectComponent, data: { authPageNames: [PageName.CONNECT]}},
+      { path: 'dashboard', component: DashboardComponent, data: { authPageNames: [PageName.DASHBOARD]}},
+      { path: 'dataexplorer', component: DataExplorerComponent, data: { authPageNames: [PageName.DATA_EXPLORER]}},
+      { path: 'app-overview', component: AppOverviewComponent, data: { authPageNames: [PageName.APPS]}},
+      { path: 'add', component: AddComponent, data: { authPageNames: [PageName.INSTALL_PIPELINE_ELEMENTS]}},
+      { path: 'files', component: FilesComponent, data: { authPageNames: [PageName.FILE_UPLOAD]}},
+      { path: 'configuration', component: ConfigurationComponent, data: { authPageNames: [PageName.SETTINGS]}},
       { path: 'notifications', component: NotificationsComponent },
       { path: 'info', component: InfoComponent },
       { path: 'pipeline-details', component: PipelineDetailsComponent },
       { path: 'profile', component: ProfileComponent},
-    ], canActivateChild: [AuthCanActivateChildrenGuard] }
+    ], canActivateChild: [AuthCanActivateChildrenGuard, PageAuthGuard] }
 ];
 
 @NgModule({
@@ -75,6 +77,7 @@ const routes: Routes = [
       AuthCanActivateChildrenGuard,
       AlreadyConfiguredCanActivateGuard,
       ConfiguredCanActivateGuard,
+      PageAuthGuard
   ]
 })
 export class AppRoutingModule { }
diff --git a/ui/src/app/core/components/base-navigation.component.ts b/ui/src/app/core/components/base-navigation.component.ts
index e1a9ab0..c1301f1 100644
--- a/ui/src/app/core/components/base-navigation.component.ts
+++ b/ui/src/app/core/components/base-navigation.component.ts
@@ -18,6 +18,8 @@
 
 
 import {NavigationEnd, Router} from "@angular/router";
+import { PageName } from '../../_enums/page-name.enum';
+import { AuthService } from '../../services/auth.service';
 
 export abstract class BaseNavigationComponent {
 
@@ -30,37 +32,51 @@ export abstract class BaseNavigationComponent {
     {
       link: '',
       title: 'Home',
-      icon: 'home'
+      icon: 'home',
+      pagesNames: [PageName.HOME],
+      visible: false
     },
     {
         link: 'editor',
         title: 'Pipeline Editor',
-        icon: 'dashboard'
+        icon: 'dashboard',
+        pageNames: [PageName.PIPELINE_EDITOR],
+        visible: false
     },
     {
         link: 'pipelines',
         title: 'Pipelines',
-        icon: 'play_arrow'
+        icon: 'play_arrow',
+        pageNames: [PageName.PIPELINE_OVERVIEW],
+        visible: false
     },
     {
         link: 'connect',
         title: 'Connect',
-        icon: 'power'
+        icon: 'power',
+        pageNames: [PageName.CONNECT],
+        visible: false
     },
     {
         link: 'dashboard',
         title: 'Dashboard',
-        icon: 'insert_chart'
+        icon: 'insert_chart',
+        pageNames: [PageName.DASHBOARD],
+        visible: false
     },
     {
         link: 'dataexplorer',
         title: 'Data Explorer',
-        icon: 'search'
+        icon: 'search',
+        pageNames: [PageName.DATA_EXPLORER],
+        visible: false
     },
     {
         link: 'app-overview',
         title: 'Apps',
-        icon: 'apps'
+        icon: 'apps',
+        pageNames: [PageName.APPS],
+        visible: false
     },
   ];
 
@@ -68,62 +84,77 @@ export abstract class BaseNavigationComponent {
     {
         link: 'add',
         title: 'Install Pipeline Elements',
-        icon: 'cloud_download'
+        icon: 'cloud_download',
+        pageNames: [PageName.INSTALL_PIPELINE_ELEMENTS],
+        visible: false
     },
     {
         link: 'files',
         title: 'File Management',
-        icon: 'folder'
+        icon: 'folder',
+        pageNames: [PageName.FILE_UPLOAD],
+        visible: false
     },
     {
         link: 'configuration',
         title: 'Configuration',
-        icon: 'settings'
+        icon: 'settings',
+        pageNames: [PageName.SETTINGS],
+        visible: false
     },
   ];
 
-  constructor(protected Router: Router) {
+  constructor(protected authService: AuthService,
+                protected router: Router) {
 
-  }
+    }
 
-  onInit() {
-    this.activePage = this.Router.url.replace("/", "");
-    this.activePageName = this.getPageTitle(this.activePage);
-    this.Router.events.subscribe(event => {
-      if (event instanceof NavigationEnd) {
-        this.activePage = event.url.replace("/", "");
-        this.activePageName = this.getPageTitle(this.activePage);
-      }
-    });
-  }
+    onInit() {
+      this.authService.user$.subscribe(user => {
+        this.menu.forEach(m => m.visible = this.isNavItemVisible(m.pageNames));
+        this.admin.forEach(m => m.visible = this.isNavItemVisible(m.pageNames));
+      });
+      this.activePage = this.router.url.replace('/', '');
+      this.activePageName = this.getPageTitle(this.activePage);
+      this.router.events.subscribe(event => {
+        if (event instanceof NavigationEnd) {
+          this.activePage = event.url.replace('/', '');
+          this.activePageName = this.getPageTitle(this.activePage);
+        }
+      });
+    }
 
-  getActivePage() {
-    return this.activePage;
-  }
+    getActivePage() {
+      return this.activePage;
+    }
+
+    getPageTitle(path) {
+      const allMenuItems = this.menu.concat(this.admin);
+      let currentTitle = 'StreamPipes';
+      allMenuItems.forEach(m => {
+        if (m.link === path) {
+          currentTitle = m.title;
+        }
+      });
+      if (path === 'pipeline-details') {
+        currentTitle = 'Pipeline Details';
+      }
+      return currentTitle;
+    }
 
-  getPageTitle(path) {
-    var allMenuItems = this.menu.concat(this.admin);
-    var currentTitle = 'StreamPipes';
-    allMenuItems.forEach(m => {
-      if (m.link === path) {
-        currentTitle = m.title;
+    go(path, payload?) {
+      if (payload === undefined) {
+        this.router.navigateByUrl(path);
+        this.activePage = path;
+      } else {
+        this.router.navigateByUrl(path, payload);
+        this.activePage = path;
       }
-    });
-    if (path == 'pipeline-details') {
-      currentTitle = 'Pipeline Details';
+      this.activePageName = this.getPageTitle(this.activePage);
     }
-    return currentTitle;
-  }
 
-  go(path, payload?) {
-    if (payload === undefined) {
-      this.Router.navigateByUrl(path);
-      this.activePage = path;
-    } else {
-      this.Router.navigateByUrl(path, payload);
-      this.activePage = path;
+    public isNavItemVisible(pageNames?: PageName[]): boolean {
+      return this.authService.isAnyAccessGranted(pageNames);
     }
-    this.activePageName = this.getPageTitle(this.activePage);
-  };
 
-}
\ No newline at end of file
+}
diff --git a/ui/src/app/core/components/iconbar/iconbar.component.html b/ui/src/app/core/components/iconbar/iconbar.component.html
index b5a74ee..38ffe54 100644
--- a/ui/src/app/core/components/iconbar/iconbar.component.html
+++ b/ui/src/app/core/components/iconbar/iconbar.component.html
@@ -17,14 +17,15 @@
   -->
 
 <div style="padding-top:0px;" fxFlex="100" fxLayout="column">
-    <div [ngClass]="item.link === activePage ? 'sp-navbar-item-selected': 'sp-navbar-item'"
-         *ngFor="let item of menu" style="min-width:0px;padding:0px;padding-top:5px;padding-bottom:5px;">
+    <div *ngFor="let item of menu">
+        <div *ngIf="item.visible" style="min-width:0px;padding:0px;padding-top:5px;padding-bottom:5px;" [ngClass]="item.link === activePage ? 'sp-navbar-item-selected': 'sp-navbar-item'">
         <button mat-button mat-icon-button class="button-margin-iconbar iconbar-size" (click)="go(item.link)"
-                matTooltip="{{item.title}}" matTooltipPosition="right">
+                matTooltip="{{item.title}}" matTooltipPosition="right" >
             <mat-icon [ngClass]="item.link === activePage ? 'sp-navbar-icon-selected' : 'sp-navbar-icon'">
                 {{item.icon}}
             </mat-icon>
         </button>
+        </div>
     </div>
     <div [ngClass]="'notifications' === activePage ? 'sp-navbar-item-selected' : 'sp-navbar-item'"
          style="padding-top:5px;padding-bottom:5px;">
@@ -38,13 +39,16 @@
         </button>
     </div>
     <mat-divider style="border-top-color:var(--color-navigation-text);"></mat-divider>
-    <div [ngClass]="item.link === activePage ? 'sp-navbar-item-selected' : 'sp-navbar-item'"
-         *ngFor="let item of admin" style="padding-top:5px;padding-bottom:5px;">
-        <button mat-button mat-icon-button class="md-icon-button button-margin-iconbar iconbar-size"
-                (click)="go(item.link)"
-                matTooltip="{{item.title}}">
-            <mat-icon
-                    [ngClass]="item.link === activePage ?'sp-navbar-icon-selected' : 'sp-navbar-icon'">{{item.icon}}</mat-icon>
-        </button>
+    <div *ngFor="let item of admin" >
+        <div  [ngClass]="item.link === activePage ? 'sp-navbar-item-selected' : 'sp-navbar-item'"
+              style="padding-top:5px;padding-bottom:5px;"
+              *ngIf="item.visible">
+            <button mat-button mat-icon-button class="md-icon-button button-margin-iconbar iconbar-size"
+                    (click)="go(item.link)"
+                    matTooltip="{{item.title}}" >
+                <mat-icon
+                        [ngClass]="item.link === activePage ?'sp-navbar-icon-selected' : 'sp-navbar-icon'">{{item.icon}}</mat-icon>
+            </button>
+        </div>
     </div>
 </div>
diff --git a/ui/src/app/core/components/iconbar/iconbar.component.ts b/ui/src/app/core/components/iconbar/iconbar.component.ts
index 8e20f84..5c818b1 100644
--- a/ui/src/app/core/components/iconbar/iconbar.component.ts
+++ b/ui/src/app/core/components/iconbar/iconbar.component.ts
@@ -34,9 +34,9 @@ export class IconbarComponent extends BaseNavigationComponent implements OnInit
   unreadNotifications = 0;
 
   constructor(router: Router,
-              private authService: AuthService,
+              authService: AuthService,
               public notificationCountService: NotificationCountService) {
-    super(router);
+    super(authService, router);
   }
 
   ngOnInit(): void {
diff --git a/ui/src/app/core/components/toolbar/toolbar.component.ts b/ui/src/app/core/components/toolbar/toolbar.component.ts
index a8604cb..3cd5c33 100644
--- a/ui/src/app/core/components/toolbar/toolbar.component.ts
+++ b/ui/src/app/core/components/toolbar/toolbar.component.ts
@@ -47,8 +47,8 @@ export class ToolbarComponent extends BaseNavigationComponent implements OnInit
               private profileService: ProfileService,
               private restApi: RestApi,
               private overlay: OverlayContainer,
-              private authService: AuthService) {
-    super(router);
+              authService: AuthService) {
+    super(authService, router);
   }
 
   ngOnInit(): void {
@@ -89,23 +89,18 @@ export class ToolbarComponent extends BaseNavigationComponent implements OnInit
   }
 
   openInfo() {
-    this.Router.navigate(['info']);
+    this.router.navigate(['info']);
     this.activePage = 'Info';
   }
 
   openProfile() {
-    this.Router.navigate(['profile']);
+    this.router.navigate(['profile']);
     this.activePage = 'Profile';
   }
 
   logout() {
     this.authService.logout();
-    this.Router.navigate(['login']);
-    // this.RestApi.logout().subscribe(() => {
-    //   this.AuthStatusService.user = undefined;
-    //   this.AuthStatusService.authenticated = false;
-    //   this.Router.navigateByUrl('login');
-    // });
+    this.router.navigate(['login']);
   }
 
   getVersion() {
diff --git a/ui/src/app/home/home.component.ts b/ui/src/app/home/home.component.ts
index a00a516..e0fba3a 100644
--- a/ui/src/app/home/home.component.ts
+++ b/ui/src/app/home/home.component.ts
@@ -34,7 +34,7 @@ export class HomeComponent {
                 private sanitizer: DomSanitizer,
                 private router: Router,
                 public appConstants: AppConstants) {
-        this.serviceLinks = this.homeService.getServiceLinks();
+        this.serviceLinks = this.homeService.getFilteredServiceLinks();
     }
 
     getBackground(url) {
diff --git a/ui/src/app/services/auth.service.ts b/ui/src/app/services/auth.service.ts
index 209747b..cf2e33c 100644
--- a/ui/src/app/services/auth.service.ts
+++ b/ui/src/app/services/auth.service.ts
@@ -22,9 +22,11 @@ import { BehaviorSubject, Observable, timer } from 'rxjs';
 import { JwtHelperService } from '@auth0/angular-jwt';
 import { JwtTokenStorageService } from './jwt-token-storage.service';
 import { UserInfo } from '../core-model/gen/streampipes-model-client';
-import { filter, map, switchMap, tap } from 'rxjs/operators';
+import { filter, map, switchMap } from 'rxjs/operators';
 import { Router } from '@angular/router';
 import { LoginService } from '../login/services/login.service';
+import { PageName } from '../_enums/page-name.enum';
+import { UserRole } from '../_enums/user-role.enum';
 
 @Injectable()
 export class AuthService {
@@ -51,10 +53,13 @@ export class AuthService {
     }
 
     public login(data) {
+        const jwtHelper: JwtHelperService = new JwtHelperService({});
+        const decodedToken = jwtHelper.decodeToken(data.accessToken);
+        console.log(decodedToken);
         this.tokenStorage.saveToken(data.accessToken);
-        this.tokenStorage.saveUser(data.userInfo);
+        this.tokenStorage.saveUser(decodedToken.user);
         this.authToken$.next(data.accessToken);
-        this.user$.next(data.userInfo);
+        this.user$.next(decodedToken.user);
     }
 
     public logout() {
@@ -63,7 +68,7 @@ export class AuthService {
     }
 
     public getCurrentUser(): UserInfo {
-        return this.tokenStorage.getUser();
+        return this.user$.getValue() || this.tokenStorage.getUser();
     }
 
     public authenticated(): boolean {
@@ -114,4 +119,66 @@ export class AuthService {
             this.router.navigate(['login']);
         });
     }
+
+    getUserRoles(): string[] {
+        return this.getCurrentUser().roles;
+    }
+
+    public hasRole(role: UserRole): boolean {
+        return this.getUserRoles().includes(UserRole[role]);
+    }
+
+    public hasAnyRole(roles: UserRole[]): boolean {
+        if (Array.isArray(roles)) {
+            return roles.reduce((aggregator: false, role: UserRole) => aggregator || this.hasRole(role), false);
+        }
+
+        return false;
+    }
+
+    isAnyAccessGranted(pageNames: PageName[]): boolean {
+        if (!pageNames || pageNames.length === 0) {
+            return true;
+        }
+
+        const result = pageNames.some(pageName => this.isAccessGranted(pageName));
+        if (!result) {
+            this.router.navigate(['']);
+        }
+        console.log(pageNames);
+        console.log(result);
+        return result;
+    }
+
+    isAccessGranted(pageName: PageName) {
+        console.log(pageName);
+        console.log(this.hasRole(UserRole.ADMIN));
+        if (this.hasRole(UserRole.ADMIN)) {
+            return true;
+        }
+        switch (pageName) {
+            case PageName.HOME:
+                return true;
+            case PageName.PIPELINE_EDITOR:
+                return this.hasAnyRole([UserRole.PIPELINE_ADMIN]);
+            case PageName.PIPELINE_OVERVIEW:
+                return this.hasAnyRole([UserRole.PIPELINE_ADMIN]);
+            case PageName.CONNECT:
+                return this.hasAnyRole([UserRole.CONNECT_ADMIN]);
+            case PageName.DASHBOARD:
+                return this.hasAnyRole([UserRole.DASHBOARD_USER, UserRole.DASHBOARD_ADMIN]);
+            case PageName.DATA_EXPLORER:
+                return this.hasAnyRole([UserRole.DATA_EXPLORER_ADMIN, UserRole.DATA_EXPLORER_USER]);
+            case PageName.APPS:
+                return this.hasAnyRole([UserRole.APP_USER]);
+            case PageName.FILE_UPLOAD:
+                return this.hasAnyRole([UserRole.CONNECT_ADMIN, UserRole.PIPELINE_ADMIN]);
+            case PageName.INSTALL_PIPELINE_ELEMENTS:
+                return this.hasAnyRole([UserRole.ADMIN]);
+            case PageName.SETTINGS:
+                return this.hasAnyRole([UserRole.ADMIN]);
+            default:
+                return true;
+        }
+    }
 }