BETTERZON-113, BETTERZON-114, BETTERZON-115: Adding API endpoint for favorite shops (#61)

This commit is contained in:
Patrick 2021-05-20 17:46:09 +02:00 committed by GitHub
parent 8d2ba797f9
commit 13f1257740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 210 additions and 18 deletions

View File

@ -16,6 +16,7 @@ import {notFoundHandler} from './middleware/notFound.middleware';
import {usersRouter} from './models/users/users.router'; import {usersRouter} from './models/users/users.router';
import {pricealarmsRouter} from './models/pricealarms/pricealarms.router'; import {pricealarmsRouter} from './models/pricealarms/pricealarms.router';
import {contactpersonsRouter} from './models/contact_persons/contact_persons.router'; import {contactpersonsRouter} from './models/contact_persons/contact_persons.router';
import {favoriteshopsRouter} from './models/favorite_shops/favoriteshops.router';
const cookieParser = require('cookie-parser'); const cookieParser = require('cookie-parser');
@ -51,6 +52,7 @@ app.use('/users', usersRouter);
app.use('/vendors', vendorsRouter); app.use('/vendors', vendorsRouter);
app.use('/pricealarms', pricealarmsRouter); app.use('/pricealarms', pricealarmsRouter);
app.use('/contactpersons', contactpersonsRouter); app.use('/contactpersons', contactpersonsRouter);
app.use('/favoriteshops', favoriteshopsRouter);
app.use(errorHandler); app.use(errorHandler);
app.use(notFoundHandler); app.use(notFoundHandler);

View File

@ -0,0 +1,5 @@
export interface FavoriteShop {
favorite_id: number;
vendor_id: number;
user_id: number;
}

View File

@ -0,0 +1,5 @@
import {FavoriteShop} from './favoriteshop.interface';
export interface FavoriteShops {
[key: number]: FavoriteShop;
}

View File

@ -0,0 +1,100 @@
/**
* Required External Modules and Interfaces
*/
import express, {Request, Response} from 'express';
import * as FavoriteShopsService from './favoriteshops.service';
import {FavoriteShop} from './favoriteshop.interface';
import {FavoriteShops} from './favoriteshops.interface';
import * as UserService from '../users/users.service';
/**
* Router Definition
*/
export const favoriteshopsRouter = express.Router();
/**
* Controller Definitions
*/
//GET favoriteshops/
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 priceAlarms = await FavoriteShopsService.getFavoriteShops(user.user_id);
res.status(200).send(priceAlarms);
} catch (e) {
console.log('Error handling a request: ' + e.message);
res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
}
});
// POST favoriteshops/
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);
// Get info for price alarm creation
const vendor_id = req.body.vendor_id;
if (!vendor_id) {
// Missing
res.status(400).send(JSON.stringify({message: 'Missing parameters'}));
return;
}
// Create price alarm
const success = await FavoriteShopsService.createFavoriteShop(user.user_id, vendor_id);
if (success) {
res.status(201).send(JSON.stringify({success: true}));
return;
} else {
res.status(500).send(JSON.stringify({success: false}));
return;
}
} catch (e) {
console.log('Error handling a request: ' + e.message);
res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
}
});
// DELETE favoriteshops/
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);
// Get info for price alarm creation
const favorite_id = parseInt(req.params.id, 10);
if (!favorite_id) {
// Missing
res.status(400).send(JSON.stringify({message: 'Missing parameters'}));
return;
}
// Create price alarm
const success = await FavoriteShopsService.deleteFavoriteShop(user.user_id, favorite_id);
if (success) {
res.status(201).send(JSON.stringify({success: true}));
return;
} else {
res.status(500).send(JSON.stringify({success: false}));
return;
}
} catch (e) {
console.log('Error handling a request: ' + e.message);
res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
}
});

View File

