Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 2c5da396

Přidáno uživatelem Jakub Hlaváč před téměř 4 roky(ů)

Re #8469 - Improvment security - implementace

  • authGuard and roleGuard final version
    + usage of localStorage for fields
    + loading properties form cookies to state

Zobrazit rozdíly:

src/app/administration/administration.module.ts
1
import { NgModule } from '@angular/core';
2
import { CommonModule } from '@angular/common';
3
import { AdministrationComponent } from './components/administration.component';
4
import {NavBarModule} from '../shared/nav-bar/nav-bar.module';
5

  
6

  
7

  
8
@NgModule({
9
  declarations: [AdministrationComponent],
10
  imports: [
11
    CommonModule,
12
    NavBarModule
13
  ]
14
})
15
export class AdministrationModule { }
src/app/administration/components/administration.component.html
1
<app-nav-bar></app-nav-bar>
2

  
3
<p>administration works!</p>
src/app/administration/components/administration.component.ts
1
import { Component, OnInit } from '@angular/core';
2

  
3
@Component({
4
  selector: 'app-administration',
5
  templateUrl: './administration.component.html',
6
  styleUrls: ['./administration.component.scss']
7
})
8
export class AdministrationComponent implements OnInit {
9

  
10
  constructor() { }
11

  
12
  ngOnInit(): void {
13
  }
14

  
15
}
src/app/app-routing.module.ts
2 2
import {RouterModule, Routes} from '@angular/router';
3 3
import {LoginComponent} from './login/components/login.component';
4 4
import {DashboardComponent} from './dashboard/components/dashboard.component';
5
import {AuthGuard} from './auth/guards/auth.guard';
6
import {RoleGuard} from './auth/guards/role.guard';
7
import {AdministrationComponent} from './administration/components/administration.component';
5 8

  
6 9
const routes: Routes = [
7 10
  {
8
    // canActivate: [AuthGuard],
9 11
    path: '',
10 12
    redirectTo: 'login',
11 13
    pathMatch: 'full'
12 14
  }, {
13
    // canActivate: [AuthGuard, RoleGuard],
15
    canActivate: [AuthGuard],
14 16
    path: 'dashboard',
15 17
    component: DashboardComponent,
18
    pathMatch: 'full'
19
  },
20
  {
21
    canActivate: [AuthGuard, RoleGuard],
22
    path: 'administration',
23
    component: AdministrationComponent,
16 24
    pathMatch: 'full',
17 25
    data: {
18
      expectedRole: ['ROLE_ADMIN']
26
      expectedRole: ['1']
19 27
    }
20 28
  },{
21 29
    path: 'login',
src/app/app.module.ts
9 9
import {AuthModule} from './auth/auth.module';
10 10
import {LoginModule} from './login/login.module';
11 11
import {DashboardModule} from './dashboard/dashboard.module';
12
import {AdministrationModule} from './administration/administration.module';
12 13

  
13 14
@NgModule({
14 15
  declarations: [
......
22 23
    NavBarModule,
23 24
    AuthModule,
24 25
    LoginModule,
25
    DashboardModule
26
    DashboardModule,
27
    AdministrationModule
26 28
  ],
27 29
  providers: [],
28 30
  bootstrap: [AppComponent]
src/app/auth/guards/auth.guard.ts
22 22
    next: ActivatedRouteSnapshot,
23 23
    state: RouterStateSnapshot
24 24
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
25
    if (!this.authService.getIsLoggedIn()) {
25
    if (!this.authService.getUser()) {
26 26
      this.router.navigate(['']);
27 27
    }
28
    return this.authService.getIsLoggedIn();
28
    return !!this.authService.getUser();
29 29
  }
30 30
}
src/app/auth/guards/role.guard.ts
23 23
    state: RouterStateSnapshot
24 24
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
25 25
    const expectedRole: string[] = routeSnapshot.data.expectedRole;
26
    if (expectedRole.map(x => this.authService.getUserRoles().some(userRole => userRole.group_name === x))) {
26
    if (expectedRole.includes(this.authService.getUser().userInfo.rights.toString())) {
27
      console.log('You have enough rights!');
27 28
     return true;
28 29
    }
30
    console.log('You are not allowed to be here!');
29 31
    this.router.navigate(['']);
30 32
    return false;
31 33
  }
src/app/auth/interceptors/auth.interceptor.ts
8 8
import {Observable, throwError, of} from 'rxjs';
9 9

  
10 10
import {catchError} from 'rxjs/operators';
11
import {UserState} from '../states/user.state';
11
import {AuthService} from '../services/auth.service';
12
import {CookieService} from 'ngx-cookie-service';
13
import {GlobalVariable} from '../../globals';
12 14

  
13 15
@Injectable()
14 16
export class AuthInterceptor implements HttpInterceptor {
15 17

  
16 18
  constructor(
17
    private userState: UserState
19
    private authService: AuthService,
20
    private cookieService: CookieService
18 21
  ) {
19 22
  }
20 23

  
21 24
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
22 25

  
23
    if (!sessionStorage.getItem('sessionid') && !request.url.includes('ControllerServlet')) {
24
       return of(null);
26
    if (!this.cookieService.get(GlobalVariable.SESSION_ID) && !request.url.includes('ControllerServlet')) {
27
      console.log('No sessionid!');
28
      return of(null);
25 29
    }
26 30

  
27 31
    if (!request.url.includes('ControllerServlet')){
28 32
      request = request.clone({
29 33
        setParams: {
30
          user: sessionStorage.getItem('userName')
34
          user: localStorage.getItem(GlobalVariable.USER_NAME)
31 35
        }
32 36
      });
33 37
    }
34 38

  
39
    console.log('Sending request!');
35 40
    return next.handle(request)
36 41
      .pipe(
37 42
        catchError(err => {
38
          if ((err instanceof HttpErrorResponse && err.status === 504 || err.status === 502 || err.status === 0)) {
43
          if ((err instanceof HttpErrorResponse && err.status === 504 || err.status === 502 || err.status === 0 || err.status === 500)) {
39 44
            return this.handleError(request, next);
40 45
          } else {
41 46
            return throwError(err);
......
45 50
  }
46 51

  
47 52
  handleError(request: HttpRequest<any>, next: HttpHandler) {
53
    this.authService.doLogout();
48 54
    return of(null);
49 55
  }
50 56
}
src/app/auth/models/user.ts
1
/* tslint:disable */
2
/* eslint-disable */
3
import {UserInfo} from '../../shared/api/endpoints/models/user-info';
4

  
5
export interface User {
6
  userInfo?: UserInfo;
7
  isLoggedIn?: boolean;
8
  userName?: string
9
}
src/app/auth/services/auth.service.ts
1 1
import {Injectable} from '@angular/core';
2 2
import {HttpClient, HttpResponse} from '@angular/common/http';
3
import {Observable, of, pipe} from 'rxjs';
3
import {Observable, of} from 'rxjs';
4 4
import {catchError, mapTo, tap} from 'rxjs/operators';
5 5
import {Router} from '@angular/router';
6 6
import {CookieService} from 'ngx-cookie-service';
7 7
import {UserState} from '../states/user.state';
8 8
import {LoginService} from '../../shared/api/endpoints/services/login.service';
9 9
import {UserInfo} from '../../shared/api/endpoints/models/user-info';
10
import {Group} from '../../shared/api/endpoints/models/group';
10
import {User} from '../models/user';
11
import {GlobalVariable} from '../../globals';
11 12

  
12 13
@Injectable({
13 14
  providedIn: 'root'
......
23 24
  ) {
24 25
  }
25 26

  
27
  setFromCookie() {
28
    const user: User = {
29
      userInfo: {
30
        rights: JSON.parse(localStorage.getItem(GlobalVariable.RIGHTS)),
31
        language: this.cookieService.get(GlobalVariable.LANGUAGE),
32
        audio: JSON.parse(this.cookieService.get(GlobalVariable.AUDIO)),
33
        sessionid: this.cookieService.get(GlobalVariable.SESSION_ID)
34
      },
35
      userName: localStorage.getItem(GlobalVariable.USER_NAME),
36
      isLoggedIn: true
37
    }
38
    this.userState.setUser(user);
39
  }
40

  
41
  getUser() {
42
    console.log('Auth Service', this.userState.getUser());
43
    if (!this.userState.getUser() && this.cookieService.get(GlobalVariable.SESSION_ID)) {
44
      console.log('Session in cookie!');
45
      this.setFromCookie();
46
    }
47
    return this.userState.getUser();
48
  }
49

  
50
  getUserState(): Observable<User> {
51
    return this.userState.getUser$();
52
  }
53

  
26 54
  doLogin(loginInput): Observable<boolean> {
27 55
    return this.loginService.login$Response(loginInput)
28 56
      .pipe(
29
        tap((userInfo: HttpResponse<UserInfo>) => this.setUserFromResponse(userInfo.body, loginInput)),
57
        tap((userInfo: HttpResponse<UserInfo>) => this.setUserFromResponse(userInfo.body, loginInput.username)),
30 58
        mapTo(true),
31 59
        catchError(() => {
32 60
          return of<boolean>(false);
......
34 62
      );
35 63
  }
36 64

  
37
  getUserState(): Observable<UserInfo> {
38
    return this.userState.getUser$();
39
  }
40

  
41
  getIsLoggedIn(): boolean {
42
    return this.userState.getLoggedIn();
43
  }
44

  
45
  setUserFromResponse(userInfo: UserInfo, loginInput): UserInfo {
46
    this.userState.setUser(userInfo);
47
    this.userState.setLoggedIn(true);
48
    sessionStorage.setItem('userName', loginInput.username)
49
    sessionStorage.setItem('sessionid', userInfo.sessionid)
50
    sessionStorage.setItem('language', userInfo.language)
51
    sessionStorage.setItem('audio', String(userInfo.audio))
52
    this.cookieService.set('userName', loginInput.username)
65
  setUserFromResponse(userInfo: UserInfo, username): UserInfo {
66
    console.log('Setting user from login!');
67
    this.userState.setUser({
68
      userInfo,
69
      isLoggedIn: true,
70
      userName: username
71
    });
72
    this.setSessionStorage(userInfo, username);
53 73
    return userInfo;
54 74
  }
55 75

  
56 76
  doLogout() {
77
    this.userState.setUser(null);
57 78
    this.cookieService.deleteAll();
79
    localStorage.clear();
80
    this.router.navigate(['/login']);
58 81
  }
59 82

  
60
  getUserRoles(): Group[] {
61
    return this.userState.getUserGroups();
83
  setSessionStorage(userInfo: UserInfo, username) {
84
    localStorage.setItem(GlobalVariable.USER_NAME, username)
85
    // TODO - get rights from response
86
    // localStorage.setItem('rights', userInfo.rights.toString());
87
    localStorage.setItem(GlobalVariable.RIGHTS, '1');
62 88
  }
63 89
}
src/app/auth/states/user.state.ts
1 1
import {Injectable} from '@angular/core';
2 2
import {BehaviorSubject, Observable} from 'rxjs';
3
import {Group, UserInfo} from '../../shared/api/endpoints/models';
3
import {User} from '../models/user';
4 4

  
5 5
@Injectable({
6 6
  providedIn: 'root'
7 7
})
8 8
export class UserState {
9
  private userState$: BehaviorSubject<UserInfo> = new BehaviorSubject<UserInfo>(null);
10
  private isLoggedAdmin$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
11
  private isLoggedIn$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
12
  private userGroups$: BehaviorSubject<Group[]> = new BehaviorSubject<Group[]>(null);
9
  private userState$: BehaviorSubject<User> = new BehaviorSubject<User>(null);
13 10

  
14
  constructor() {
15
  }
11
  constructor() {}
16 12

  
17
  setUser(user: UserInfo): void {
13
  setUser(user: User): void {
18 14
    this.userState$.next(user);
19 15
  }
20 16

  
21
  getUser(): UserInfo {
22
    return this.userState$.getValue();
23
  }
24

  
25
  getUser$(refresh: boolean = false): Observable<UserInfo> {
26
    /*if (this.userState$.getValue() === null || refresh){
27
      this.accountService.getAccountUsingGET('body')
28
        .subscribe(res => this.setUser(res));
29
    }*/
30
    return this.userState$.asObservable();
31
  }
32

  
33
  setLoggedAdmin(adminLogged: boolean): void {
34
    this.isLoggedAdmin$.next(adminLogged);
35
  }
36

  
37
  getLoggedAdmin(): boolean {
38
    return this.isLoggedAdmin$.getValue();
17
  setLoggedIn(loggedIn: boolean) {
18
    this.userState$.next({...this.userState$.getValue(), isLoggedIn: loggedIn})
39 19
  }
40 20

  
41
  setLoggedIn(loggedIn: boolean): void {
42
    this.isLoggedIn$.next(loggedIn);
21
  getUser(): User {
22
    return this.userState$.getValue();
43 23
  }
44 24

  
45
  getLoggedIn$(): Observable<boolean> {
46
    return this.isLoggedIn$.asObservable();
25
  getUser$(refresh: boolean = false): Observable<User> {
26
    return this.userState$.asObservable();
47 27
  }
48 28

  
49 29
  getLoggedIn(): boolean {
50
    return this.isLoggedIn$.getValue();
51
  }
52

  
53
  setUserGroups(userGroups: Group[]): void {
54
    this.userGroups$.next(userGroups);
55
  }
56

  
57
  getUserGroups$(): Observable<Group[]> {
58
    return this.userGroups$.asObservable();
59
  }
60

  
61
  getUserGroups(): Group[] {
62
    return this.userGroups$.getValue();
30
    return this.userState$.getValue().isLoggedIn;
63 31
  }
64 32
}
src/app/dashboard/components/dashboard.component.ts
29 29
  }
30 30

  
31 31
  getGroups() {
32
    console.log('Get Groups');
32 33
    this.groupService.getGroups({Operation: 'GetGroups'}).pipe(
33 34
      tap(data => this.groups = data)
34 35
    ).toPromise();
src/app/globals.ts
1
export const GlobalVariable = Object.freeze({
2
  SESSION_ID: 'sessionid',
3
  USER_NAME: 'userName',
4
  RIGHTS: 'rights',
5
  LANGUAGE: 'language',
6
  AUDIO: 'audio'
7
});
src/app/login/components/login.component.ts
4 4
import {of, Subscription} from 'rxjs';
5 5
import {AuthService} from '../../auth/services/auth.service';
6 6
import {Router} from '@angular/router';
7
import {UserState} from '../../auth/states/user.state';
8 7

  
9 8
@Component({
10 9
  selector: 'app-login',
......
19 18
  constructor(
20 19
    private formBuilder: FormBuilder,
21 20
    private authService: AuthService,
22
    private router: Router,
23
    private userState: UserState
21
    private router: Router
24 22
  ) {
25 23
  }
26 24

  
......
29 27
      username: ['', [Validators.required]],
30 28
      password: ['', Validators.required]
31 29
    });
30
    this.userRedirect();
32 31
  }
33 32

  
34 33
  doLogin(): void {
......
39 38
      })
40 39
        .pipe(
41 40
          switchMap(res => {
41
            console.log(res);
42 42
            if (res) {
43
              console.log('Login getUserState');
43 44
              return this.authService.getUserState();
44 45
            } else {
45 46
              return of(false);
......
47 48
          })
48 49
        ).subscribe(
49 50
          res => {
51
            console.log(res);
50 52
            if (res) {
51
              console.log(res);
52
              this.userState.setLoggedIn(true);
53 53
              this.subscription[2].unsubscribe();
54 54
              this.router.navigate(['/dashboard'])
55 55
            }
......
57 57
        );
58 58
    }
59 59
  }
60

  
61
  userRedirect(): void {
62
    console.log('Login redirect');
63
    if (this.authService.getUser()){
64
      console.log('Redirect to dashboard!');
65
      this.router.navigate(['/dashboard']);
66
    }
67
  }
60 68
}
src/app/shared/nav-bar/components/nav-bar.component.html
20 20
    <div class="navbar-collapse collapse w-100 order-3 dual-collapse2">
21 21
      <ul class="navbar-nav ms-auto">
22 22
        <li class="nav-item">
23
          <a class="nav-link" href="#">ASWI</a>
23
          <a class="nav-link" href="#">{{loggedUser?.userName.toUpperCase()}}</a>
24 24
        </li>
25 25
        <li class="divider-vertical"></li>
26 26
        <li class="nav-item">
src/app/shared/nav-bar/components/nav-bar.component.ts
1
import {Component, OnInit} from '@angular/core';
1
import {Component, OnDestroy, OnInit} from '@angular/core';
2 2
import {AuthService} from '../../../auth/services/auth.service';
3
import {Router} from '@angular/router';
4
import {UserState} from '../../../auth/states/user.state';
3
import {User} from '../../../auth/models/user';
4
import {Subscription} from 'rxjs';
5 5

  
6 6
@Component({
7 7
  selector: 'app-nav-bar',
8 8
  templateUrl: './nav-bar.component.html',
9 9
  styleUrls: ['./nav-bar.component.scss']
10 10
})
11
export class NavBarComponent implements OnInit {
11
export class NavBarComponent implements OnInit, OnDestroy {
12 12

  
13
  loggedUser: User;
14
  subscription: Subscription[] = [];
13 15
  constructor(
14
    private authService: AuthService,
15
    private router: Router,
16
    private userState: UserState
16
    private authService: AuthService
17 17
  ) {
18 18
  }
19 19

  
20 20
  ngOnInit(): void {
21
    this.setUser();
22
  }
23

  
24
  setUser(){
25
    this.authService.getUserState().subscribe(res => {
26
      if(res){
27
        this.loggedUser = res;
28
      }
29
    });
21 30
  }
22 31

  
23 32
  logOut(): void {
24
    this.userState.setLoggedIn(false);
25 33
    this.authService.doLogout();
26 34
  }
35

  
36
  ngOnDestroy(): void {
37
    this.subscription.forEach(subs => subs.unsubscribe());
38
  }
27 39
}
src/app/shared/services/logger.service.ts
1
import {Injectable} from '@angular/core';
2

  
3
@Injectable({
4
  providedIn: 'root'
5
})
6
export class LoggerService {
7

  
8
  isLoggingEnabled = true;
9

  
10
  consoleLog(args){
11
    console.log(args);
12
  }
13
}

Také k dispozici: Unified diff