From 978c9071613177aea8b3d773827c87fa329522cd Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 7 Aug 2020 00:01:45 +0800 Subject: Use cache login user if offline. --- Timeline/ClientApp/src/app/data/user.ts | 131 ++++++++++++++---------------- Timeline/ClientApp/src/app/user/Login.tsx | 4 +- 2 files changed, 65 insertions(+), 70 deletions(-) (limited to 'Timeline/ClientApp/src') diff --git a/Timeline/ClientApp/src/app/data/user.ts b/Timeline/ClientApp/src/app/data/user.ts index 14f4e943..defcb4e4 100644 --- a/Timeline/ClientApp/src/app/data/user.ts +++ b/Timeline/ClientApp/src/app/data/user.ts @@ -1,6 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { BehaviorSubject, Observable, of, from } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { BehaviorSubject, Observable, from } from 'rxjs'; import { UiLogicError } from '../common'; import { convertError } from '../utilities/rxjs'; @@ -41,7 +40,7 @@ export class BadCredentialError { message = 'login.badCredential'; } -const TOKEN_STORAGE_KEY = 'token'; +const USER_STORAGE_KEY = 'currentuser'; export class UserService { private userSubject = new BehaviorSubject( @@ -56,96 +55,92 @@ export class UserService { return this.userSubject.value; } - checkLoginState(): Observable { + async checkLoginState(): Promise { if (this.currentUser !== undefined) { console.warn("Already checked user. Can't check twice."); } - const savedToken = window.localStorage.getItem(TOKEN_STORAGE_KEY); - if (savedToken) { - const u$ = from(getHttpTokenClient().verify({ token: savedToken })).pipe( - map( - (res) => - ({ - ...res.user, - token: savedToken, - } as UserWithToken) - ) - ); - u$.subscribe( - (user) => { - if (user != null) { - pushAlert({ - type: 'success', - message: { - type: 'i18n', - key: 'user.welcomeBack', - }, - }); - } - this.userSubject.next(user); + const savedUser = await dataStorage.getItem( + USER_STORAGE_KEY + ); + + if (savedUser == null) { + this.userSubject.next(null); + return null; + } + + this.userSubject.next(savedUser); + + const savedToken = savedUser.token; + try { + const res = await getHttpTokenClient().verify({ token: savedToken }); + const user: UserWithToken = { ...res.user, token: savedToken }; + await dataStorage.setItem(USER_STORAGE_KEY, user); + this.userSubject.next(user); + pushAlert({ + type: 'success', + message: { + type: 'i18n', + key: 'user.welcomeBack', }, - (error) => { - if (error instanceof HttpNetworkError) { - pushAlert({ - type: 'danger', - message: { type: 'i18n', key: 'user.verifyTokenFailedNetwork' }, - }); - } else { - window.localStorage.removeItem(TOKEN_STORAGE_KEY); - pushAlert({ - type: 'danger', - message: { type: 'i18n', key: 'user.verifyTokenFailed' }, - }); - } - this.userSubject.next(null); - } - ); - return u$; + }); + return user; + } catch (error) { + if (error instanceof HttpNetworkError) { + pushAlert({ + type: 'danger', + message: { type: 'i18n', key: 'user.verifyTokenFailedNetwork' }, + }); + return savedUser; + } else { + await dataStorage.removeItem(USER_STORAGE_KEY); + this.userSubject.next(null); + pushAlert({ + type: 'danger', + message: { type: 'i18n', key: 'user.verifyTokenFailed' }, + }); + return null; + } } - this.userSubject.next(null); - return of(null); } - login( + async login( credentials: LoginCredentials, rememberMe: boolean - ): Observable { + ): Promise { if (this.currentUser) { throw new UiLogicError('Already login.'); } - const u$ = from( - getHttpTokenClient().create({ + try { + const res = await getHttpTokenClient().create({ ...credentials, expire: 30, - }) - ).pipe( - map( - (res) => - ({ - ...res.user, - token: res.token, - } as UserWithToken) - ), - convertError(HttpCreateTokenBadCredentialError, BadCredentialError) - ); - u$.subscribe((user) => { + }); + const user: UserWithToken = { + ...res.user, + token: res.token, + }; if (rememberMe) { - window.localStorage.setItem(TOKEN_STORAGE_KEY, user.token); + await dataStorage.setItem(USER_STORAGE_KEY, user); } this.userSubject.next(user); - }); - return u$; + } catch (e) { + if (e instanceof HttpCreateTokenBadCredentialError) { + throw new BadCredentialError(); + } else { + throw e; + } + } } - logout(): void { + async logout(): Promise { if (this.currentUser === undefined) { throw new UiLogicError('Please check user first.'); } if (this.currentUser === null) { throw new UiLogicError('No login.'); } - window.localStorage.removeItem(TOKEN_STORAGE_KEY); + await dataStorage.removeItem(USER_STORAGE_KEY); this.userSubject.next(null); } @@ -166,7 +161,7 @@ export class UserService { ) ); $.subscribe(() => { - this.logout(); + void this.logout(); }); return $; } diff --git a/Timeline/ClientApp/src/app/user/Login.tsx b/Timeline/ClientApp/src/app/user/Login.tsx index a615d8ed..2f2a3188 100644 --- a/Timeline/ClientApp/src/app/user/Login.tsx +++ b/Timeline/ClientApp/src/app/user/Login.tsx @@ -62,8 +62,8 @@ const Login: React.FC = (_) => { }, rememberMe ) - .subscribe( - (_) => { + .then( + () => { if (history.length === 0) { history.push('/'); } else { -- cgit v1.2.3