Skip to content

Commit

Permalink
SHIBUI-1058 Added user authorization for dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Jan 18, 2019
1 parent 1ecda3f commit 323f6e0
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 28 deletions.
3 changes: 2 additions & 1 deletion ui/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<i class="fa fa-cubes fa-fw" aria-hidden="true"></i>
&nbsp;
<translate-i18n key="label.metadata-provider">Metadata Provider</translate-i18n>
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -24,6 +25,7 @@ export class AppComponent implements OnInit {
formatted$: Observable<string>;
today = new Date();
year = new Date().getFullYear();
isAdmin$: Observable<boolean>;

brand: Brand = brand;

Expand All @@ -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()));
}
Expand Down
21 changes: 12 additions & 9 deletions ui/src/app/core/action/user.action.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down
31 changes: 27 additions & 4 deletions ui/src/app/core/effect/user.effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -23,10 +34,22 @@ export class UserEffects {
)
);

@Effect()
loadCurrentUser$ = this.actions$.pipe(
ofType<UserLoadRequestAction>(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;
})
Expand Down
9 changes: 4 additions & 5 deletions ui/src/app/core/model/user.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
export interface User {
id: string;
username: string;
role: string;
name: {
first: string,
last: string
};
firstName: string;
lastName: string;
emailAddress: string;
}
2 changes: 2 additions & 0 deletions ui/src/app/core/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
15 changes: 8 additions & 7 deletions ui/src/app/core/reducer/user.reducer.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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,
Expand Down
15 changes: 15 additions & 0 deletions ui/src/app/core/service/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -17,4 +18,18 @@ export class UserService {
`${this.base}/supportedRoles`
);
}

getCurrentUser(): Observable<User> {
return this.http.get<User>(
`${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 */
4 changes: 2 additions & 2 deletions ui/src/app/dashboard/container/dashboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
Metadata Sources
</a>
</li>
<li class="nav-item">
<li class="nav-item" *ngIf="isAdmin$ | async">
<a class="nav-link"
[routerLink]="['./', 'metadata', 'manager', 'providers']"
routerLinkActive="active"
translate="label.metadata-providers">
Metadata Providers
</a>
</li>
<li class="nav-item">
<li class="nav-item" *ngIf="isAdmin$ | async">
<a class="nav-link"
[routerLink]="['./', 'users', 'admin']"
routerLinkActive="active"
Expand Down
9 changes: 9 additions & 0 deletions ui/src/app/dashboard/container/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Store } from '@ngrx/store';

import * as fromRoot from '../../app.reducer';
import * as fromCore from '../../core/reducer';
import { Observable } from 'rxjs';
import { User } from '../../core/model/user';
import { map } from 'rxjs/operators';

@Component({
selector: 'dashboard-page',
Expand All @@ -11,8 +15,13 @@ import * as fromRoot from '../../app.reducer';
})
export class DashboardPageComponent {

user$: Observable<User>;
isAdmin$: Observable<boolean>;

constructor(
private store: Store<fromRoot.State>
) {
this.user$ = this.store.select(fromCore.getUser);
this.isAdmin$ = this.store.select(fromCore.isCurrentUserAdmin);
}
}
3 changes: 3 additions & 0 deletions ui/src/app/dashboard/dashboard.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { I18nModule } from '../i18n/i18n.module';
import { CustomWidgetRegistry } from '../schema-form/registry';
Expand All @@ -8,8 +9,10 @@ import { DashboardRoutingModule } from './dashboard.routing';
import { MetadataModule } from '../metadata/metadata.module';
import { UserModule } from '../user/user.module';


@NgModule({
imports: [
CommonModule,
DashboardRoutingModule,
MetadataModule,
UserModule,
Expand Down

0 comments on commit 323f6e0

Please sign in to comment.