From 678bfc08ca0dfb87b69671bbbaee46c62f3afabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= Date: Fri, 20 Aug 2021 21:22:57 +0000 Subject: [PATCH] API-11: User Data Endpoint (#6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrick Müller Reviewed-on: https://git.plutodev.de/PlutoDev/plutoapi-v2/pulls/6 Co-authored-by: Patrick Müller Co-committed-by: Patrick Müller --- src/models/partyplaner/data/Data.router.ts | 36 ++++++--- src/models/partyplaner/data/data.service.ts | 75 +++++++++++++++++++ src/models/partyplaner/login/Login.router.ts | 2 - .../partyplaner/userService/user.service.ts | 28 +++++++ 4 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 src/models/partyplaner/data/data.service.ts diff --git a/src/models/partyplaner/data/Data.router.ts b/src/models/partyplaner/data/Data.router.ts index 19d34cd..6739e84 100644 --- a/src/models/partyplaner/data/Data.router.ts +++ b/src/models/partyplaner/data/Data.router.ts @@ -2,6 +2,8 @@ * Required External Modules and Interfaces */ import express, {Request, Response} from 'express'; +import * as DataService from './data.service'; +import * as UserService from '../userService/user.service'; import logger from '../../../middleware/logger'; /** @@ -9,18 +11,32 @@ import logger from '../../../middleware/logger'; */ export const dataRouter = express.Router(); -dataRouter.get('/', async (req: Request, res: Response) => { +dataRouter.get('/user/:isDevCall', async (req: Request, res: Response) => { try { - res.status(200).send('GET data'); - } catch (e) { - logger.error('Error handling a request: ' + e.message); - res.status(500).send({'message': 'Internal Server Error. Try again later.'}); - } -}); + let userId = (req.query.userId ?? '').toString(); + let sessionId = (req.query.sessionId ?? '').toString(); + let sessionKey = (req.query.sessionKey ?? '').toString(); + let useDev: boolean = (req.params.isDevCall ?? '') === 'dev'; // TBD -dataRouter.post('/', async (req: Request, res: Response) => { - try { - res.status(200).send('POST data'); + if (userId === '' || sessionId === '' || sessionKey === '') { + res.status(400).send({ + 'status': 'WRONG_PARAMS', + 'message': 'Missing or wrong parameters' + }); + return; + } + + if (!await UserService.checkSession(useDev, userId, sessionId, sessionKey)) { + res.status(403).send({ + 'status': 'INVALID_SESSION', + 'message': 'The user or session could not be found or the session is invalid' + }); + return; + } + + let data = await DataService.getUserData(useDev, userId); + + res.status(200).send(data); } catch (e) { logger.error('Error handling a request: ' + e.message); res.status(500).send({'message': 'Internal Server Error. Try again later.'}); diff --git a/src/models/partyplaner/data/data.service.ts b/src/models/partyplaner/data/data.service.ts new file mode 100644 index 0000000..07fe4b3 --- /dev/null +++ b/src/models/partyplaner/data/data.service.ts @@ -0,0 +1,75 @@ +import * as dotenv from 'dotenv'; + +dotenv.config(); + +const mariadb = require('mariadb'); +const prod_pool = mariadb.createPool({ + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.PARTYPLANER_PROD_DATABASE, + connectionLimit: 5 +}); +const dev_pool = mariadb.createPool({ + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.PARTYPLANER_DEV_DATABASE, + connectionLimit: 5 +}); + +/** + * Used in the getUserData method as return value + */ +export interface UserData { + username: string; + email: string; + firstName: string; + lastName: string; + lastLogin: string; + emailIsVerified: string; + isPremiumUser: string; +} + +/** + * Returns all data about the given user + * @param useDev If the dev or prod database should be used + * @param userId The userId of the user to return the data for + * @return UserData An object containing the user data + */ +export const getUserData = async (useDev: boolean, userId: string): Promise => { + let conn; + try { + if (useDev) { + conn = await dev_pool.getConnection(); + } else { + conn = await prod_pool.getConnection(); + } + + let rows = await conn.query('SELECT username, email, first_name, last_Name, last_login, email_is_verified, is_premium_user FROM users WHERE user_id = ?', userId); + + let user: UserData = {} as UserData; + + for (let row in rows) { + if (row !== 'meta') { + user = { + username: rows[row].username, + email: rows[row].email, + firstName: rows[row].first_name, + lastName: rows[row].last_name, + lastLogin: rows[row].last_login, + emailIsVerified: rows[row].email_is_verified, + isPremiumUser: rows[row].is_premium_user + }; + } + } + + return user; + } catch (err) { + throw err; + } finally { + if (conn) { + conn.end(); + } + } +}; diff --git a/src/models/partyplaner/login/Login.router.ts b/src/models/partyplaner/login/Login.router.ts index 351f5b4..191127a 100644 --- a/src/models/partyplaner/login/Login.router.ts +++ b/src/models/partyplaner/login/Login.router.ts @@ -14,8 +14,6 @@ loginRouter.post('/:isDevCall', async (req: Request, res: Response) => { try { let username: string = ''; let email: string = ''; - let firstName: string = ''; - let lastName: string = ''; let password: string = ''; let useDev: boolean = (req.params.isDevCall ?? '') === 'dev'; // TBD diff --git a/src/models/partyplaner/userService/user.service.ts b/src/models/partyplaner/userService/user.service.ts index c6e85a8..966c8a8 100644 --- a/src/models/partyplaner/userService/user.service.ts +++ b/src/models/partyplaner/userService/user.service.ts @@ -298,3 +298,31 @@ export const checkUsernameAndEmail = async (useDev: boolean, username: string, e } } }; + +export const checkSession = async (useDev: boolean, userId: string, sessionId: string, sessionKey: string): Promise => { + let conn; + try { + if (useDev) { + conn = await dev_pool.getConnection(); + } else { + conn = await prod_pool.getConnection(); + } + + let rows = await conn.query('SELECT session_key_hash FROM sessions WHERE user_id = ? AND session_id = ?', [userId, sessionId]); + + let savedHash = ''; + for (let row in rows) { + if (row !== 'meta') { + savedHash = rows[row].session_key_hash; + } + } + + return bcrypt.compareSync(sessionKey, savedHash); + } catch (err) { + throw err; + } finally { + if (conn) { + conn.end(); + } + } +};