From bc2e9052585c748056588a3a4ed1d34553b6f8ac Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sat, 22 May 2021 09:18:59 +0200 Subject: [PATCH] Refactor AuthGuard, persist displayMode in user settings --- .../src/app/user/update-user-settings.dto.ts | 7 ++- apps/api/src/app/user/user.controller.ts | 3 +- apps/api/src/app/user/user.service.ts | 16 +++-- .../api/src/services/configuration.service.ts | 2 +- .../components/header/header.component.html | 6 +- apps/client/src/app/core/auth.guard.ts | 62 +++++++++++++------ .../src/app/core/http-response.interceptor.ts | 1 - .../pages/account/account-page.component.ts | 24 +++---- .../src/app/pages/account/account-page.html | 16 +++-- apps/client/src/app/pages/zen/zen-page.scss | 3 +- libs/common/src/lib/config.ts | 2 +- .../lib/interfaces/user-settings.interface.ts | 4 +- prisma/schema.prisma | 14 +++-- 13 files changed, 96 insertions(+), 64 deletions(-) diff --git a/apps/api/src/app/user/update-user-settings.dto.ts b/apps/api/src/app/user/update-user-settings.dto.ts index def1914bd..4c3e978bb 100644 --- a/apps/api/src/app/user/update-user-settings.dto.ts +++ b/apps/api/src/app/user/update-user-settings.dto.ts @@ -1,7 +1,10 @@ -import { Currency } from '@prisma/client'; +import { Currency, DisplayMode } from '@prisma/client'; import { IsString } from 'class-validator'; export class UpdateUserSettingsDto { @IsString() - currency: Currency; + baseCurrency: Currency; + + @IsString() + displayMode: DisplayMode; } diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index 6b11c064e..974a8195d 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -93,7 +93,8 @@ export class UserController { } return await this.userService.updateUserSettings({ - currency: data.currency, + currency: data.baseCurrency, + displayMode: data.displayMode, userId: this.request.user.id }); } diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index f1994fffe..0ed3f2e44 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -5,7 +5,7 @@ import { resetHours } from '@ghostfolio/common/helper'; import { User as IUser, UserWithSettings } from '@ghostfolio/common/interfaces'; import { getPermissions, permissions } from '@ghostfolio/common/permissions'; import { Injectable } from '@nestjs/common'; -import { Currency, Prisma, Provider, User } from '@prisma/client'; +import { Currency, DisplayMode, Prisma, Provider, User } from '@prisma/client'; import { add } from 'date-fns'; const crypto = require('crypto'); @@ -52,8 +52,9 @@ export class UserService { accounts: Account, permissions: currentPermissions, settings: { - baseCurrency: Settings?.currency || UserService.DEFAULT_CURRENCY, - locale + locale, + baseCurrency: Settings?.currency ?? UserService.DEFAULT_CURRENCY, + displayMode: Settings.displayMode ?? DisplayMode.DEFAULT }, subscription: { expiresAt: resetHours(add(new Date(), { days: 7 })), @@ -79,6 +80,7 @@ export class UserService { // Set default settings if needed user.Settings = { currency: UserService.DEFAULT_CURRENCY, + displayMode: DisplayMode.DEFAULT, updatedAt: new Date(), userId: user?.id }; @@ -187,14 +189,17 @@ export class UserService { public async updateUserSettings({ currency, + displayMode, userId }: { - currency: Currency; + currency?: Currency; + displayMode?: DisplayMode; userId: string; }) { await this.prisma.settings.upsert({ create: { currency, + displayMode, User: { connect: { id: userId @@ -202,7 +207,8 @@ export class UserService { } }, update: { - currency + currency, + displayMode }, where: { userId: userId diff --git a/apps/api/src/services/configuration.service.ts b/apps/api/src/services/configuration.service.ts index a52bf85cd..0ba57989c 100644 --- a/apps/api/src/services/configuration.service.ts +++ b/apps/api/src/services/configuration.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; +import { DataSource } from '@prisma/client'; import { bool, cleanEnv, json, num, port, str } from 'envalid'; import { Environment } from './interfaces/environment.interface'; -import { DataSource } from '.prisma/client'; @Injectable() export class ConfigurationService { diff --git a/apps/client/src/app/components/header/header.component.html b/apps/client/src/app/components/header/header.component.html index a7b6800aa..598ca13df 100644 --- a/apps/client/src/app/components/header/header.component.html +++ b/apps/client/src/app/components/header/header.component.html @@ -8,11 +8,14 @@ class="d-none d-sm-block" i18n mat-flat-button - [color]="currentRoute === 'home' ? 'primary' : null" + [color]=" + currentRoute === 'home' || currentRoute === 'zen' ? 'primary' : null + " [routerLink]="['/']" >Overview</a > <a + *ngIf="user?.settings?.displayMode === 'DEFAULT'" class="d-none d-sm-block mx-1" i18n mat-flat-button @@ -21,6 +24,7 @@ >Analysis</a > <a + *ngIf="user?.settings?.displayMode === 'DEFAULT'" class="d-none d-sm-block mx-1" i18n mat-flat-button diff --git a/apps/client/src/app/core/auth.guard.ts b/apps/client/src/app/core/auth.guard.ts index 5df7a3638..00dc9553e 100644 --- a/apps/client/src/app/core/auth.guard.ts +++ b/apps/client/src/app/core/auth.guard.ts @@ -5,16 +5,19 @@ import { Router, RouterStateSnapshot } from '@angular/router'; +import { DisplayMode } from '@prisma/client'; +import { EMPTY } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { DataService } from '../services/data.service'; import { SettingsStorageService } from '../services/settings-storage.service'; -import { TokenStorageService } from '../services/token-storage.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor( + private dataService: DataService, private router: Router, - private settingsStorageService: SettingsStorageService, - private tokenStorageService: TokenStorageService + private settingsStorageService: SettingsStorageService ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { @@ -25,23 +28,46 @@ export class AuthGuard implements CanActivate { ); } - const isLoggedIn = !!this.tokenStorageService.getToken(); + return new Promise<boolean>((resolve) => { + this.dataService + .fetchUser() + .pipe( + catchError(() => { + if (state.url !== '/start') { + this.router.navigate(['/start']); + resolve(false); + return EMPTY; + } - if (isLoggedIn) { - if (state.url === '/start') { - this.router.navigate(['/home']); - return false; - } + resolve(true); + return EMPTY; + }) + ) + .subscribe((user) => { + if ( + state.url === '/home' && + user.settings.displayMode === DisplayMode.ZEN + ) { + this.router.navigate(['/zen']); + resolve(false); + } else if (state.url === '/start') { + if (user.settings.displayMode === DisplayMode.ZEN) { + this.router.navigate(['/zen']); + } else { + this.router.navigate(['/home']); + } - return true; - } - - // Not logged in - if (state.url !== '/start') { - this.router.navigate(['/start']); - return false; - } + resolve(false); + } else if ( + state.url === '/zen' && + user.settings.displayMode === DisplayMode.DEFAULT + ) { + this.router.navigate(['/home']); + resolve(false); + } - return true; + resolve(true); + }); + }); } } diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index 72de866d2..3f49e7891 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -79,7 +79,6 @@ export class HttpResponseInterceptor implements HttpInterceptor { } } else if (error.status === StatusCodes.UNAUTHORIZED) { this.tokenStorageService.signOut(); - this.router.navigate(['start']); } return throwError(''); diff --git a/apps/client/src/app/pages/account/account-page.component.ts b/apps/client/src/app/pages/account/account-page.component.ts index a710ca2a5..4d1b428e3 100644 --- a/apps/client/src/app/pages/account/account-page.component.ts +++ b/apps/client/src/app/pages/account/account-page.component.ts @@ -51,8 +51,6 @@ export class AccountPageComponent implements OnDestroy, OnInit { this.dataService.fetchUser().subscribe((user) => { this.user = user; - this.user.settings.mode = 'ZEN'; - this.hasPermissionToUpdateUserSettings = hasPermission( this.user.permissions, permissions.updateUserSettings @@ -70,9 +68,14 @@ export class AccountPageComponent implements OnDestroy, OnInit { this.update(); } - public onChangeBaseCurrency({ value: currency }: { value: Currency }) { + public onChangeUserSettings(aKey: string, aValue: string) { + const settings = { ...this.user.settings, [aKey]: aValue }; + this.dataService - .putUserSettings({ currency }) + .putUserSettings({ + baseCurrency: settings?.baseCurrency, + displayMode: settings?.displayMode + }) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { this.dataService.fetchUser().subscribe((user) => { @@ -83,19 +86,6 @@ export class AccountPageComponent implements OnDestroy, OnInit { }); } - public onChangeMode({ value: mode }: { value: Currency }) { - /*this.dataService - .putUserSettings({ currency }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.dataService.fetchUser().subscribe((user) => { - this.user = user; - - this.cd.markForCheck(); - }); - });*/ - } - public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/pages/account/account-page.html b/apps/client/src/app/pages/account/account-page.html index e3b6f830a..ff2904782 100644 --- a/apps/client/src/app/pages/account/account-page.html +++ b/apps/client/src/app/pages/account/account-page.html @@ -30,14 +30,14 @@ <div class="d-flex mt-4 py-1"> <div class="pt-4 w-50" i18n>Settings</div> <div class="w-50"> - <form #changeBaseCurrencyForm="ngForm"> - <mat-form-field appearance="outline" class="w-100"> + <form #changeUserSettingsForm="ngForm"> + <mat-form-field appearance="outline" class="mb-3 w-100"> <mat-label i18n>Base Currency</mat-label> <mat-select name="baseCurrency" [disabled]="!hasPermissionToUpdateUserSettings" [value]="user.settings.baseCurrency" - (selectionChange)="onChangeBaseCurrency($event)" + (selectionChange)="onChangeUserSettings('baseCurrency', $event.value)" > <mat-option *ngFor="let currency of currencies" @@ -46,15 +46,13 @@ > </mat-select> </mat-form-field> - </form> - <form #changeModeForm="ngForm"> <mat-form-field appearance="outline" class="w-100"> - <mat-label i18n>Mode</mat-label> + <mat-label i18n>Display Mode</mat-label> <mat-select - name="baseCurrency" + name="displayMode" [disabled]="!hasPermissionToUpdateUserSettings" - [value]="user.settings.mode" - (selectionChange)="onChangeMode($event)" + [value]="user.settings.displayMode" + (selectionChange)="onChangeUserSettings('displayMode', $event.value)" > <mat-option value="DEFAULT">Default</mat-option> <mat-option value="ZEN">Zen</mat-option> diff --git a/apps/client/src/app/pages/zen/zen-page.scss b/apps/client/src/app/pages/zen/zen-page.scss index d3be6211f..a0921ff14 100644 --- a/apps/client/src/app/pages/zen/zen-page.scss +++ b/apps/client/src/app/pages/zen/zen-page.scss @@ -4,8 +4,7 @@ .chart-container { aspect-ratio: 16 / 9; - cursor: pointer; - margin-top: -1rem; + margin-top: 3rem; max-height: 50vh; // Fallback for aspect-ratio (using padding hack) diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 3c724127c..66191843d 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -1,4 +1,4 @@ -import { Currency } from '.prisma/client'; +import { Currency } from '@prisma/client'; export const baseCurrency = Currency.CHF; diff --git a/libs/common/src/lib/interfaces/user-settings.interface.ts b/libs/common/src/lib/interfaces/user-settings.interface.ts index e025e0832..78a6ad01c 100644 --- a/libs/common/src/lib/interfaces/user-settings.interface.ts +++ b/libs/common/src/lib/interfaces/user-settings.interface.ts @@ -1,7 +1,7 @@ -import { Currency } from '@prisma/client'; +import { Currency, DisplayMode } from '@prisma/client'; export interface UserSettings { baseCurrency: Currency; + displayMode: DisplayMode; locale: string; - mode: 'DEFAULT' | 'ZEN'; } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index eb7a084c9..7742bdd69 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -92,10 +92,11 @@ model Property { } model Settings { - currency Currency - updatedAt DateTime @updatedAt - User User @relation(fields: [userId], references: [id]) - userId String @id + currency Currency? + displayMode DisplayMode? + updatedAt DateTime @updatedAt + User User @relation(fields: [userId], references: [id]) + userId String @id } model User { @@ -133,6 +134,11 @@ enum DataSource { YAHOO } +enum DisplayMode { + DEFAULT + ZEN +} + enum Provider { ANONYMOUS GOOGLE