assign trainers to user; add email to jwt token
This commit is contained in:
5
customer/app/package-lock.json
generated
5
customer/app/package-lock.json
generated
@@ -6823,6 +6823,11 @@
|
||||
"set-immediate-shim": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"jwt-decode": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
|
||||
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
|
||||
},
|
||||
"karma": {
|
||||
"version": "6.3.4",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.4.tgz",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"@ngxs/logger-plugin": "^3.7.2",
|
||||
"@ngxs/store": "^3.7.2",
|
||||
"bootstrap": "^5.1.1",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"moment": "^2.24.0",
|
||||
"ngx-bootstrap": "^5.0.0",
|
||||
"ngx-toastr": "^14.1.3",
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http";
|
||||
import { Observable } from "rxjs";
|
||||
import {Injectable} from "@angular/core";
|
||||
import {HttpInterceptor, HttpRequest, HttpHandler, HttpEvent} from "@angular/common/http";
|
||||
import {Observable} from "rxjs";
|
||||
import {Store} from "@ngxs/store";
|
||||
import {AppState} from "../state/app.state";
|
||||
|
||||
/*
|
||||
The JWT interceptor intercepts the incoming requests from the application/user and adds JWT token to the request's Authorization header, only if the user is logged in.
|
||||
|
||||
This JWT token in the request header is required to access the SECURE END API POINTS on the server
|
||||
This JWT token in the request header is required to access the SECURE END API POINTS on the server
|
||||
*/
|
||||
|
||||
@Injectable()
|
||||
export class JwtInterceptor implements HttpInterceptor{
|
||||
constructor(){}
|
||||
export class JwtInterceptor implements HttpInterceptor {
|
||||
constructor(private store: Store) {
|
||||
}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
|
||||
// check if the current user is logged in
|
||||
// if the user making the request is logged in, he will have JWT token in it's local storage, which is set by Authorization Service during login process
|
||||
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||
if(currentUser && currentUser.token){
|
||||
// clone the incoming request and add JWT token in the cloned request's Authorization Header
|
||||
request = request.clone({
|
||||
setHeaders: {
|
||||
Authorization: `Bearer ${currentUser.token}`
|
||||
}
|
||||
});
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
// check if the current user is logged in
|
||||
// if the user making the request is logged in, he will have JWT token in it's local storage, which is set by Authorization Service during login process
|
||||
// let currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||
|
||||
const token = this.store.selectSnapshot<string>(AppState.getToken);
|
||||
|
||||
if (token) {
|
||||
// clone the incoming request and add JWT token in the cloned request's Authorization Header
|
||||
request = request.clone({
|
||||
setHeaders: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
|
||||
// handle any other requests which went unhandled
|
||||
return next.handle(request);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// handle any other requests which went unhandled
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,11 +67,11 @@ export class FitNavigationComponent implements OnInit {
|
||||
if ( item.roles && item.roles.length ){
|
||||
let firstRole = item.roles[0];
|
||||
if ( firstRole == '!'){
|
||||
return !this.authenticationService.user.value;
|
||||
return !this.authenticationService.isLoggedIn();
|
||||
}else if ( firstRole == '*'){
|
||||
return true;
|
||||
}else if ( firstRole == '@'){
|
||||
return this.authenticationService.user.value;
|
||||
return this.authenticationService.isLoggedIn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<fit-navigation></fit-navigation>
|
||||
<div class="container " >
|
||||
<div class="row ">
|
||||
<div class="col-12">Bejelentkezve: {{username | async}}</div>
|
||||
</div>
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {Select} from "@ngxs/store";
|
||||
import {AppState} from "../../state/app.state";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
selector: 'app-secured-layout',
|
||||
@@ -6,6 +9,7 @@ import { Component, OnInit } from '@angular/core';
|
||||
styleUrls: ['./secured-layout.component.scss']
|
||||
})
|
||||
export class SecuredLayoutComponent implements OnInit {
|
||||
@Select(AppState.getUsername) public username: Observable<string>;
|
||||
|
||||
constructor() { }
|
||||
|
||||
|
||||
@@ -1,57 +1,71 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { map } from 'rxjs/operators';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {catchError, map} from 'rxjs/operators';
|
||||
import {Endpoints} from "./endpoints";
|
||||
import {BehaviorSubject} from "rxjs";
|
||||
import { throwError} from "rxjs";
|
||||
import {PasswordChangeRequest} from "../app.types";
|
||||
import jwtDecode, {JwtPayload} from "jwt-decode";
|
||||
import {Store} from "@ngxs/store";
|
||||
import {LoginAction} from "../state/app.actions";
|
||||
import {AppState} from "../state/app.state";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthenticationService {
|
||||
private _user: BehaviorSubject<any> = new BehaviorSubject(null);
|
||||
constructor(private http: HttpClient){
|
||||
let user = localStorage.getItem('currentUser' );
|
||||
if ( user ){
|
||||
this.user.next( JSON.stringify(user));
|
||||
}
|
||||
constructor(private http: HttpClient, private store: Store) {
|
||||
store.dispatch(new LoginAction(this.getToken()))
|
||||
}
|
||||
|
||||
public getToken() {
|
||||
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||
return currentUser?.token;
|
||||
}
|
||||
|
||||
// login
|
||||
login(username: string, password:string){
|
||||
return this.http.post<any>(Endpoints.POST_USERS_AUTHENTICATE(), {username:username,password:password})
|
||||
login(username: string, password: string) {
|
||||
return this.http.post<any>(Endpoints.POST_USERS_AUTHENTICATE(), {username: username, password: password})
|
||||
.pipe(
|
||||
// the backend service sends an instance of the user
|
||||
// user: any (because .post<any>)
|
||||
map(user => {
|
||||
// login successful if the response has jwt token
|
||||
if(user && user.token){
|
||||
if (user && user.token) {
|
||||
// store user details and jwt token in the local storage to keep the user logged in between page refreshes
|
||||
localStorage.setItem('currentUser', JSON.stringify(user));
|
||||
this.user.next(user);
|
||||
const decoded = jwtDecode<JwtPayload>(user.token);
|
||||
console.info("decoded", decoded);
|
||||
// this.user.next(user);
|
||||
this.store.dispatch(new LoginAction(user.token));
|
||||
}
|
||||
|
||||
return user;
|
||||
})
|
||||
}),
|
||||
catchError(err => {
|
||||
localStorage.removeItem('currentUser');
|
||||
this.store.dispatch(new LoginAction(null));
|
||||
return throwError(err);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
passwordChange(passwordChangeRequest: PasswordChangeRequest){
|
||||
passwordChange(passwordChangeRequest: PasswordChangeRequest) {
|
||||
return this.http.post<any>(Endpoints.POST_USER_PASSWORD_CHANGE(), passwordChangeRequest)
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this._user;
|
||||
}
|
||||
|
||||
public isLoggedIn(){
|
||||
return this.user.value;
|
||||
// get user() {
|
||||
// return this._user;
|
||||
// }
|
||||
//
|
||||
public isLoggedIn() {
|
||||
return this.store.selectSnapshot(AppState.getToken);
|
||||
}
|
||||
|
||||
// logout
|
||||
logout(){
|
||||
logout() {
|
||||
// remove user from local storage
|
||||
localStorage.removeItem('currentUser');
|
||||
this.user.next(null);
|
||||
this.store.dispatch(new LoginAction(null));
|
||||
// this.user.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,3 +6,9 @@ export class FilterTimeTableAction {
|
||||
constructor(public idTrainer: number, public idEventType: number) {}
|
||||
}
|
||||
|
||||
export class LoginAction {
|
||||
// For debug / console output upon dev environment
|
||||
static readonly type = "[App] LoginAction";
|
||||
constructor(public token: string) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import {Action, Selector, State, StateContext, Store} from "@ngxs/store";
|
||||
import {Action, Selector, State, StateContext} from "@ngxs/store";
|
||||
import {Injectable} from "@angular/core";
|
||||
import {
|
||||
FilterTimeTableAction,
|
||||
FilterTimeTableAction, LoginAction,
|
||||
} from "./app.actions";
|
||||
import {TimeTableFilter} from "../app.types";
|
||||
import jwtDecode, {JwtPayload} from "jwt-decode";
|
||||
|
||||
|
||||
export interface AppStateModel {
|
||||
username: string;
|
||||
token: string;
|
||||
filterTimeTable: FilterTimeTableAction;
|
||||
}
|
||||
|
||||
@@ -14,6 +17,8 @@ export interface AppStateModel {
|
||||
@State<AppStateModel>({
|
||||
name: "app",
|
||||
defaults: {
|
||||
username: null,
|
||||
token: null,
|
||||
filterTimeTable: {
|
||||
idTrainer: -1,
|
||||
idEventType: -1
|
||||
@@ -23,8 +28,7 @@ export interface AppStateModel {
|
||||
export class AppState {
|
||||
|
||||
|
||||
constructor(
|
||||
) {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
@Selector()
|
||||
@@ -32,6 +36,17 @@ export class AppState {
|
||||
return state.filterTimeTable;
|
||||
}
|
||||
|
||||
@Selector()
|
||||
public static getUsername(state: AppStateModel): string {
|
||||
return state.username;
|
||||
}
|
||||
|
||||
@Selector()
|
||||
public static getToken(state: AppStateModel): string {
|
||||
return state.token;
|
||||
}
|
||||
|
||||
|
||||
@Action(FilterTimeTableAction)
|
||||
dispatchFilterTimeTable(ctx: StateContext<AppStateModel>, {idEventType, idTrainer}: FilterTimeTableAction): void {
|
||||
ctx.patchState({
|
||||
@@ -42,4 +57,23 @@ export class AppState {
|
||||
});
|
||||
}
|
||||
|
||||
@Action(LoginAction)
|
||||
dispatchLogin(ctx: StateContext<AppStateModel>, {token}: LoginAction): void {
|
||||
let username = null;
|
||||
|
||||
try {
|
||||
const decoded = jwtDecode<JwtPayload & { username: string }>(token);
|
||||
username = decoded?.username;
|
||||
} catch (e) {
|
||||
// user not logged in
|
||||
token = null;
|
||||
}
|
||||
|
||||
|
||||
ctx.patchState({
|
||||
username: username,
|
||||
token: token
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user