From bf56d2b50944fe63c3547bb84e1a7596e51dcaea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= Date: Tue, 15 Jun 2021 11:32:48 +0200 Subject: [PATCH] BETTERZON-146: Changing session handling from cookies to localStorage --- .../contact_persons/contact_persons.router.ts | 8 +- .../crawling_status/crawling_status.router.ts | 4 +- .../favorite_shops/favoriteshops.router.ts | 12 +- .../models/pricealarms/pricealarms.router.ts | 12 +- Backend/src/models/prices/prices.router.ts | 4 +- Backend/src/models/users/users.router.ts | 22 ++-- Backend/src/models/vendors/vendors.router.ts | 16 ++- .../auth/signin/signin.component.ts | 57 ++++----- Frontend/src/app/services/api.service.ts | 108 ++++++++++++++++-- 9 files changed, 183 insertions(+), 60 deletions(-) diff --git a/Backend/src/models/contact_persons/contact_persons.router.ts b/Backend/src/models/contact_persons/contact_persons.router.ts index b06f62d..071482b 100644 --- a/Backend/src/models/contact_persons/contact_persons.router.ts +++ b/Backend/src/models/contact_persons/contact_persons.router.ts @@ -76,7 +76,9 @@ contactpersonsRouter.post('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get required parameters const vendor_id = req.body.vendor_id; @@ -104,7 +106,9 @@ contactpersonsRouter.put('/:id', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get required parameters const contact_person_id = parseInt(req.params.id, 10); diff --git a/Backend/src/models/crawling_status/crawling_status.router.ts b/Backend/src/models/crawling_status/crawling_status.router.ts index 4ca0b89..3d215bd 100644 --- a/Backend/src/models/crawling_status/crawling_status.router.ts +++ b/Backend/src/models/crawling_status/crawling_status.router.ts @@ -25,7 +25,9 @@ crawlingstatusRouter.get('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); if (!user.is_admin) { res.status(403).send({}); diff --git a/Backend/src/models/favorite_shops/favoriteshops.router.ts b/Backend/src/models/favorite_shops/favoriteshops.router.ts index 0c0d033..4cb0266 100644 --- a/Backend/src/models/favorite_shops/favoriteshops.router.ts +++ b/Backend/src/models/favorite_shops/favoriteshops.router.ts @@ -24,7 +24,9 @@ favoriteshopsRouter.get('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.params.session_id; + const session_key = req.params.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); const priceAlarms = await FavoriteShopsService.getFavoriteShops(user.user_id); @@ -40,7 +42,9 @@ favoriteshopsRouter.post('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get info for price alarm creation const vendor_id = req.body.vendor_id; @@ -72,7 +76,9 @@ favoriteshopsRouter.delete('/:id', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.params.session_id; + const session_key = req.params.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get info for price alarm creation const favorite_id = parseInt(req.params.id, 10); diff --git a/Backend/src/models/pricealarms/pricealarms.router.ts b/Backend/src/models/pricealarms/pricealarms.router.ts index fcd4939..a5d01c5 100644 --- a/Backend/src/models/pricealarms/pricealarms.router.ts +++ b/Backend/src/models/pricealarms/pricealarms.router.ts @@ -24,7 +24,9 @@ pricealarmsRouter.get('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.params.session_id; + const session_key = req.params.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); const priceAlarms = await PriceAlarmsService.getPriceAlarms(user.user_id); @@ -40,7 +42,9 @@ pricealarmsRouter.post('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get info for price alarm creation const product_id = req.body.product_id; @@ -73,7 +77,9 @@ pricealarmsRouter.put('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get info for price alarm creation const alarm_id = req.body.alarm_id; diff --git a/Backend/src/models/prices/prices.router.ts b/Backend/src/models/prices/prices.router.ts index 16bc5ba..61ed812 100644 --- a/Backend/src/models/prices/prices.router.ts +++ b/Backend/src/models/prices/prices.router.ts @@ -107,7 +107,9 @@ pricesRouter.post('/', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get required parameters const vendor_id = req.body.vendor_id; diff --git a/Backend/src/models/users/users.router.ts b/Backend/src/models/users/users.router.ts index d1ca782..7851ef7 100644 --- a/Backend/src/models/users/users.router.ts +++ b/Backend/src/models/users/users.router.ts @@ -47,10 +47,10 @@ usersRouter.post('/register', async (req: Request, res: Response) => { const session: Session = await UserService.createUser(username, password, email, ip); // Send the session details back to the user - res.cookie('betterauth', JSON.stringify({ - id: session.session_id, - key: session.session_key - }), {expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30)}).status(201).send({}); + res.status(201).send({ + session_id: session.session_id, + session_key: session.session_key + }); } catch (e) { console.log('Error handling a request: ' + e.message); res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'})); @@ -80,10 +80,10 @@ usersRouter.post('/login', async (req: Request, res: Response) => { } // Send the session details back to the user - res.cookie('betterauth', JSON.stringify({ - id: session.session_id, - key: session.session_key - }), {expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30)}).status(200).send({}); + res.status(200).send({ + session_id: session.session_id, + session_key: session.session_key + }); } catch (e) { console.log('Error handling a request: ' + e.message); res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'})); @@ -94,15 +94,17 @@ usersRouter.post('/login', async (req: Request, res: Response) => { usersRouter.post('/checkSessionValid', async (req: Request, res: Response) => { try { const ip: string = req.connection.remoteAddress ?? ''; + const session_id = req.body.session_id; + const session_key = req.body.session_key; - if(!req.cookies.betterauth) { + if(!session_id || !session_key) { // Error logging in, probably wrong username / password res.status(401).send(JSON.stringify({messages: ['No session detected'], codes: [5]})); return; } // Update the user entry and create a session - const user: User = await UserService.checkSessionWithCookie(req.cookies.betterauth, ip); + const user: User = await UserService.checkSession(session_id, session_key, ip); if (!user.user_id) { // Error logging in, probably wrong username / password diff --git a/Backend/src/models/vendors/vendors.router.ts b/Backend/src/models/vendors/vendors.router.ts index 7888cae..75ccc35 100644 --- a/Backend/src/models/vendors/vendors.router.ts +++ b/Backend/src/models/vendors/vendors.router.ts @@ -37,7 +37,9 @@ vendorsRouter.get('/managed', async (req: Request, res: Response) => { try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.params.session_id; + const session_key = req.params.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); const vendors = await VendorService.getManagedShops(user.user_id); @@ -91,7 +93,9 @@ vendorsRouter.put('/manage/deactivatelisting', async (req: Request, res: Respons try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get required parameters const vendor_id = req.body.vendor_id; @@ -115,7 +119,9 @@ vendorsRouter.put('/manage/shop/deactivate/:id', async (req: Request, res: Respo try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get required parameters const vendor_id = parseInt(req.params.id, 10); @@ -138,7 +144,9 @@ vendorsRouter.put('/manage/shop/activate/:id', async (req: Request, res: Respons try { // Authenticate user const user_ip = req.connection.remoteAddress ?? ''; - const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip); + const session_id = req.body.session_id; + const session_key = req.body.session_key; + const user = await UserService.checkSession(session_id, session_key, user_ip); // Get required parameters const vendor_id = parseInt(req.params.id, 10); diff --git a/Frontend/src/app/components/auth/signin/signin.component.ts b/Frontend/src/app/components/auth/signin/signin.component.ts index cf4142e..e39ac56 100644 --- a/Frontend/src/app/components/auth/signin/signin.component.ts +++ b/Frontend/src/app/components/auth/signin/signin.component.ts @@ -1,7 +1,7 @@ -import { Component, OnInit } from '@angular/core'; -import {FormBuilder, FormGroup, Validators} from "@angular/forms"; -import {ApiService} from "../../../services/api.service"; -import {Router} from "@angular/router"; +import {Component, OnInit} from '@angular/core'; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {ApiService} from '../../../services/api.service'; +import {Router} from '@angular/router'; @Component({ selector: 'app-signin', @@ -23,33 +23,34 @@ export class SigninComponent implements OnInit { private formBuilder: FormBuilder, private api: ApiService, private router: Router - ) { } + ) { + } ngOnInit(): void { - this.loginForm = this.formBuilder.group({ - username: ['', Validators.required], - password: ['', [Validators.required, Validators.minLength(8)]] - }); - } + this.loginForm = this.formBuilder.group({ + username: ['', Validators.required], + password: ['', [Validators.required, Validators.minLength(8)]] + }); + } - onSubmit() { + onSubmit(): void { + this.submitted = true; - this.submitted = true; + if (this.loginForm.invalid) { + return; + } - if (this.loginForm.invalid) { - return; - } - - this.api.loginUser(this.loginForm.value.username, this.loginForm.value.password) - .subscribe( - data => { - this.router.navigate(['']); - this.isSuccessful = true; - this.isSignUpFailed = false; - }, - err => { - this.errorMessage = err.error.message; - this.isSignUpFailed = true; - }) - } + this.api.loginUser(this.loginForm.value.username, this.loginForm.value.password) + .subscribe( + data => { + this.router.navigate(['']); + this.isSuccessful = true; + this.isSignUpFailed = false; + this.api.saveSessionInfoToLocalStorage(data); + }, + err => { + this.errorMessage = err.error.message; + this.isSignUpFailed = true; + }); + } } diff --git a/Frontend/src/app/services/api.service.ts b/Frontend/src/app/services/api.service.ts index 1cefc4b..953c229 100644 --- a/Frontend/src/app/services/api.service.ts +++ b/Frontend/src/app/services/api.service.ts @@ -243,7 +243,11 @@ export class ApiService { */ addNewPrice(vendorId: number, productId: number, price: number): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.post((this.apiUrl + '/prices'), JSON.stringify({ + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, vendor_id: vendorId, product_id: productId, price_in_cents: price @@ -278,7 +282,13 @@ export class ApiService { */ getManagedVendors(): Observable { try { - return this.http.get((this.apiUrl + '/vendors/managed')); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + let params = new HttpParams(); + params = params.append('session_id', sessionInfo.session_id); + params = params.append('session_key', sessionInfo.session_key); + + return this.http.get((this.apiUrl + '/vendors/managed'), {params}); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } @@ -318,7 +328,11 @@ export class ApiService { */ deactivateSingleVendorListing(vendorId: number, productId: number): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.put((this.apiUrl + '/vendors/manage/deactivatelisting'), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, vendor_id: vendorId, product_id: productId }); @@ -334,7 +348,12 @@ export class ApiService { */ deactivateVendor(vendorId: number): Observable { try { - return this.http.put((this.apiUrl + '/vendors/manage/shop/deactivate/' + vendorId), {}); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + return this.http.put((this.apiUrl + '/vendors/manage/shop/deactivate/' + vendorId), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, + }); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } @@ -347,7 +366,12 @@ export class ApiService { */ activateVendor(vendorId: number): Observable { try { - return this.http.put((this.apiUrl + '/vendors/manage/shop/activate/' + vendorId), {}); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + return this.http.put((this.apiUrl + '/vendors/manage/shop/activate/' + vendorId), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, + }); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } @@ -367,7 +391,13 @@ export class ApiService { */ getPriceAlarms(): Observable { try { - return this.http.get((this.apiUrl + '/pricealarms')); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + let params = new HttpParams(); + params = params.append('session_id', sessionInfo.session_id); + params = params.append('session_key', sessionInfo.session_key); + + return this.http.get((this.apiUrl + '/pricealarms'), {params}); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } @@ -381,7 +411,11 @@ export class ApiService { */ createPriceAlarms(productId: number, definedPrice: number): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.post((this.apiUrl + '/pricealarms'), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, product_id: productId, defined_price: definedPrice }); @@ -398,7 +432,11 @@ export class ApiService { */ updatePriceAlarms(alarmId: number, definedPrice: number): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.put((this.apiUrl + '/pricealarms'), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, alarm_id: alarmId, defined_price: definedPrice }); @@ -458,12 +496,36 @@ export class ApiService { */ getUserInfo(): Observable { try { - return this.http.post((this.apiUrl + '/users/checkSessionValid'), {}); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.post((this.apiUrl + '/users/checkSessionValid'), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key + }); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } } + /** + * Gets session id and session key from local storage + * @return any {session_id: '', session_key: ''} + */ + getSessionInfoFromLocalStorage(): any { + const session_id = localStorage.getItem('session_id') ?? ''; + const session_key = localStorage.getItem('session_key') ?? ''; + return {session_id, session_key}; + } + + /** + * Extracts and saves the session data from an api response + * @param data The api response + */ + saveSessionInfoToLocalStorage(data: any): boolean { + localStorage.setItem('session_id', data.session_id); + localStorage.setItem('session_key', data.session_key); + return true; + } + /* ______ _ __ __ / ____/___ __ ______ _____(_) /____ _____/ /_ ____ ____ _____ / /_ / __ `/ | / / __ \/ ___/ / __/ _ \ / ___/ __ \/ __ \/ __ \/ ___/ @@ -478,7 +540,13 @@ export class ApiService { */ getFavoriteShops(): Observable { try { - return this.http.get((this.apiUrl + '/favoriteshops')); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + let params = new HttpParams(); + params = params.append('session_id', sessionInfo.session_id); + params = params.append('session_key', sessionInfo.session_key); + + return this.http.get((this.apiUrl + '/favoriteshops'), {params}); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } @@ -491,7 +559,11 @@ export class ApiService { */ addFavoriteShop(vendorId: number): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.post((this.apiUrl + '/favoriteshops'), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, vendor_id: vendorId }); } catch (exception) { @@ -506,7 +578,13 @@ export class ApiService { */ deleteFavoriteShop(vendorId: number): Observable { try { - return this.http.delete((this.apiUrl + '/favoriteshops/' + vendorId)); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + let params = new HttpParams(); + params = params.append('session_id', sessionInfo.session_id); + params = params.append('session_key', sessionInfo.session_key); + + return this.http.delete((this.apiUrl + '/favoriteshops/' + vendorId), {params}); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); } @@ -570,7 +648,11 @@ export class ApiService { */ addContactPerson(vendorId: number, firstName: string, lastName: string, gender: string, email: string, phone: string): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.post((this.apiUrl + '/contactpersons'), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, vendor_id: vendorId, first_name: firstName, last_name: lastName, @@ -596,7 +678,11 @@ export class ApiService { */ updateContactPerson(contactId: number, vendorId: number, firstName: string, lastName: string, gender: string, email: string, phone: string): Observable { try { + const sessionInfo = this.getSessionInfoFromLocalStorage(); + return this.http.put((this.apiUrl + '/contactpersons/' + contactId), { + session_id: sessionInfo.session_id, + session_key: sessionInfo.session_key, vendor_id: vendorId, first_name: firstName, last_name: lastName, @@ -718,7 +804,13 @@ export class ApiService { */ getCurrentCrawlingStatus(): Observable { try { - return this.http.get((this.apiUrl + '/crawlingstatus')); + const sessionInfo = this.getSessionInfoFromLocalStorage(); + + let params = new HttpParams(); + params = params.append('session_id', sessionInfo.session_id); + params = params.append('session_key', sessionInfo.session_key); + + return this.http.get((this.apiUrl + '/crawlingstatus'), {params}); } catch (exception) { process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`); }