From a15fc5fd4e96769777dbcba49b18e6535f8f2419 Mon Sep 17 00:00:00 2001
From: xkureck <luckureckova@gmail.com>
Date: Wed, 13 Oct 2021 17:08:36 +0200
Subject: [PATCH 1/2] feat(admin): new section - Service account in My profile
 section

*  new page on My profile section "Service account"
* new section with
user type: service in My profile section which should be used by user to
manage his service accounts
* in admin section pages "service
identitites" and "associated users" moved from advanced menu
* service
identitites renamed to "service accounts"
---
 .../src/app/admin/admin-routing.module.ts     | 38 +++++-----
 .../admin-user-detail-page.component.html     |  2 +-
 .../admin-user-detail-page.component.ts       |  4 ++
 .../users-list/users-list.component.html      |  4 +-
 .../users-list/users-list.component.ts        | 12 ++--
 .../side-menu/side-menu-item.service.ts       | 66 ++++++++++++-----
 .../shared/side-menu/side-menu.component.ts   |  2 +-
 .../user-overview/user-overview.component.ts  | 30 ++++++--
 ...r-settings-associated-users.component.html |  4 +-
 ...ser-settings-associated-users.component.ts | 20 +++++-
 .../user-settings-overview.component.ts       | 17 -----
 ...service-identity-detail-page.component.css |  0
 ...ervice-identity-detail-page.component.html | 34 +++++++++
 .../service-identity-detail-page.component.ts | 72 +++++++++++++++++++
 .../service-identity-overview.component.css   |  0
 .../service-identity-overview.component.html  |  1 +
 .../service-identity-overview.component.ts    | 30 ++++++++
 ...settings-service-identities.component.html | 60 ++++++++--------
 ...r-settings-service-identities.component.ts | 27 ++++---
 .../src/app/users/users-routing.module.ts     | 23 ++++++
 apps/admin-gui/src/app/users/users.module.ts  |  4 ++
 .../application-form-list.component.html      |  2 +-
 apps/admin-gui/src/assets/i18n/en.json        |  8 +--
 23 files changed, 344 insertions(+), 116 deletions(-)
 create mode 100644 apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.css
 create mode 100644 apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.html
 create mode 100644 apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.ts
 create mode 100644 apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.css
 create mode 100644 apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.html
 create mode 100644 apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.ts

diff --git a/apps/admin-gui/src/app/admin/admin-routing.module.ts b/apps/admin-gui/src/app/admin/admin-routing.module.ts
index 92d184e56..3283dfc22 100644
--- a/apps/admin-gui/src/app/admin/admin-routing.module.ts
+++ b/apps/admin-gui/src/app/admin/admin-routing.module.ts
@@ -158,26 +158,26 @@ const routes: Routes = [
         data: {animation: 'UserRolesPage'}
       },
       {
-        path: 'settings',
-        component: UserSettingsComponent,
-        children: [
-          {
-            path: '',
-            component: UserSettingsOverviewComponent,
-            data: {animation: 'UserSettingsOverviewPage'}
-          },
-          {
-            path: 'service-identities',
-            component: UserSettingsServiceIdentitiesComponent,
-            data: {animation: 'UserServiceIdentities'}
-          },
-          {
-            path: 'associated-users',
-            component: UserSettingsAssociatedUsersComponent,
-            data: {animation: 'AssociatedUsersPage'}
-          }
-        ]
+        path: 'service-identities',
+        component: UserSettingsServiceIdentitiesComponent,
+        data: {animation: 'UserServiceIdentities'}
+      },
+      {
+        path: 'associated-users',
+        component: UserSettingsAssociatedUsersComponent,
+        data: {animation: 'AssociatedUsersPage'}
       }
