API-10: Adding PartyPlaner register endpoint
- Also various other improvements
This commit is contained in:
		
							parent
							
								
									7df8b5ad8e
								
							
						
					
					
						commit
						8295deaf6a
					
				
							
								
								
									
										9
									
								
								app.ts
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								app.ts
									
									
									
									
									
								
							| 
						 | 
					@ -2,6 +2,10 @@ import express from 'express';
 | 
				
			||||||
import * as http from 'http';
 | 
					import * as http from 'http';
 | 
				
			||||||
import * as bodyparser from 'body-parser';
 | 
					import * as bodyparser from 'body-parser';
 | 
				
			||||||
import * as dotenv from 'dotenv';
 | 
					import * as dotenv from 'dotenv';
 | 
				
			||||||
 | 
					// Router imports
 | 
				
			||||||
 | 
					import {partyPlanerRouter} from "./src/models/partyplaner/PartyPlaner.router";
 | 
				
			||||||
 | 
					import {highlightMarkerRouter} from "./src/models/twitch-highlight-marker/HighlightMarker.router";
 | 
				
			||||||
 | 
					import {dhbwServiceRouter} from "./src/models/dhbw-service/DHBWService.router";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dotenv.config();
 | 
					dotenv.config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,11 +16,6 @@ if (!process.env.PORT) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const port: number = parseInt(process.env.PORT, 10);
 | 
					const port: number = parseInt(process.env.PORT, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Router imports
 | 
					 | 
				
			||||||
import {partyPlanerRouter} from "./src/models/partyplaner/PartyPlaner.router";
 | 
					 | 
				
			||||||
import {highlightMarkerRouter} from "./src/models/twitch-highlight-marker/HighlightMarker.router";
 | 
					 | 
				
			||||||
import { dhbwServiceRouter } from './src/models/dhbw-service/DHBWServiceRouter';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app: express.Application = express();
 | 
					const app: express.Application = express();
 | 
				
			||||||
const server: http.Server = http.createServer(app);
 | 
					const server: http.Server = http.createServer(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1513
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1513
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -13,12 +13,15 @@
 | 
				
			||||||
  "author": "",
 | 
					  "author": "",
 | 
				
			||||||
  "license": "ISC",
 | 
					  "license": "ISC",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "bcrypt": "^5.0.1",
 | 
				
			||||||
    "debug": "^4.3.1",
 | 
					    "debug": "^4.3.1",
 | 
				
			||||||
    "dotenv": "^8.2.0",
 | 
					    "dotenv": "^8.2.0",
 | 
				
			||||||
    "express": "^4.17.1",
 | 
					    "express": "^4.17.1",
 | 
				
			||||||
 | 
					    "guid-typescript": "^1.0.9",
 | 
				
			||||||
    "mariadb": "^2.5.3"
 | 
					    "mariadb": "^2.5.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@types/bcrypt": "^3.0.1",
 | 
				
			||||||
    "@types/debug": "^4.1.5",
 | 
					    "@types/debug": "^4.1.5",
 | 
				
			||||||
    "@types/express": "^4.17.11",
 | 
					    "@types/express": "^4.17.11",
 | 
				
			||||||
    "source-map-support": "^0.5.19",
 | 
					    "source-map-support": "^0.5.19",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,11 +12,11 @@ export const dhbwServiceRouter = express.Router();
 | 
				
			||||||
// Sub-Endpoints
 | 
					// Sub-Endpoints
 | 
				
			||||||
dhbwServiceRouter.use('/generalInfo', generalInfoRouter);
 | 
					dhbwServiceRouter.use('/generalInfo', generalInfoRouter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
generalInfoRouter.get('/', async (req: Request, res: Response) => {
 | 
					dhbwServiceRouter.get('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`Pluto Development DHBW Service App API Endpoint`);
 | 
					        res.status(200).send('Pluto Development DHBW Service App API Endpoint');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					@ -10,18 +10,18 @@ export const generalInfoRouter = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
generalInfoRouter.get('/', async (req: Request, res: Response) => {
 | 
					generalInfoRouter.get('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`GET generalInfo v2.1`);
 | 
					        res.status(200).send('GET generalInfo v2.1');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
generalInfoRouter.post('/', async (req: Request, res: Response) => {
 | 
					generalInfoRouter.post('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`POST generalInfo v2.1`);
 | 
					        res.status(200).send('POST generalInfo v2.1');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
import express, {Request, Response} from 'express';
 | 
					import express, {Request, Response} from 'express';
 | 
				
			||||||
import {dataRouter} from "./data/Data.router";
 | 
					import {dataRouter} from "./data/Data.router";
 | 
				
			||||||
 | 
					import {registerRouter} from "./register/Register.router";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Router Definition
 | 
					 * Router Definition
 | 
				
			||||||
| 
						 | 
					@ -11,12 +12,13 @@ export const partyPlanerRouter = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sub-Endpoints
 | 
					// Sub-Endpoints
 | 
				
			||||||
partyPlanerRouter.use('/data', dataRouter);
 | 
					partyPlanerRouter.use('/data', dataRouter);
 | 
				
			||||||
 | 
					partyPlanerRouter.use('/register', registerRouter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
partyPlanerRouter.get('/', async (req: Request, res: Response) => {
 | 
					partyPlanerRouter.get('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`Pluto Development PartyPlaner API Endpoint V2`);
 | 
					        res.status(200).send('Pluto Development PartyPlaner API Endpoint V2');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,18 +10,18 @@ export const dataRouter = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dataRouter.get('/', async (req: Request, res: Response) => {
 | 
					dataRouter.get('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`GET data`);
 | 
					        res.status(200).send('GET data');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dataRouter.post('/', async (req: Request, res: Response) => {
 | 
					dataRouter.post('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`POST data`);
 | 
					        res.status(200).send('POST data');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										67
									
								
								src/models/partyplaner/register/Register.router.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/models/partyplaner/register/Register.router.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Required External Modules and Interfaces
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import express, {Request, Response} from 'express';
 | 
				
			||||||
 | 
					import * as UserService from '../userService/user.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Router Definition
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const registerRouter = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					registerRouter.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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // API accepts both JSON in body and HTTP parameters
 | 
				
			||||||
 | 
					        if (req.headers['content-type'] === 'application/json') {
 | 
				
			||||||
 | 
					            username = req.body.username;
 | 
				
			||||||
 | 
					            email = req.body.email;
 | 
				
			||||||
 | 
					            firstName = req.body.firstName;
 | 
				
			||||||
 | 
					            lastName = req.body.lastName;
 | 
				
			||||||
 | 
					            password = req.body.password;
 | 
				
			||||||
 | 
					        } else if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
 | 
				
			||||||
 | 
					            username = (req.query.username ?? '').toString();
 | 
				
			||||||
 | 
					            email = (req.query.email ?? '').toString();
 | 
				
			||||||
 | 
					            firstName = (req.query.firstName ?? '').toString();
 | 
				
			||||||
 | 
					            lastName = (req.query.lastName ?? '').toString();
 | 
				
			||||||
 | 
					            password = (req.query.password ?? '').toString();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let userIP = req.socket.remoteAddress ?? '';
 | 
				
			||||||
 | 
					        let deviceInfo = req.headers['user-agent'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (username === '' || email === '' || firstName === '' || lastName === '' || password === '') {
 | 
				
			||||||
 | 
					            res.status(400).send({
 | 
				
			||||||
 | 
					                'status': 'WRONG_PARAMS',
 | 
				
			||||||
 | 
					                'message': 'Missing or wrong parameters'
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check for invalid username / email
 | 
				
			||||||
 | 
					        const status = await UserService.checkUsernameAndEmail(useDev, username, email);
 | 
				
			||||||
 | 
					        if (status.hasProblems) {
 | 
				
			||||||
 | 
					            // Username and/or email are duplicates, return error
 | 
				
			||||||
 | 
					            res.status(400).send({
 | 
				
			||||||
 | 
					                'message': status.messages[0],
 | 
				
			||||||
 | 
					                'status': status.status[0],
 | 
				
			||||||
 | 
					                'additionalMessages': status.messages.slice(1),
 | 
				
			||||||
 | 
					                'additionalStatus': status.status.slice(1)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create user
 | 
				
			||||||
 | 
					        let session = await UserService.registerUser(useDev, username, email, firstName, lastName, password, userIP, deviceInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res.status(201).send(session);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
							
								
								
									
										200
									
								
								src/models/partyplaner/userService/user.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								src/models/partyplaner/userService/user.service.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,200 @@
 | 
				
			||||||
 | 
					import * as dotenv from 'dotenv';
 | 
				
			||||||
 | 
					import * as bcrypt from 'bcrypt';
 | 
				
			||||||
 | 
					import {Guid} from 'guid-typescript';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getExistingUsernamesAndEmails = async (useDev: boolean): Promise<any> => {
 | 
				
			||||||
 | 
					    let conn;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        if (useDev) {
 | 
				
			||||||
 | 
					            conn = await dev_pool.getConnection();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            conn = await prod_pool.getConnection();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const rows = await conn.query('SELECT username, email FROM users');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let usernames: string[] = [];
 | 
				
			||||||
 | 
					        let emails: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (let row in rows) {
 | 
				
			||||||
 | 
					            if (row !== 'meta') {
 | 
				
			||||||
 | 
					                usernames.push(rows[row].username);
 | 
				
			||||||
 | 
					                emails.push(rows[row].email);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            'usernames': usernames,
 | 
				
			||||||
 | 
					            'emails': emails
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					        throw err;
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					        if (conn) {
 | 
				
			||||||
 | 
					            conn.end();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Used in the checkUsernameAndEmail method as return value
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface Session {
 | 
				
			||||||
 | 
					    userId: string;
 | 
				
			||||||
 | 
					    sessionId: string;
 | 
				
			||||||
 | 
					    sessionKey: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const registerUser = async (useDev: boolean, username: string, email: string, firstName: string, lastName: string, password: string, ip: string, deviceInfo: string): Promise<Session> => {
 | 
				
			||||||
 | 
					    let conn;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        if (useDev) {
 | 
				
			||||||
 | 
					            conn = await dev_pool.getConnection();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            conn = await prod_pool.getConnection();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const pwHash = bcrypt.hashSync(password, 10);
 | 
				
			||||||
 | 
					        const sessionKey = Guid.create().toString();
 | 
				
			||||||
 | 
					        const sessionKeyHash = bcrypt.hashSync(sessionKey, 10);
 | 
				
			||||||
 | 
					        const verifyEmailCode = Guid.create().toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create user
 | 
				
			||||||
 | 
					        const userQuery = 'INSERT INTO users (username, email, first_name, last_name, password_hash, verify_email_code, registration_date, last_login) VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW()) RETURNING user_id';
 | 
				
			||||||
 | 
					        const userIdRes = await conn.query(userQuery, [username, email, firstName, lastName, pwHash, verifyEmailCode]);
 | 
				
			||||||
 | 
					        await conn.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get user id of the created user
 | 
				
			||||||
 | 
					        let userId: number = -1;
 | 
				
			||||||
 | 
					        for (const row in userIdRes) {
 | 
				
			||||||
 | 
					            if (row !== 'meta' && userIdRes[row].user_id != null) {
 | 
				
			||||||
 | 
					                userId = userIdRes[row].user_id;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let deviceType = 'unknown';
 | 
				
			||||||
 | 
					        if (deviceInfo.includes('PartyPlaner') || deviceInfo.includes('Dart')) {
 | 
				
			||||||
 | 
					            deviceType = 'mobile';
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            deviceType = 'desktop';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create session
 | 
				
			||||||
 | 
					        const sessionQuery = 'INSERT INTO sessions (user_id, session_key_hash, created_Date, last_login, valid_until, valid_days, last_ip, device_info, type) VALUES (?,?,NOW(),NOW(),DATE_ADD(NOW(), INTERVAL 365 DAY),365,?, ?, ?) RETURNING session_id';
 | 
				
			||||||
 | 
					        const sessionIdRes = await conn.query(sessionQuery, [userId, sessionKeyHash, ip, deviceInfo, deviceType]);
 | 
				
			||||||
 | 
					        await conn.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get session id of the created session
 | 
				
			||||||
 | 
					        let sessionId: number = -1;
 | 
				
			||||||
 | 
					        for (const row in sessionIdRes) {
 | 
				
			||||||
 | 
					            if (row !== 'meta' && sessionIdRes[row].session_id != null) {
 | 
				
			||||||
 | 
					                sessionId = sessionIdRes[row].session_id;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            'userId': userId.toString(),
 | 
				
			||||||
 | 
					            'sessionId': sessionId.toString(),
 | 
				
			||||||
 | 
					            'sessionKey': sessionKey
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					        throw err;
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					        if (conn) {
 | 
				
			||||||
 | 
					            conn.end();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Used in the checkUsernameAndEmail method as return value
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface Status {
 | 
				
			||||||
 | 
					    hasProblems: boolean;
 | 
				
			||||||
 | 
					    messages: string[];
 | 
				
			||||||
 | 
					    status: string[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Checks if the given username and email are valid and not yet used by another user
 | 
				
			||||||
 | 
					 * @param useDev If the dev database has to be used
 | 
				
			||||||
 | 
					 * @param username The username to check
 | 
				
			||||||
 | 
					 * @param email The email to check
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const checkUsernameAndEmail = async (useDev: boolean, username: string, email: string): Promise<Status> => {
 | 
				
			||||||
 | 
					    let conn;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        if (useDev) {
 | 
				
			||||||
 | 
					            conn = await dev_pool.getConnection();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            conn = await prod_pool.getConnection();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const usernameQuery = 'SELECT username FROM users WHERE username = ?';
 | 
				
			||||||
 | 
					        const emailQuery = 'SELECT email FROM users WHERE email = ?';
 | 
				
			||||||
 | 
					        const usernameRes = await conn.query(usernameQuery, username);
 | 
				
			||||||
 | 
					        const emailRes = await conn.query(emailQuery, email);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let res: Status = {
 | 
				
			||||||
 | 
					            hasProblems: false,
 | 
				
			||||||
 | 
					            messages: [],
 | 
				
			||||||
 | 
					            status: []
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const usernameRegex = RegExp('^[a-zA-Z0-9\\-\\_]{4,20}$'); // Can contain a-z, A-Z, 0-9, -, _ and has to be 4-20 chars long
 | 
				
			||||||
 | 
					        if (!usernameRegex.test(username)) {
 | 
				
			||||||
 | 
					            // Username doesn't match requirements
 | 
				
			||||||
 | 
					            res.hasProblems = true;
 | 
				
			||||||
 | 
					            res.messages.push('The username contains illegal characters or is not the allowed size');
 | 
				
			||||||
 | 
					            res.status.push('INVALID_USERNAME');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const emailRegex = RegExp('^[a-zA-Z0-9\\-\\_.]{1,30}\\@[a-zA-Z0-9\\-.]{1,20}\\.[a-z]{1,20}$'); // Normal email regex, user@plutodev.de
 | 
				
			||||||
 | 
					        if (!emailRegex.test(email)) {
 | 
				
			||||||
 | 
					            // Username doesn't match requirements
 | 
				
			||||||
 | 
					            res.hasProblems = true;
 | 
				
			||||||
 | 
					            res.messages.push('The email contains illegal characters or is not the allowed size');
 | 
				
			||||||
 | 
					            res.status.push('INVALID_EMAIL');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (usernameRes.length > 0) {
 | 
				
			||||||
 | 
					            // Username is a duplicate
 | 
				
			||||||
 | 
					            res.hasProblems = true;
 | 
				
			||||||
 | 
					            res.messages.push('This username is already in use');
 | 
				
			||||||
 | 
					            res.status.push('DUPLICATE_USERNAME');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (emailRes.length > 0) {
 | 
				
			||||||
 | 
					            // Email is a duplicate
 | 
				
			||||||
 | 
					            res.hasProblems = true;
 | 
				
			||||||
 | 
					            res.messages.push('This email is already in use');
 | 
				
			||||||
 | 
					            res.status.push('DUPLICATE_EMAIL');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					        throw err;
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					        if (conn) {
 | 
				
			||||||
 | 
					            conn.end();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -13,9 +13,9 @@ highlightMarkerRouter.use('/addHighlight', addHighlightRouter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
highlightMarkerRouter.get('/', async (req: Request, res: Response) => {
 | 
					highlightMarkerRouter.get('/', async (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`Pluto Development Twitch Highlight Marker API Endpoint`);
 | 
					        res.status(200).send('Pluto Development Twitch Highlight Marker API Endpoint');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,10 +11,10 @@ export const addHighlightRouter = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
addHighlightRouter.get('/', (req: Request, res: Response) => {
 | 
					addHighlightRouter.get('/', (req: Request, res: Response) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        res.status(200).send(`GET endpoint not defined.`);
 | 
					        res.status(200).send('GET endpoint not defined.');
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,23 +23,23 @@ addHighlightRouter.post('/', (req: Request, res: Response) => {
 | 
				
			||||||
        // Check input params
 | 
					        // Check input params
 | 
				
			||||||
        const body = req.body;
 | 
					        const body = req.body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(body.access_key !== process.env.TWITCH_HIGHLIGHTS_ACCESS_KEY){
 | 
					        if (body.access_key !== process.env.TWITCH_HIGHLIGHTS_ACCESS_KEY) {
 | 
				
			||||||
            // Unauthorized, return error
 | 
					            // Unauthorized, return error
 | 
				
			||||||
            res.type('application/json');
 | 
					            res.type('application/json');
 | 
				
			||||||
            res.status(403).send('{"status": "error", "description": "Unauthorized."}');
 | 
					            res.status(403).send({'status': 'error', 'description': 'Unauthorized.'});
 | 
				
			||||||
        } else if(!body.streamer || !body.stream_id || !body.stream_game || !body.timestamp || !body.description || !body.username){
 | 
					        } else if (!body.streamer || !body.stream_id || !body.stream_game || !body.timestamp || !body.description || !body.username) {
 | 
				
			||||||
            // Missing params, return error
 | 
					            // Missing params, return error
 | 
				
			||||||
            res.type('application/json');
 | 
					            res.type('application/json');
 | 
				
			||||||
            res.status(400).send('{"status": "error", "description": "Missing parameters."}');
 | 
					            res.status(400).send({'status': 'error', 'description': 'Missing parameters.'});
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // Everything fine, return success
 | 
					            // Everything fine, return success
 | 
				
			||||||
            AddHighlightService.createHighlightEntry(body);
 | 
					            AddHighlightService.createHighlightEntry(body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            res.type('application/json');
 | 
					            res.type('application/json');
 | 
				
			||||||
            res.status(200).send('{"status": "success", "description": ""}');
 | 
					            res.status(200).send({'status': 'success', 'description': ''});
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.log('Error handling a request: ' + e.message);
 | 
					        console.log('Error handling a request: ' + e.message);
 | 
				
			||||||
        res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
 | 
					        res.status(500).send({'message': 'Internal Server Error. Try again later.'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,6 @@ const pool = mariadb.createPool({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const createHighlightEntry = async (req_body: any) => {
 | 
					export const createHighlightEntry = async (req_body: any) => {
 | 
				
			||||||
    let conn;
 | 
					    let conn;
 | 
				
			||||||
    let price: any;
 | 
					 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        conn = await pool.getConnection();
 | 
					        conn = await pool.getConnection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user