From 323f6e0cab5234d1503efd4b9f74b7eeded7d729 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 18 Jan 2019 12:31:24 -0700 Subject: [PATCH 01/46] SHIBUI-1058 Added user authorization for dashboard --- ui/src/app/app.component.html | 3 +- ui/src/app/app.component.ts | 4 +++ ui/src/app/core/action/user.action.ts | 21 +++++++------ ui/src/app/core/effect/user.effect.ts | 31 ++++++++++++++++--- ui/src/app/core/model/user.ts | 9 +++--- ui/src/app/core/reducer/index.ts | 2 ++ ui/src/app/core/reducer/user.reducer.ts | 15 ++++----- ui/src/app/core/service/user.service.ts | 15 +++++++++ .../container/dashboard.component.html | 4 +-- .../container/dashboard.component.ts | 9 ++++++ ui/src/app/dashboard/dashboard.module.ts | 3 ++ 11 files changed, 88 insertions(+), 28 deletions(-) diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index fe988c62f..f29cfd620 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -34,7 +34,8 @@ routerLink="/metadata/provider/wizard" routerLinkActive="active" [attr.aria-label]="'action.add-new-provider' | translate" - role="button"> + role="button" + *ngIf="isAdmin$ | async">   Metadata Provider diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index f0ac72720..57119404d 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -11,6 +11,7 @@ import { I18nService } from './i18n/service/i18n.service'; import { SetLocale } from './i18n/action/message.action'; import { brand } from './app.brand'; import { Brand } from './core/model/brand'; +import { UserLoadRequestAction } from './core/action/user.action'; @Component({ selector: 'app-root', @@ -24,6 +25,7 @@ export class AppComponent implements OnInit { formatted$: Observable; today = new Date(); year = new Date().getFullYear(); + isAdmin$: Observable; brand: Brand = brand; @@ -35,9 +37,11 @@ export class AppComponent implements OnInit { ) { this.version$ = this.store.select(fromRoot.getVersionInfo); this.formatted$ = this.version$.pipe(map(this.formatter)); + this.isAdmin$ = this.store.select(fromRoot.isCurrentUserAdmin); } ngOnInit(): void { + this.store.dispatch(new UserLoadRequestAction()); this.store.dispatch(new VersionInfoLoadRequestAction()); this.store.dispatch(new SetLocale(this.i18nService.getCurrentLocale())); } diff --git a/ui/src/app/core/action/user.action.ts b/ui/src/app/core/action/user.action.ts index 2aa273f9a..8ab396e12 100644 --- a/ui/src/app/core/action/user.action.ts +++ b/ui/src/app/core/action/user.action.ts @@ -1,39 +1,42 @@ import { Action } from '@ngrx/store'; import { User } from '../model/user'; -export const USER_LOAD_REQUEST = '[Auth] User REQUEST'; -export const USER_LOAD_SUCCESS = '[Auth] User SUCCESS'; -export const USER_LOAD_ERROR = '[Auth] User ERROR'; -export const REDIRECT = '[Auth] User Redirect'; + +export enum CurrentUserActionTypes { + USER_LOAD_REQUEST = '[Current User] Load User Request', + USER_LOAD_SUCCESS = '[Current User] Load User Success', + USER_LOAD_ERROR = '[Current User] Load User Fail', + REDIRECT = '[Current User] Redirect' +} /** * Add User to Collection Actions */ export class UserLoadRequestAction implements Action { - readonly type = USER_LOAD_REQUEST; + readonly type = CurrentUserActionTypes.USER_LOAD_REQUEST; constructor() { } } export class UserLoadSuccessAction implements Action { - readonly type = USER_LOAD_SUCCESS; + readonly type = CurrentUserActionTypes.USER_LOAD_SUCCESS; constructor(public payload: User) { } } export class UserLoadErrorAction implements Action { - readonly type = USER_LOAD_ERROR; + readonly type = CurrentUserActionTypes.USER_LOAD_ERROR; constructor(public payload: { message: string }) { } } export class UserRedirect implements Action { - readonly type = REDIRECT; + readonly type = CurrentUserActionTypes.REDIRECT; constructor(public payload: string) { } } -export type Actions = +export type CurrentUserActionsUnion = | UserLoadRequestAction | UserLoadSuccessAction | UserLoadErrorAction diff --git a/ui/src/app/core/effect/user.effect.ts b/ui/src/app/core/effect/user.effect.ts index 095267bff..5417fa999 100644 --- a/ui/src/app/core/effect/user.effect.ts +++ b/ui/src/app/core/effect/user.effect.ts @@ -4,8 +4,19 @@ import { Effect, Actions, ofType } from '@ngrx/effects'; import { of } from 'rxjs'; import { map, tap, catchError, switchMap } from 'rxjs/operators'; -import * as user from '../action/user.action'; -import { LoadRoleRequest, LoadRoleFail, LoadRoleSuccess, ConfigurationActionTypes } from '../action/configuration.action'; +import { + LoadRoleRequest, + LoadRoleFail, + LoadRoleSuccess, + ConfigurationActionTypes +} from '../action/configuration.action'; +import { + UserLoadRequestAction, + CurrentUserActionTypes, + UserLoadSuccessAction, + UserLoadErrorAction, + UserRedirect +} from '../action/user.action'; import { UserService } from '../service/user.service'; @Injectable() @@ -23,10 +34,22 @@ export class UserEffects { ) ); + @Effect() + loadCurrentUser$ = this.actions$.pipe( + ofType(CurrentUserActionTypes.USER_LOAD_REQUEST), + switchMap(() => + this.userService.getCurrentUser() + .pipe( + map(user => new UserLoadSuccessAction(user)), + catchError(error => of(new UserLoadErrorAction(error))) + ) + ) + ); + @Effect({dispatch: false}) redirect$ = this.actions$.pipe( - ofType(user.REDIRECT), - map((action: user.UserRedirect) => action.payload), + ofType(CurrentUserActionTypes.REDIRECT), + map((action: UserRedirect) => action.payload), tap(path => { window.location.href = path; }) diff --git a/ui/src/app/core/model/user.ts b/ui/src/app/core/model/user.ts index 37d05212e..27375c23e 100644 --- a/ui/src/app/core/model/user.ts +++ b/ui/src/app/core/model/user.ts @@ -1,8 +1,7 @@ export interface User { - id: string; + username: string; role: string; - name: { - first: string, - last: string - }; + firstName: string; + lastName: string; + emailAddress: string; } diff --git a/ui/src/app/core/reducer/index.ts b/ui/src/app/core/reducer/index.ts index 9d9f91dec..edf4c41b7 100644 --- a/ui/src/app/core/reducer/index.ts +++ b/ui/src/app/core/reducer/index.ts @@ -41,3 +41,5 @@ export const getVersionError = createSelector(getVersionState, fromVersion.getVe export const getConfigState = createSelector(getCoreFeature, getConfigStateFn); export const getRoles = createSelector(getConfigState, fromConfig.getRoles); + +export const isCurrentUserAdmin = createSelector(getUser, user => user.role === 'ROLE_ADMIN'); diff --git a/ui/src/app/core/reducer/user.reducer.ts b/ui/src/app/core/reducer/user.reducer.ts index b18810b2c..2510d5c5e 100644 --- a/ui/src/app/core/reducer/user.reducer.ts +++ b/ui/src/app/core/reducer/user.reducer.ts @@ -1,7 +1,8 @@ -import { createSelector, createFeatureSelector } from '@ngrx/store'; import { User } from '../model/user'; -import * as user from '../action/user.action'; -import * as fromRoot from '../../core/reducer'; +import { + CurrentUserActionTypes, + CurrentUserActionsUnion +} from '../action/user.action'; export interface UserState { fetching: boolean; @@ -18,20 +19,20 @@ export const initialState: UserState = { error: null }; -export function reducer(state = initialState, action: user.Actions): UserState { +export function reducer(state = initialState, action: CurrentUserActionsUnion): UserState { switch (action.type) { - case user.USER_LOAD_REQUEST: { + case CurrentUserActionTypes.USER_LOAD_REQUEST: { return Object.assign({}, state, { fetching: true }); } - case user.USER_LOAD_SUCCESS: { + case CurrentUserActionTypes.USER_LOAD_SUCCESS: { return Object.assign({}, state, { fetching: false, user: action.payload }); } - case user.USER_LOAD_ERROR: { + case CurrentUserActionTypes.USER_LOAD_ERROR: { return Object.assign({}, state, { fetching: false, user: null, diff --git a/ui/src/app/core/service/user.service.ts b/ui/src/app/core/service/user.service.ts index e44e16bce..3a72d1a4a 100644 --- a/ui/src/app/core/service/user.service.ts +++ b/ui/src/app/core/service/user.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { User } from '../model/user'; import { HttpClient } from '@angular/common/http'; +import { catchError } from 'rxjs/operators'; @Injectable() export class UserService { @@ -17,4 +18,18 @@ export class UserService { `${this.base}/supportedRoles` ); } + + getCurrentUser(): Observable { + return this.http.get( + `${this.base}/user` + ).pipe( + catchError(err => of({ + username: 'abc123', + firstName: 'Foo', + lastName: 'Bar', + role: 'ROLE_USER', + emailAddress: 'foo@unicon.net' + } as User)) + ); + } } /* istanbul ignore next */ diff --git a/ui/src/app/dashboard/container/dashboard.component.html b/ui/src/app/dashboard/container/dashboard.component.html index 0a9e4319f..09c647146 100644 --- a/ui/src/app/dashboard/container/dashboard.component.html +++ b/ui/src/app/dashboard/container/dashboard.component.html @@ -8,7 +8,7 @@ Metadata Sources - -