+      // {
+      //   path: 'settings',
+      //   component: UserSettingsComponent,
+      //   children: [
+      //     {
+      //       path: '',
+      //       component: UserSettingsOverviewComponent,
+      //       data: {animation: 'UserSettingsOverviewPage'}
+      //     }
+      //   ]
+      // }
     ]
   },
   {
diff --git a/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.html b/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.html
index 393429d94..7c2d99921 100644
--- a/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.html
+++ b/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.html
@@ -6,7 +6,7 @@
     <mat-icon
       matTooltip="{{'ADMIN_USER.ENTITY' | translate}}"
       [ngStyle]="{'color':'black'}"
-      svgIcon='perun-user-dark'
+      [svgIcon]="svgIcon"
       class="perun-icon perun-icon-detail">
     </mat-icon>
     <div class="page-title-block">
diff --git a/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.ts b/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.ts
index fb6b2e83f..879898803 100644
--- a/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.ts
+++ b/apps/admin-gui/src/app/admin/pages/admin-user-detail-page/admin-user-detail-page.component.ts
@@ -28,6 +28,7 @@ export class AdminUserDetailPageComponent implements OnInit {
   path: string;
   regex: string;
   loading = false;
+  svgIcon = 'perun-user-dark';
 
   ngOnInit() {
     this.loading = true;
@@ -39,6 +40,9 @@ export class AdminUserDetailPageComponent implements OnInit {
 
       this.usersService.getUserById(userId).subscribe(user => {
         this.user = user;
+        if(this.user.serviceUser) {
+          this.svgIcon = 'perun-service-identity';
+        }
 
         const userItem = this.sideMenuItemService.parseUser(user, this.path, this.regex);
         this.sideMenuService.setAdminItems([userItem]);
diff --git a/apps/admin-gui/src/app/shared/components/users-list/users-list.component.html b/apps/admin-gui/src/app/shared/components/users-list/users-list.component.html
index 162157695..ac008eccf 100644
--- a/apps/admin-gui/src/app/shared/components/users-list/users-list.component.html
+++ b/apps/admin-gui/src/app/shared/components/users-list/users-list.component.html
@@ -76,8 +76,8 @@
       <tr
         *matRowDef="let user; columns: displayedColumns;"
         [class.cursor-pointer]="!disableRouting"
-        [perunWebAppsForceRouterLink]="disableRouting ? null : ['/admin/users', user.id]"
-        [perunWebAppsMiddleClickRouterLink]="disableRouting ? null : ['/admin/users', user.id]"
+        [perunWebAppsForceRouterLink]="disableRouting ? null : (routeToAdmin ? ['/admin/users', user.id] : ['/myProfile/service-identities', user.id])"
+        [perunWebAppsMiddleClickRouterLink]="disableRouting ? null : (routeToAdmin ? ['/admin/users', user.id] : ['/myProfile/service-identities', user.id])"
         class="dark-hover-list-item"
         mat-row>
       </tr>
diff --git a/apps/admin-gui/src/app/shared/components/users-list/users-list.component.ts b/apps/admin-gui/src/app/shared/components/users-list/users-list.component.ts
index 21cb25f2c..d3860c5b4 100644
--- a/apps/admin-gui/src/app/shared/components/users-list/users-list.component.ts
+++ b/apps/admin-gui/src/app/shared/components/users-list/users-list.component.ts
@@ -1,4 +1,4 @@
-import { AfterViewInit, Component, Input, OnChanges, ViewChild } from '@angular/core';
+import { Component, Input, OnChanges, ViewChild } from '@angular/core';
 import { MatSort } from '@angular/material/sort';
 import { MatTableDataSource } from '@angular/material/table';
 import {SelectionModel} from '@angular/cdk/collections';
@@ -17,7 +17,7 @@ import { GuiAuthResolver, TableCheckbox } from '@perun-web-apps/perun/services';
   templateUrl: './users-list.component.html',
   styleUrls: ['./users-list.component.scss']
 })
-export class UsersListComponent implements OnChanges, AfterViewInit {
+export class UsersListComponent implements OnChanges{
 
   constructor(private authResolver: GuiAuthResolver,
               private tableCheckbox: TableCheckbox) { }
@@ -40,6 +40,9 @@ export class UsersListComponent implements OnChanges, AfterViewInit {
   displayedColumns: string[] = ['select', 'user', 'id', 'name', 'email', 'logins', 'organization'];
 
 
+  @Input()
+  routeToAdmin = true;
+
   @Input()
   disableRouting = false;
 
@@ -118,13 +121,10 @@ export class UsersListComponent implements OnChanges, AfterViewInit {
     this.dataSource.data = this.users;
   }
 
-  ngAfterViewInit(): void {
+  ngOnChanges() {
     if (!this.authResolver.isPerunAdminOrObserver()){
       this.displayedColumns = this.displayedColumns.filter(column => column !== 'id');
     }
-  }
-
-  ngOnChanges() {
     this.setDataSource();
   }
 
diff --git a/apps/admin-gui/src/app/shared/side-menu/side-menu-item.service.ts b/apps/admin-gui/src/app/shared/side-menu/side-menu-item.service.ts
index 10bb72257..e95761c8f 100644
--- a/apps/admin-gui/src/app/shared/side-menu/side-menu-item.service.ts
+++ b/apps/admin-gui/src/app/shared/side-menu/side-menu-item.service.ts
@@ -131,8 +131,13 @@ export class SideMenuItemService {
         },
         {
           label: 'MENU_ITEMS.USER.ROLES',
-          url: [`myProfile/roles`],
-          activatedRegex: `myProfile/roles`
+          url: [`/myProfile/roles`],
+          activatedRegex: `/myProfile/roles`
+        },
+        {
+          label: 'MENU_ITEMS.USER.SERVICE_IDENTITIES',
+          url: [`/myProfile/service-identities`],
+          activatedRegex: `^/myProfile/service-identities`
         },
         {
           label: 'MENU_ITEMS.USER.SETTINGS',
@@ -374,6 +379,31 @@ export class SideMenuItemService {
     };
   }
 
+  parseServiceIdentity(user: User): SideMenuItem {
+    return {
+      label: parseFullName(user),
+      baseLink: [`/myProfile/service-identities/${user.id}`],
+      backgroundColorCss: this.userBgColor,
+      textColorCss: this.userTextColor,
+      links: [
+        {
+          label: 'MENU_ITEMS.USER.OVERVIEW',
+          url: [`/myProfile/service-identities/${user.id}`],
+          activatedRegex: '/myProfile/service-identities/\\d+$'
+        },
+        {
+          label: 'MENU_ITEMS.USER.ASSOCIATED_USERS',
+          url: [`/myProfile/service-identities/${user.id}/associated-users`],
+          activatedRegex: '/myProfile/service-identities/\\d+/associated-users'
+        }
+      ],
+      colorClass: 'user-bg-color',
+      icon: 'perun-service-identity',
+      activatedClass: 'dark-item-activated',
+      linksClass: 'dark-item-links'
+    };
+  }
+
   parseService(service: Service): SideMenuItem {
     return {
       label: service.name,
@@ -639,36 +669,34 @@ export class SideMenuItemService {
     // Roles
     links.push({
       label: 'MENU_ITEMS.USER.ROLES',
-        url: [`${path}/roles`],
+      url: [`${path}/roles`],
       activatedRegex: `^${path}/roles`
     });
 
-
-    // Settings
-    links.push({
-      label: 'MENU_ITEMS.ADMIN.SETTINGS',
-      url: [`${path}/settings`],
-      activatedRegex: `${regex}/settings$`,
-      children: [],
-      showChildrenRegex: `${regex}/settings`
-    });
-
     // Settings associated users if user is service
     // Settings service identities if user is person
     if (user.serviceUser) {
-      links[links.length - 1].children.push({
+      links.push({
         label: 'MENU_ITEMS.USER.ASSOCIATED_USERS',
-        url: [`${path}/settings/associated-users`],
-        activatedRegex: `^${path}/settings/associated-users`
+        url: [`${path}/associated-users`],
+        activatedRegex: `^${path}/associated-users`
       });
     } else {
-      links[links.length - 1].children.push({
+      links.push({
         label: 'MENU_ITEMS.USER.SERVICE_IDENTITIES',
-        url: [`${path}/settings/service-identities`],
-        activatedRegex: `^${path}/settings/service-identities`
+        url: [`${path}/service-identities`],
+        activatedRegex: `^${path}/service-identities`
       });
     }
 
+    // Settings
+    // links.push({
+    //   label: 'MENU_ITEMS.ADMIN.SETTINGS',
+    //   url: [`${path}/settings`],
+    //   activatedRegex: `${regex}/settings$`,
+    //   children: [],
+    //   showChildrenRegex: `${regex}/settings`
+    // });
     return links;
   }
 
diff --git a/apps/admin-gui/src/app/shared/side-menu/side-menu.component.ts b/apps/admin-gui/src/app/shared/side-menu/side-menu.component.ts
index a5a29892c..fa91eded2 100644
--- a/apps/admin-gui/src/app/shared/side-menu/side-menu.component.ts
+++ b/apps/admin-gui/src/app/shared/side-menu/side-menu.component.ts
@@ -141,7 +141,7 @@ export class SideMenuComponent implements OnInit {
   }
 
   private setUserItems(items: SideMenuItem[]) {
-    this.userItemOpened = true;
+    this.userItemOpened = items.length === 0;
     this.resetExceptUser();
     this.setNewItems(this.userItems, items);
   }
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-overview/user-overview.component.ts b/apps/admin-gui/src/app/users/pages/user-detail-page/user-overview/user-overview.component.ts
index 46314c8ec..5f2b5febc 100644
--- a/apps/admin-gui/src/app/users/pages/user-detail-page/user-overview/user-overview.component.ts
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-overview/user-overview.component.ts
@@ -29,6 +29,7 @@ export class UserOverviewComponent implements OnInit {
 
   navItems: MenuItem[] = [];
   user: User;
+  isServiceUser = false;
   userID: number;
   path: string;
   mailDataSource: MatTableDataSource<Attribute>;
@@ -41,7 +42,7 @@ export class UserOverviewComponent implements OnInit {
       if(params['userId'] !== undefined) {
         this.userService.getUserById(params['userId']).subscribe(user => {
           this.user = user;
-
+          this.isServiceUser = user.serviceUser;
           this.initNavItems();
         });
       } else {
@@ -113,13 +114,30 @@ export class UserOverviewComponent implements OnInit {
         url: `roles`,
         label: 'MENU_ITEMS.USER.ROLES',
         style: 'user-btn'
-      },
-      {
-        cssIcon: 'perun-settings2',
-        url: `settings`,
-        label: 'MENU_ITEMS.ADMIN.SETTINGS',
+      });
+    if(this.isServiceUser){
+      this.navItems.push({
+        cssIcon: 'perun-user-dark',
+        url:`associated-users`,
+        label: 'MENU_ITEMS.USER.ASSOCIATED_USERS',
         style: 'user-btn'
       });
+    } else {
+      this.navItems.push({
+        cssIcon: 'perun-service-identity',
+        url:`service-identities`,
+        label: 'MENU_ITEMS.USER.SERVICE_IDENTITIES',
+        style: 'user-btn'
+      });
+    }
+    if (!window.location.pathname.startsWith('/admin')) {
+      this.navItems.push({
+          cssIcon: 'perun-settings2',
+          url: `settings`,
+          label: 'MENU_ITEMS.ADMIN.SETTINGS',
+          style: 'user-btn'
+        });
+    }
   }
 
   changeEmail() {
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.html b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.html
index 562ab1d5f..1862081be 100644
--- a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.html
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.html
@@ -24,7 +24,9 @@
     *ngIf="!loading"
     [users]="associatedUsers"
     [selection]="selection"
-    [displayedColumns]="displayedColumns">
+    [disableRouting]="disableRouting"
+    [displayedColumns]="displayedColumns"
+  >
   </app-users-list>
 </div>
 
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.ts b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.ts
index 21d897256..99dac9c02 100644
--- a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.ts
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component.ts
@@ -9,6 +9,7 @@ import { SelectionModel } from '@angular/cdk/collections';
 import { getDefaultDialogConfig } from '@perun-web-apps/perun/utils';
 import { ConnectIdentityDialogComponent } from '../../../../../shared/components/dialogs/connect-identity-dialog/connect-identity-dialog.component';
 import { DisconnectIdentityDialogComponent } from '../../../../../shared/components/dialogs/disconnect-identity-dialog/disconnect-identity-dialog.component';
+import { GuiAuthResolver } from '@perun-web-apps/perun/services';
 
 @Component({
   selector: 'app-user-settings-associated-users',
@@ -20,6 +21,7 @@ export class UserSettingsAssociatedUsersComponent implements OnInit {
   constructor(private route: ActivatedRoute,
               private dialog: MatDialog,
               private router: Router,
+              public authResolver: GuiAuthResolver,
               private userManager: UsersManagerService) {
   }
 
@@ -29,15 +31,19 @@ export class UserSettingsAssociatedUsersComponent implements OnInit {
   userId: number;
   tableId = TABLE_USER_ASSOCIATED_USERS;
   displayedColumns = [ 'select', 'id', 'user', 'name' ];
+  addAuth: boolean;
+  removeAuth: boolean;
+  disableRouting: boolean;
 
   ngOnInit(): void {
     this.loading = true;
 
-    this.route.parent.parent.params
+    this.route.parent.params
       .subscribe(params => {
         this.userId = params["userId"];
         this.userManager.getUsersBySpecificUser(this.userId).subscribe(associatedUsers => {
           this.associatedUsers = associatedUsers;
+          this.setAuth();
           this.loading = false;
         });
       });
@@ -52,6 +58,12 @@ export class UserSettingsAssociatedUsersComponent implements OnInit {
     });
   }
 
+  setAuth() {
+    this.addAuth = this.authResolver.isAuthorized('addSpecificUserOwner_User_User_policy', [{id: this.userId, beanName: 'User'}]);
+    this.removeAuth = this.authResolver.isAuthorized('removeSpecificUserOwner_User_User_policy', [{id: this.userId, beanName: 'User'}]);
+    this.disableRouting = !this.authResolver.isPerunAdminOrObserver();
+  }
+
   onAdd(){
     const config = getDefaultDialogConfig();
     config.width = "1250px";
@@ -85,7 +97,11 @@ export class UserSettingsAssociatedUsersComponent implements OnInit {
 
     dialogRef.afterClosed().subscribe(result => {
       if (result) {
-        this.refreshTable();
+        if(!this.authResolver.isAuthorized('getUsersBySpecificUser_User_policy', [{id: this.userId, beanName: 'User'}])) {
+          this.router.navigate(['/myProfile']);
+        } else {
+          this.refreshTable();
+        }
       }
     });
   }
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-overview/user-settings-overview.component.ts b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-overview/user-settings-overview.component.ts
index 748207c1e..e2d360ea0 100644
--- a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-overview/user-settings-overview.component.ts
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-overview/user-settings-overview.component.ts
@@ -42,7 +42,6 @@ export class UserSettingsOverviewComponent implements OnInit {
     this.navItems = [
     ];
     // if at user profile, add user gui config item
-    // if at admin profile, add service identities
     if (!window.location.pathname.startsWith('/admin')) {
       this.navItems.push(
         {
@@ -57,22 +56,6 @@ export class UserSettingsOverviewComponent implements OnInit {
           label: 'MENU_ITEMS.USER.GUI_CONFIG',
           style: 'user-btn'
         });
-    } else {
-      if(this.isServiceUser){
-        this.navItems.push({
-          cssIcon: 'perun-service-identity',
-          url:`associated-users`,
-          label: 'MENU_ITEMS.USER.ASSOCIATED_USERS',
-          style: 'user-btn'
-        });
-      } else {
-        this.navItems.push({
-          cssIcon: 'perun-service-identity',
-          url:`service-identities`,
-          label: 'MENU_ITEMS.USER.SERVICE_IDENTITIES',
-          style: 'user-btn'
-        });
-      }
     }
   }
 }
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.css b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.html b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.html
new file mode 100644
index 000000000..7eb18042c
--- /dev/null
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.html
@@ -0,0 +1,34 @@
+<div *ngIf="user !== undefined" class="container-fluid pl-xl-5 pr-xl-5 user-theme">
+  <perun-web-apps-back-button>
+  </perun-web-apps-back-button>
+  <mat-spinner *ngIf="loading" class="mr-auto ml-auto"></mat-spinner>
+  <div class="d-flex page-title-headtitle">
+    <mat-icon
+      matTooltip="{{'MENU_ITEMS.USER.ENTITY' | translate}}"
+      [ngStyle]="{'color':'black'}"
+      svgIcon='perun-service-identity'
+      class="perun-icon perun-icon-detail">
+    </mat-icon>
+    <div class="page-title-block">
+      <div class="page-title-headline d-flex align-items-center">
+        <a [routerLink]="['/myProfile/service-identities', user.id]" class="user-link" queryParamsHandling="merge">
+          {{user | userFullName}}
+        </a>
+        <span class="text-muted">
+          &nbsp;#{{user.id}}
+        </span>
+        <button *ngIf="authResolver.isPerunAdmin()" (click)="editUser()" mat-icon-button>
+          <mat-icon>edit</mat-icon>
+        </button>
+      </div>
+      <div>
+        {{'ADMIN_USER.UUID' | translate}}: {{user.uuid}}
+      </div>
+      <span class="mt-1 entity-info">
+        {{'MENU_ITEMS.USER.ENTITY' | translate}},
+        {{'MENU_ITEMS.USER.USER_TYPE' | translate}}: {{getUserType()}}
+      </span>
+    </div>
+  </div>
+  <app-animated-router-outlet></app-animated-router-outlet>
+</div>
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.ts b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.ts
new file mode 100644
index 000000000..d8b7113f3
--- /dev/null
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component.ts
@@ -0,0 +1,72 @@
+import { Component, OnInit } from '@angular/core';
+import { SideMenuService } from '../../../../../../core/services/common/side-menu.service';
+import { GuiAuthResolver } from '@perun-web-apps/perun/services';
+import { ActivatedRoute } from '@angular/router';
+import { User, UsersManagerService } from '@perun-web-apps/perun/openapi';
+import { SideMenuItemService } from '../../../../../../shared/side-menu/side-menu-item.service';
+import { getDefaultDialogConfig } from '@perun-web-apps/perun/utils';
+import { EditUserDialogComponent } from '../../../../../../shared/components/dialogs/edit-user-dialog/edit-user-dialog.component';
+import { MatDialog } from '@angular/material/dialog';
+
+@Component({
+  selector: 'app-service-identity-detail-page',
+  templateUrl: './service-identity-detail-page.component.html',
+  styleUrls: ['./service-identity-detail-page.component.css']
+})
+export class ServiceIdentityDetailPageComponent implements OnInit {
+
+  constructor(
+    private sideMenuService: SideMenuService,
+    private usersService: UsersManagerService,
+    private sideMenuItemService: SideMenuItemService,
+    private route: ActivatedRoute,
+    private dialog: MatDialog,
+    public authResolver: GuiAuthResolver
+  ) {
+  }
+
+  user: User;
+  loading = false;
+
+
+  ngOnInit() {
+    this.loading = true;
+    this.route.params.subscribe(params => {
+      const userId = params['userId'];
+
+      this.usersService.getUserById(userId).subscribe(user => {
+        this.user = user;
+
+        const userItem = this.sideMenuItemService.parseServiceIdentity(user);
+        this.sideMenuService.setUserItems([userItem]);
+        this.loading = false;
+      }, () => this.loading = false);
+    });
+  }
+
+  getUserType(){
+    if (this.user.serviceUser){
+      return "Service";
+    }
+    return "Person";
+  }
+
+  editUser() {
+    const config = getDefaultDialogConfig();
+    config.width = '450px';
+    config.data = {
+      theme: 'admin-theme',
+      user: this.user
+    };
+
+    const dialogRef = this.dialog.open(EditUserDialogComponent, config);
+
+    dialogRef.afterClosed().subscribe(result => {
+      if (result) {
+        this.usersService.getUserById(this.user.id).subscribe(user => {
+          this.user = user;
+        });
+      }
+    });
+  }
+}
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.css b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.html b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.html
new file mode 100644
index 000000000..77ae77437
--- /dev/null
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.html
@@ -0,0 +1 @@
+<perun-web-apps-menu-buttons-field [items]="navItems" [size]="'small'"></perun-web-apps-menu-buttons-field>
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.ts b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.ts
new file mode 100644
index 000000000..1c55e7f16
--- /dev/null
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component.ts
@@ -0,0 +1,30 @@
+import { Component, OnInit } from '@angular/core';
+import { MenuItem } from '@perun-web-apps/perun/models';
+
+@Component({
+  selector: 'app-service-identity-overview',
+  templateUrl: './service-identity-overview.component.html',
+  styleUrls: ['./service-identity-overview.component.css']
+})
+export class ServiceIdentityOverviewComponent implements OnInit {
+
+  constructor() { }
+
+  navItems: MenuItem[] = [];
+
+  ngOnInit(): void {
+    this.initNavItems();
+  }
+
+  private initNavItems() {
+    this.navItems = [
+      {
+        cssIcon: 'perun-user',
+        url: `associated-users`,
+        label: 'MENU_ITEMS.USER.ASSOCIATED_USERS',
+        style: 'user-btn'
+      }
+    ];
+  }
+
+}
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.html b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.html
index f87a1c28e..3f1e2a2fd 100644
--- a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.html
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.html
@@ -1,31 +1,33 @@
-<div>
-  <h1 class="page-subtitle">{{'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.TITLE' | translate}}</h1>
-  <perun-web-apps-refresh-button (refresh)="refreshTable()" *ngIf="!loading"></perun-web-apps-refresh-button>
-  <button
-    *ngIf="!loading && authResolver.isPerunAdmin()"
-    (click)="onAdd()"
-    mat-flat-button
-    class="mr-2"
-    color="accent">
-    {{'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.CREATE' | translate}}
-  </button>
-  <button
-    *ngIf="!loading && authResolver.isPerunAdmin()"
-    (click)="onRemove()"
-    [disabled]="selection.selected.length === 0"
-    mat-flat-button
-    class="mr-2"
-    color="warn">
-    {{'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.DELETE' | translate}}
-  </button>
-  <app-users-list
-    [tableId]="tableId"
-    [noUsersFoundLabel]="'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.NO_IDENTITIES' | translate"
-    *ngIf="!loading"
-    [users]="identities"
-    [selection]="selection"
-    [displayedColumns]="displayedColumns">
-  </app-users-list>
-</div>
+<h1 class="page-subtitle">{{'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.TITLE' | translate}}</h1>
+<perun-web-apps-refresh-button (refresh)="refreshTable()"></perun-web-apps-refresh-button>
+<button
+  *ngIf="!loading && addIdentity"
+  (click)="onAdd()"
+  mat-flat-button
+  class="mr-2"
+  color="accent">
+  {{'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.CREATE' | translate}}
+</button>
+<button
+  *ngIf="!loading && removeIdentity"
+  (click)="onRemove()"
+  [disabled]="selection.selected.length === 0"
+  mat-flat-button
+  class="mr-2"
+  color="warn">
+  {{'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.DELETE' | translate}}
+</button>
 
 <mat-spinner *ngIf="loading" class="mr-auto ml-auto"></mat-spinner>
+
+<app-users-list
+  [tableId]="tableId"
+  [noUsersFoundLabel]="'USER_DETAIL.SETTINGS.SERVICE_IDENTITIES.NO_IDENTITIES' | translate"
+  *ngIf="!loading"
+  [users]="identities"
+  [selection]="selection"
+  [routeToAdmin]="routeToAdminSection"
+  [displayedColumns]="displayedColumns">
+</app-users-list>
+
+
diff --git a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.ts b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.ts
index 606e1fdbc..3ba2d535f 100644
--- a/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.ts
+++ b/apps/admin-gui/src/app/users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component.ts
@@ -7,7 +7,7 @@ import { TABLE_USER_SERVICE_IDENTITIES } from '@perun-web-apps/config/table-conf
 import { getDefaultDialogConfig } from '@perun-web-apps/perun/utils';
 import { ConnectIdentityDialogComponent } from '../../../../../shared/components/dialogs/connect-identity-dialog/connect-identity-dialog.component';
 import { DisconnectIdentityDialogComponent } from '../../../../../shared/components/dialogs/disconnect-identity-dialog/disconnect-identity-dialog.component';
-import { GuiAuthResolver } from '@perun-web-apps/perun/services';
+import { GuiAuthResolver, StoreService } from '@perun-web-apps/perun/services';
 
 @Component({
   selector: 'app-user-settings-service-identities',
@@ -20,7 +20,8 @@ export class UserSettingsServiceIdentitiesComponent implements OnInit {
               private dialog: MatDialog,
               private router: Router,
               private userManager: UsersManagerService,
-              public authResolver: GuiAuthResolver
+              public authResolver: GuiAuthResolver,
+              private store: StoreService,
               ) { }
 
   loading = false;
@@ -28,18 +29,23 @@ export class UserSettingsServiceIdentitiesComponent implements OnInit {
   identities: User[] = [];
   userId: number;
   tableId = TABLE_USER_SERVICE_IDENTITIES;
-  displayedColumns = [ 'select', 'id', 'user', 'name' ];
+  displayedColumns = ['select', 'id', 'user', 'name']
+  addIdentity: boolean;
+  removeIdentity: boolean;
+  routeToAdminSection = true;
 
   ngOnInit(): void {
     this.loading = true;
 
-    this.route.parent.parent.params
+    this.route.parent.params
         .subscribe(params => {
       this.userId = params["userId"];
-      this.userManager.getSpecificUsersByUser(this.userId).subscribe(identities => {
-        this.identities = identities;
-        this.loading = false;
-      });
+      if(this.userId === undefined) {
+        this.userId = this.store.getPerunPrincipal().userId;
+        this.routeToAdminSection = false;
+      }
+      this.setAuthRights();
+      this.refreshTable();
     });
   }
 
@@ -52,6 +58,11 @@ export class UserSettingsServiceIdentitiesComponent implements OnInit {
     });
   }
 
+  setAuthRights() {
+    this.addIdentity = this.authResolver.isPerunAdmin();
+    this.removeIdentity = this.authResolver.isAuthorized('removeSpecificUserOwner_User_User_policy',[{id: this.userId, beanName: 'User'}]);
+  }
+
   onAdd(){
     const config = getDefaultDialogConfig();
     config.width = "1250px";
diff --git a/apps/admin-gui/src/app/users/users-routing.module.ts b/apps/admin-gui/src/app/users/users-routing.module.ts
index 283b9f8b7..bf295b288 100644
--- a/apps/admin-gui/src/app/users/users-routing.module.ts
+++ b/apps/admin-gui/src/app/users/users-routing.module.ts
@@ -10,6 +10,10 @@ import { UserSettingsAppConfigurationComponent } from './pages/user-detail-page/
 import { UserOverviewComponent } from './pages/user-detail-page/user-overview/user-overview.component';
 import { UserProfileComponent } from './components/user-profile/user-profile.component';
 import { UserRolesComponent } from './pages/user-detail-page/user-settings/user-roles/user-roles.component';
+import { UserSettingsServiceIdentitiesComponent } from './pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component';
+import { ServiceIdentityDetailPageComponent } from './pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component';
+import { ServiceIdentityOverviewComponent } from './pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component';
+import { UserSettingsAssociatedUsersComponent } from './pages/user-detail-page/user-settings/user-settings-associated-users/user-settings-associated-users.component';
 
 
 const routes: Routes = [
@@ -42,6 +46,11 @@ const routes: Routes = [
         component: UserRolesComponent,
         data: {animation: 'UserRolesPage'}
       },
+      {
+        path: 'service-identities',
+        component: UserSettingsServiceIdentitiesComponent,
+        data: {animation: 'UserServiceIdentities'}
+      },
       {
         path: 'settings',
         component: UserSettingsComponent,
@@ -64,6 +73,20 @@ const routes: Routes = [
         ]
       }
     ]
+  },
+  {
+    path: 'service-identities/:userId',
+    component: ServiceIdentityDetailPageComponent,
+    children: [
+      {
+        path: '',
+        component: ServiceIdentityOverviewComponent,
+      },
+      {
+        path: 'associated-users',
+        component: UserSettingsAssociatedUsersComponent
+      }
+    ]
   }
 ];
 
diff --git a/apps/admin-gui/src/app/users/users.module.ts b/apps/admin-gui/src/app/users/users.module.ts
index 8d875f138..849f018da 100644
--- a/apps/admin-gui/src/app/users/users.module.ts
+++ b/apps/admin-gui/src/app/users/users.module.ts
@@ -59,6 +59,8 @@ import { DashboardCardComponent } from './pages/user-detail-page/user-dashboard/
 import { DashboardRecentlyViewedButtonFieldComponent } from './pages/user-detail-page/user-dashboard/dashboard-recently-viewed-button-field/dashboard-recently-viewed-button-field.component';
 import { UserFacilitiesComponent } from './pages/user-detail-page/user-facilities/user-facilities.component';
 import { UserAccountsComponent } from './pages/user-detail-page/user-accounts/user-accounts.component';
+import { ServiceIdentityDetailPageComponent } from './pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-detail-page.component';
+import { ServiceIdentityOverviewComponent } from './pages/user-detail-page/user-settings/user-settings-service-identities/service-identity-detail-page/service-identity-overview/service-identity-overview.component';
 
 
 @NgModule({
@@ -82,6 +84,8 @@ import { UserAccountsComponent } from './pages/user-detail-page/user-accounts/us
     DashboardRecentlyViewedButtonFieldComponent,
     UserFacilitiesComponent,
     UserAccountsComponent,
+    ServiceIdentityDetailPageComponent,
+    ServiceIdentityOverviewComponent
   ],
   exports: [
     UserDetailPageComponent,
diff --git a/apps/admin-gui/src/app/vos/components/application-form-list/application-form-list.component.html b/apps/admin-gui/src/app/vos/components/application-form-list/application-form-list.component.html
index 5b8dae893..1120f4722 100644
--- a/apps/admin-gui/src/app/vos/components/application-form-list/application-form-list.component.html
+++ b/apps/admin-gui/src/app/vos/components/application-form-list/application-form-list.component.html
@@ -1,7 +1,7 @@
 <mat-spinner *ngIf="loading" class="ml-auto mr-auto">
 </mat-spinner>
 
-<div *ngIf="!loading" class="card mt-2">
+<div *ngIf="this.applicationFormItems.length !== 0 && !loading" class="card mt-2">
   <div class="card-body table-theme">
     <div class="overflow-auto">
       <table #table
diff --git a/apps/admin-gui/src/assets/i18n/en.json b/apps/admin-gui/src/assets/i18n/en.json
index 1225f8359..62ee24b00 100644
--- a/apps/admin-gui/src/assets/i18n/en.json
+++ b/apps/admin-gui/src/assets/i18n/en.json
@@ -879,7 +879,7 @@
       "TITLE": "User - ",
       "ROLES": "Roles",
       "GUI_CONFIG": "Gui configuration",
-      "SERVICE_IDENTITIES": "Service Identities",
+      "SERVICE_IDENTITIES": "Service Accounts",
       "IDENTITIES": "Identities",
       "PASSWORD_RESET": "Password reset",
       "FACILITIES": "Facilities",
@@ -1976,7 +1976,7 @@
       "TITLE": "Create service account",
       "CREATE": "Create",
       "CANCEL": "Cancel",
-      "CREATE_IDENTITY": "Create service identity",
+      "CREATE_IDENTITY": "Create service account",
       "NAME": "Account name",
       "EMAIL": "Email",
       "NAMESPACE": "Namespace",
@@ -2196,10 +2196,10 @@
         "SUCCESS_SAVE": "Attributes saved successfully"
       },
       "SERVICE_IDENTITIES": {
-        "TITLE": "Service identities",
+        "TITLE": "Service accounts",
         "CREATE": "Add",
         "DELETE": "Remove",
-        "NO_IDENTITIES": "No service identities assigned."
+        "NO_IDENTITIES": "No service accounts assigned."
       },
       "GUI_CONFIG": {
         "PREF_TABLE_PAGE_SIZE": "Preferred table page size",
-- 
GitLab


From 4d55397923822b93123efaf7876372cc9089a168 Mon Sep 17 00:00:00 2001
From: xkureck <luckureckova@gmail.com>
Date: Mon, 18 Oct 2021 16:50:42 +0200
Subject: [PATCH 2/2] feat(admin): new section - Service account in My profile
 section

* fix ng lint problems
---
 apps/admin-gui/src/app/admin/admin-routing.module.ts | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/apps/admin-gui/src/app/admin/admin-routing.module.ts b/apps/admin-gui/src/app/admin/admin-routing.module.ts
index 3283dfc22..ecfec210c 100644
--- a/apps/admin-gui/src/app/admin/admin-routing.module.ts
+++ b/apps/admin-gui/src/app/admin/admin-routing.module.ts
@@ -19,11 +19,7 @@ import {AdminUserDetailPageComponent} from './pages/admin-user-detail-page/admin
 import {UserOverviewComponent} from '../users/pages/user-detail-page/user-overview/user-overview.component';
 import {UserOrganizationsComponent} from '../users/pages/user-detail-page/user-organizations/user-organizations.component';
 import {UserGroupsComponent} from '../users/pages/user-detail-page/user-groups/user-groups.component';
-import {UserSettingsComponent} from '../users/pages/user-detail-page/user-settings/user-settings.component';
 import {UserAttributesComponent} from '../users/pages/user-detail-page/user-attributes/user-attributes.component';
-import {
-  UserSettingsOverviewComponent
-} from '../users/pages/user-detail-page/user-settings/user-settings-overview/user-settings-overview.component';
 import { AdminExtSourcesComponent } from './pages/admin-page/admin-ext-sources/admin-ext-sources.component';
 import { UserRolesComponent } from '../users/pages/user-detail-page/user-settings/user-roles/user-roles.component';
 import { UserSettingsServiceIdentitiesComponent } from '../users/pages/user-detail-page/user-settings/user-settings-service-identities/user-settings-service-identities.component';
-- 
GitLab