aboutsummaryrefslogtreecommitdiff
path: root/Timeline/ClientApp/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-03-18 21:21:56 +0800
committercrupest <crupest@outlook.com>2019-03-18 21:21:56 +0800
commit69ede25976c11f0624036251523d5f1d28811740 (patch)
tree97f461c68c2a9b3d3967afefc7b3015e80107e3d /Timeline/ClientApp/src
parente973ad02680f9d9ffdb9f7ac5aff9283484d2f46 (diff)
downloadtimeline-69ede25976c11f0624036251523d5f1d28811740.tar.gz
timeline-69ede25976c11f0624036251523d5f1d28811740.tar.bz2
timeline-69ede25976c11f0624036251523d5f1d28811740.zip
Add logout. Fix a bug.
The bug is it always goes to login page whether you have login or not before when user is presented in url.
Diffstat (limited to 'Timeline/ClientApp/src')
-rw-r--r--Timeline/ClientApp/src/app/user/auth.guard.ts33
-rw-r--r--Timeline/ClientApp/src/app/user/internal-user-service/internal-user.service.ts23
-rw-r--r--Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html1
-rw-r--r--Timeline/ClientApp/src/app/user/user-logout/user-logout.component.css0
-rw-r--r--Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html1
-rw-r--r--Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts25
-rw-r--r--Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts17
-rw-r--r--Timeline/ClientApp/src/app/user/user.module.ts6
-rw-r--r--Timeline/ClientApp/src/app/user/user.service.ts2
9 files changed, 82 insertions, 26 deletions
diff --git a/Timeline/ClientApp/src/app/user/auth.guard.ts b/Timeline/ClientApp/src/app/user/auth.guard.ts
index 561a0c53..1fc7a7c0 100644
--- a/Timeline/ClientApp/src/app/user/auth.guard.ts
+++ b/Timeline/ClientApp/src/app/user/auth.guard.ts
@@ -1,6 +1,7 @@
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
+import { take, map } from 'rxjs/operators';
import { InternalUserService } from './internal-user-service/internal-user.service';
@@ -23,26 +24,26 @@ export abstract class AuthGuard implements CanActivate {
return true;
}
- const { currentUserInfo } = this.internalUserService;
-
- if (currentUserInfo === null) {
- if (authStrategy === 'requirenologin') {
- return true;
- }
- } else {
- if (authStrategy === 'requirelogin') {
- return true;
- } else if (authStrategy instanceof Array) {
- const { roles } = currentUserInfo;
- if (authStrategy.every(value => roles.includes(value))) {
+ return this.internalUserService.userInfo$.pipe(take(1), map(userInfo => {
+ if (userInfo === null) {
+ if (authStrategy === 'requirenologin') {
return true;
}
+ } else {
+ if (authStrategy === 'requirelogin') {
+ return true;
+ } else if (authStrategy instanceof Array) {
+ const { roles } = userInfo;
+ if (authStrategy.every(value => roles.includes(value))) {
+ return true;
+ }
+ }
}
- }
- // reach here means auth fails
- this.onAuthFailed();
- return false;
+ // reach here means auth fails
+ this.onAuthFailed();
+ return false;
+ }));
}
}
diff --git a/Timeline/ClientApp/src/app/user/internal-user-service/internal-user.service.ts b/Timeline/ClientApp/src/app/user/internal-user-service/internal-user.service.ts
index 2098391e..d82e9613 100644
--- a/Timeline/ClientApp/src/app/user/internal-user-service/internal-user.service.ts
+++ b/Timeline/ClientApp/src/app/user/internal-user-service/internal-user.service.ts
@@ -3,7 +3,7 @@ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable, throwError, BehaviorSubject, of } from 'rxjs';
-import { map, catchError, retry, switchMap, tap } from 'rxjs/operators';
+import { map, catchError, retry, switchMap, tap, filter } from 'rxjs/operators';
import { AlreadyLoginError, BadCredentialsError, BadNetworkError, UnknownError } from './errors';
import {
@@ -35,14 +35,13 @@ export const TOKEN_STORAGE_KEY = 'token';
export class InternalUserService {
private token: string | null = null;
- private userInfoSubject = new BehaviorSubject<UserInfo | null>(null);
+ private userInfoSubject = new BehaviorSubject<UserInfo | null | undefined>(undefined);
- get currentUserInfo(): UserInfo | null {
- return this.userInfoSubject.value;
- }
+ readonly userInfo$: Observable<UserInfo | null> =
+ <Observable<UserInfo | null>>this.userInfoSubject.pipe(filter(value => value !== undefined));
- get userInfo$(): Observable<UserInfo | null> {
- return this.userInfoSubject;
+ get currentUserInfo(): UserInfo | null | undefined {
+ return this.userInfoSubject.value;
}
private openSnackBar(snackBar: MatSnackBar, textKey: SnackBarTextKey) {
@@ -129,4 +128,14 @@ export class InternalUserService {
})
);
}
+
+ logout() {
+ if (this.currentUserInfo === null) {
+ throw new Error('No login now. You can\'t logout.');
+ }
+
+ this.window.localStorage.removeItem(TOKEN_STORAGE_KEY);
+ this.token = null;
+ this.userInfoSubject.next(null);
+ }
}
diff --git a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html
index e156f0f8..8599a91d 100644
--- a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html
+++ b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html
@@ -3,3 +3,4 @@
</p>
<p class="mat-body">You have been login as <span class="username">{{ userInfo.username }}</span>.</p>
<p class="mat-body">Your roles are <span class="roles">{{ userInfo.roles.join(', ') }}</span>.</p>
+<a mat-flat-button [routerLink]="['..','logout']">Logout</a>
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.css b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.css
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html
new file mode 100644
index 00000000..56d96b83
--- /dev/null
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html
@@ -0,0 +1 @@
+<p class="mat-body">Log out succeeded!</p>
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts
new file mode 100644
index 00000000..91369e01
--- /dev/null
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UserLogoutComponent } from './user-logout.component';
+
+describe('UserLogoutComponent', () => {
+ let component: UserLogoutComponent;
+ let fixture: ComponentFixture<UserLogoutComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ UserLogoutComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UserLogoutComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts
new file mode 100644
index 00000000..24002c84
--- /dev/null
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts
@@ -0,0 +1,17 @@
+import { Component, OnInit } from '@angular/core';
+import { InternalUserService } from '../internal-user-service/internal-user.service';
+
+@Component({
+ selector: 'app-user-logout',
+ templateUrl: './user-logout.component.html',
+ styleUrls: ['./user-logout.component.css']
+})
+export class UserLogoutComponent implements OnInit {
+
+ constructor(private userService: InternalUserService) { }
+
+ ngOnInit() {
+ this.userService.logout();
+ }
+
+}
diff --git a/Timeline/ClientApp/src/app/user/user.module.ts b/Timeline/ClientApp/src/app/user/user.module.ts
index dcb61736..50c59662 100644
--- a/Timeline/ClientApp/src/app/user/user.module.ts
+++ b/Timeline/ClientApp/src/app/user/user.module.ts
@@ -16,20 +16,22 @@ import { UserLoginSuccessComponent } from './user-login-success/user-login-succe
import { RedirectComponent } from './redirect.component';
import { UtilityModule } from '../utilities/utility.module';
import { WINDOW } from './window-inject-token';
+import { UserLogoutComponent } from './user-logout/user-logout.component';
@NgModule({
- declarations: [UserDialogComponent, UserLoginComponent, UserLoginSuccessComponent, RedirectComponent],
+ declarations: [UserDialogComponent, UserLoginComponent, UserLoginSuccessComponent, RedirectComponent, UserLogoutComponent],
imports: [
RouterModule.forChild([
{ path: 'login', canActivate: [RequireNoLoginGuard], component: UserLoginComponent, outlet: 'user' },
{ path: 'success', canActivate: [RequireLoginGuard], component: UserLoginSuccessComponent, outlet: 'user' },
+ { path: 'logout', canActivate: [RequireLoginGuard], component: UserLogoutComponent, outlet: 'user' },
{ path: '**', component: RedirectComponent, outlet: 'user' }
]),
CommonModule, HttpClientModule, ReactiveFormsModule, BrowserAnimationsModule,
MatFormFieldModule, MatProgressSpinnerModule, MatDialogModule, MatInputModule, MatButtonModule, MatSnackBarModule,
UtilityModule
],
- providers: [{provide: WINDOW, useValue: window}],
+ providers: [{ provide: WINDOW, useValue: window }],
exports: [RouterModule],
entryComponents: [UserDialogComponent]
})
diff --git a/Timeline/ClientApp/src/app/user/user.service.ts b/Timeline/ClientApp/src/app/user/user.service.ts
index e7d50dd2..6cae2d31 100644
--- a/Timeline/ClientApp/src/app/user/user.service.ts
+++ b/Timeline/ClientApp/src/app/user/user.service.ts
@@ -29,7 +29,7 @@ export class UserService {
});
}
- get currentUserInfo(): UserInfo | null {
+ get currentUserInfo(): UserInfo | null | undefined {
return this.internalService.currentUserInfo;
}