@ -0,0 +1,92 @@
import * as dotenv from 'dotenv';
dotenv.config();
const mariadb = require('mariadb');
const pool = mariadb.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
connectionLimit: 5
});
/**
* Data Model Interfaces
*/
import {FavoriteShop} from './favoriteshop.interface';
import {FavoriteShops} from './favoriteshops.interface';
/**
* Service Methods
*/
/**
* Creates a favorite shop entry for the given user for the given shop
* @param user_id The id of the user to create the favorite shop entry for
* @param vendor_id The id of the vendor to set as favorite
*/
export const createFavoriteShop = async (user_id: number, vendor_id: number): Promise<boolean> => {
let conn;
try {
conn = await pool.getConnection();
const res = await conn.query('INSERT INTO favorite_shops (vendor_id, user_id) VALUES (?, ?)', [vendor_id, user_id]);
return res.affectedRows === 1;
} catch (err) {
throw err;
} finally {
if (conn) {
conn.end();
}
}
};
/**
* Fetches and returns all favorite shops for the given user
* @param user_id
*/
export const getFavoriteShops = async (user_id: number): Promise<FavoriteShops> => {
let conn;
let shops = [];
try {
conn = await pool.getConnection();
const rows = await conn.query('SELECT favorite_id, vendor_id, user_id FROM favorite_shops WHERE user_id = ?', user_id);
for (let row in rows) {
if (row !== 'meta') {
shops.push(rows[row]);
}
}
return shops;
} catch (err) {
throw err;
} finally {
if (conn) {
conn.end();
}
}
};
/**
* Deletes the given favorite shop entry
* @param user_id The id of the user that wants to delete the favorite shop entry
* @param favorite_id The favorite shop to delete
*/
export const deleteFavoriteShop = async (user_id: number, favorite_id: number): Promise<boolean> => {
let conn;
try {
conn = await pool.getConnection();
const res = await conn.query('DELETE FROM favorite_shops WHERE favorite_id = ? AND user_id = ?', [favorite_id, user_id]);
return res.affectedRows === 1;
} catch (err) {
throw err;
} finally {
if (conn) {
conn.end();
}
}
};

View File

@ -35,7 +35,7 @@ pricealarmsRouter.get('/', async (req: Request, res: Response) => {
} }
}); });
// POST pricealarms/create // POST pricealarms/
pricealarmsRouter.post('/', async (req: Request, res: Response) => { pricealarmsRouter.post('/', async (req: Request, res: Response) => {
try { try {
// Authenticate user // Authenticate user
@ -68,7 +68,7 @@ pricealarmsRouter.post('/', async (req: Request, res: Response) => {
} }
}); });
// PUT pricealarms/update // PUT pricealarms/
pricealarmsRouter.put('/', async (req: Request, res: Response) => { pricealarmsRouter.put('/', async (req: Request, res: Response) => {
try { try {
// Authenticate user // Authenticate user

View File

@ -29,17 +29,13 @@ import {PriceAlarms} from './pricealarms.interface';
* @param product_id The id of the product to create the price alarm for * @param product_id The id of the product to create the price alarm for
* @param defined_price The defined price for the price alarm * @param defined_price The defined price for the price alarm
*/ */
export const createPriceAlarm = async (user_id: number, product_id: number, defined_price: number): Promise<Boolean> => { export const createPriceAlarm = async (user_id: number, product_id: number, defined_price: number): Promise<boolean> => {
let conn; let conn;
try { try {
conn = await pool.getConnection(); conn = await pool.getConnection();
const res = await conn.query('INSERT INTO price_alarms (user_id, product_id, defined_price) VALUES (?, ?, ?)', [user_id, product_id, defined_price]); const res = await conn.query('INSERT INTO price_alarms (user_id, product_id, defined_price) VALUES (?, ?, ?)', [user_id, product_id, defined_price]);
if (res.affectedRows === 1) { return res.affectedRows === 1;
return true;
} else {
return false;
}
} catch (err) { } catch (err) {
throw err; throw err;
} finally { } finally {
@ -47,8 +43,6 @@ export const createPriceAlarm = async (user_id: number, product_id: number, defi
conn.end(); conn.end();
} }
} }
return false;
}; };
/** /**
@ -83,17 +77,13 @@ export const getPriceAlarms = async (user_id: number): Promise<PriceAlarms> => {
* @param user_id The id of the user that wants to update the price alarm * @param user_id The id of the user that wants to update the price alarm
* @param defined_price The defined price for the price alarm * @param defined_price The defined price for the price alarm
*/ */
export const updatePriceAlarm = async (alarm_id: number, user_id: number, defined_price: number): Promise<Boolean> => { export const updatePriceAlarm = async (alarm_id: number, user_id: number, defined_price: number): Promise<boolean> => {
let conn; let conn;
try { try {
conn = await pool.getConnection(); conn = await pool.getConnection();
const res = await conn.query('UPDATE price_alarms SET defined_price = ? WHERE alarm_id = ? AND user_id = ?', [defined_price, alarm_id, user_id]); const res = await conn.query('UPDATE price_alarms SET defined_price = ? WHERE alarm_id = ? AND user_id = ?', [defined_price, alarm_id, user_id]);
if (res.affectedRows === 1) { return res.affectedRows === 1;
return true;
} else {
return false;
}
} catch (err) { } catch (err) {
throw err; throw err;
} finally { } finally {
@ -101,6 +91,4 @@ export const updatePriceAlarm = async (alarm_id: number, user_id: number, define
conn.end(); conn.end();
} }
} }
return false;
}; };