Refactor queries and add auth on streamer endpoints
- Move prepared statement definitions to queries module - Add authentication to streamer-only endpoints
This commit is contained in:
		
							parent
							
								
									4555dd6b7f
								
							
						
					
					
						commit
						ccfcc57540
					
				
					 3 changed files with 152 additions and 103 deletions
				
			
		
							
								
								
									
										80
									
								
								src/app.ts
									
										
									
									
									
								
							
							
						
						
									
										80
									
								
								src/app.ts
									
										
									
									
									
								
							| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
import * as config from "./config";
 | 
					import * as config from "./config";
 | 
				
			||||||
import * as requests from "./requests";
 | 
					import * as requests from "./requests";
 | 
				
			||||||
import * as twitch from "./twitch";
 | 
					import * as twitch from "./twitch";
 | 
				
			||||||
 | 
					import * as queries from "./queries";
 | 
				
			||||||
import { URLSearchParams } from "url";
 | 
					import { URLSearchParams } from "url";
 | 
				
			||||||
import express from "express";
 | 
					import express from "express";
 | 
				
			||||||
import session from "express-session";
 | 
					import session from "express-session";
 | 
				
			||||||
| 
						 | 
					@ -84,8 +85,19 @@ app.post("/api/addRequest", async (request, response) => {
 | 
				
			||||||
	.catch((e: any) => errorHandler(request,response,e));
 | 
						.catch((e: any) => errorHandler(request,response,e));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.post("/api/updateRequestState", async (request, response) => { // TODO: Streamer auth
 | 
					app.post("/api/updateRequestState", async (request, response) => {
 | 
				
			||||||
	response.type('text/plain');
 | 
						if (request.session) await validateApiToken(request.session);
 | 
				
			||||||
 | 
						if (!request.session || !request.session.user) {
 | 
				
			||||||
 | 
							response.status(401);
 | 
				
			||||||
 | 
							response.send("Must be logged in");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var streamerid = await db.query(queries.getStreamerId).then((result: pg.QueryResult) => result.rows[0]['userid']);
 | 
				
			||||||
 | 
						if (request.session.user.id != streamerid) {
 | 
				
			||||||
 | 
							response.status(401);
 | 
				
			||||||
 | 
							response.send("You are not the streamer");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (!request.body.url) {
 | 
						if (!request.body.url) {
 | 
				
			||||||
		response.status(400);
 | 
							response.status(400);
 | 
				
			||||||
		response.send("Missing url");
 | 
							response.send("Missing url");
 | 
				
			||||||
| 
						 | 
					@ -93,11 +105,12 @@ app.post("/api/updateRequestState", async (request, response) => { // TODO: Stre
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!request.body.state) {
 | 
						if (!request.body.state) {
 | 
				
			||||||
		response.status(400);
 | 
							response.status(400);
 | 
				
			||||||
		response.send("Missing scoreDiff");
 | 
							response.send("Missing state");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var url = request.body.url as string;
 | 
						var url = request.body.url as string;
 | 
				
			||||||
	var state = request.body.state as string;
 | 
						var state = request.body.state as string;
 | 
				
			||||||
 | 
						response.type('text/plain');
 | 
				
			||||||
	requests.updateRequestState(url,state).then((val: [number,string]) => {
 | 
						requests.updateRequestState(url,state).then((val: [number,string]) => {
 | 
				
			||||||
		response.status(val[0]);
 | 
							response.status(val[0]);
 | 
				
			||||||
		response.send(val[1]);
 | 
							response.send(val[1]);
 | 
				
			||||||
| 
						 | 
					@ -105,8 +118,19 @@ app.post("/api/updateRequestState", async (request, response) => { // TODO: Stre
 | 
				
			||||||
	.catch((e: any) => errorHandler(request,response,e));
 | 
						.catch((e: any) => errorHandler(request,response,e));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.post("/api/updateRequestScore", async (request, response) => { // TODO: Streamer auth
 | 
					app.post("/api/updateRequestScore", async (request, response) => {
 | 
				
			||||||
	response.type('text/plain');
 | 
						if (request.session) await validateApiToken(request.session);
 | 
				
			||||||
 | 
						if (!request.session || !request.session.user) {
 | 
				
			||||||
 | 
							response.status(401);
 | 
				
			||||||
 | 
							response.send("Must be logged in");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var streamerid = await db.query(queries.getStreamerId).then((result: pg.QueryResult) => result.rows[0]['userid']);
 | 
				
			||||||
 | 
						if (request.session.user.id != streamerid) {
 | 
				
			||||||
 | 
							response.status(401);
 | 
				
			||||||
 | 
							response.send("You are not the streamer");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (!request.body.url) {
 | 
						if (!request.body.url) {
 | 
				
			||||||
		response.status(400);
 | 
							response.status(400);
 | 
				
			||||||
		response.send("Missing url");
 | 
							response.send("Missing url");
 | 
				
			||||||
| 
						 | 
					@ -119,6 +143,7 @@ app.post("/api/updateRequestScore", async (request, response) => { // TODO: Stre
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var url = request.body.url as string;
 | 
						var url = request.body.url as string;
 | 
				
			||||||
	var scoreDiff = parseInt(request.body.scoreDiff as string, 10);
 | 
						var scoreDiff = parseInt(request.body.scoreDiff as string, 10);
 | 
				
			||||||
 | 
						response.type('text/plain');
 | 
				
			||||||
	requests.updateRequestScore(url,scoreDiff).then((val: [number,string]) => {
 | 
						requests.updateRequestScore(url,scoreDiff).then((val: [number,string]) => {
 | 
				
			||||||
		response.status(val[0]);
 | 
							response.status(val[0]);
 | 
				
			||||||
		response.send(val[1]);
 | 
							response.send(val[1]);
 | 
				
			||||||
| 
						 | 
					@ -126,14 +151,26 @@ app.post("/api/updateRequestScore", async (request, response) => { // TODO: Stre
 | 
				
			||||||
	.catch((e: any) => errorHandler(request,response,e));
 | 
						.catch((e: any) => errorHandler(request,response,e));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.post("/api/deleteRequest", async (request, response) => { // TODO: Streamer auth
 | 
					app.post("/api/deleteRequest", async (request, response) => {
 | 
				
			||||||
	response.type('text/plain');
 | 
						if (request.session) await validateApiToken(request.session);
 | 
				
			||||||
 | 
						if (!request.session || !request.session.user) {
 | 
				
			||||||
 | 
							response.status(401);
 | 
				
			||||||
 | 
							response.send("Must be logged in");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var streamerid = await db.query(queries.getStreamerId).then((result: pg.QueryResult) => result.rows[0]['userid']);
 | 
				
			||||||
 | 
						if (request.session.user.id != streamerid) {
 | 
				
			||||||
 | 
							response.status(401);
 | 
				
			||||||
 | 
							response.send("You are not the streamer");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (!request.body.url) {
 | 
						if (!request.body.url) {
 | 
				
			||||||
		response.status(400);
 | 
							response.status(400);
 | 
				
			||||||
		response.send("Missing url");
 | 
							response.send("Missing url");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var url = request.body.url as string;
 | 
						var url = request.body.url as string;
 | 
				
			||||||
 | 
						response.type('text/plain');
 | 
				
			||||||
	requests.deleteRequest(url).then((val: [number,string]) => {
 | 
						requests.deleteRequest(url).then((val: [number,string]) => {
 | 
				
			||||||
		response.status(val[0]);
 | 
							response.status(val[0]);
 | 
				
			||||||
		response.send(val[1]);
 | 
							response.send(val[1]);
 | 
				
			||||||
| 
						 | 
					@ -204,28 +241,17 @@ app.get("/callback", async (request, response) => {
 | 
				
			||||||
	if (typeof tokenResponse == 'undefined') throw new Error('tokenResponse is undefined');
 | 
						if (typeof tokenResponse == 'undefined') throw new Error('tokenResponse is undefined');
 | 
				
			||||||
	request.session.tokenpair = { access_token: tokenResponse.access_token, refresh_token: tokenResponse.refresh_token };
 | 
						request.session.tokenpair = { access_token: tokenResponse.access_token, refresh_token: tokenResponse.refresh_token };
 | 
				
			||||||
	request.session.user = (await twitch.apiRequest(request.session.tokenpair,"/users")).data[0];
 | 
						request.session.user = (await twitch.apiRequest(request.session.tokenpair,"/users")).data[0];
 | 
				
			||||||
	const updateUserQuery = {
 | 
						var query = Object.assign(queries.updateUser,{ values: [request.session.user.id,request.session.user.display_name,request.session.user.profile_image_url] });
 | 
				
			||||||
		name: "updateUser",
 | 
					 | 
				
			||||||
		text: "INSERT INTO users (userid,displayName,imageUrl) VALUES ($1,$2,$3)\
 | 
					 | 
				
			||||||
			       ON CONFLICT (userid) DO UPDATE SET displayName = $2, imageUrl = $3"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var query = Object.assign(updateUserQuery,{ values: [request.session.user.id,request.session.user.display_name,request.session.user.profile_image_url] });
 | 
					 | 
				
			||||||
	db.query(query);
 | 
						db.query(query);
 | 
				
			||||||
 | 
						var streamerid = await db.query(queries.getStreamerId).then((result: pg.QueryResult) => result.rows[0]['userid']);
 | 
				
			||||||
	if (typeof (tokenResponse as any).scope != 'undefined') { // Scopes requested - update streamer info
 | 
						if (typeof (tokenResponse as any).scope != 'undefined') { // Scopes requested - update streamer info
 | 
				
			||||||
		const getStreamerIdQuery = {
 | 
					 | 
				
			||||||
			name: "getStreamerId",
 | 
					 | 
				
			||||||
			text: "SELECT userid FROM streamer"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var streamerid = await db.query(getStreamerIdQuery).then((result: pg.QueryResult) => result.rows[0]['userid']);
 | 
					 | 
				
			||||||
		if (request.session.user.id == streamerid) {
 | 
							if (request.session.user.id == streamerid) {
 | 
				
			||||||
			const updateStreamerQuery = {
 | 
								var query = Object.assign(queries.updateStreamer,{ values: [request.session.user.id,JSON.stringify(request.session.tokenpair)] });
 | 
				
			||||||
				name: "updateStreamer",
 | 
					 | 
				
			||||||
				text: "INSERT INTO streamer (userid,tokenPair) VALUES ($1,$2)\
 | 
					 | 
				
			||||||
					       ON CONFLICT (userid) DO UPDATE SET tokenPair = $2"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			var query = Object.assign(updateStreamerQuery,{ values: [request.session.user.id,JSON.stringify(request.session.tokenpair)] });
 | 
					 | 
				
			||||||
			db.query(query);
 | 
								db.query(query);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						} else if (request.session.user.id == streamerid) {
 | 
				
			||||||
 | 
							response.redirect(307, `https://id.twitch.tv/oauth2/authorize?client_id=${config.twitchClientId}&redirect_uri=${config.urlPrefix}/callback&response_type=code&scope=channel:read:subscriptions moderation:read`);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	response.redirect(307, '/');
 | 
						response.redirect(307, '/');
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -233,11 +259,7 @@ app.get("/callback", async (request, response) => {
 | 
				
			||||||
// Frontend templates
 | 
					// Frontend templates
 | 
				
			||||||
app.get("/", async (request, response) => {
 | 
					app.get("/", async (request, response) => {
 | 
				
			||||||
	if (request.session) await validateApiToken(request.session);
 | 
						if (request.session) await validateApiToken(request.session);
 | 
				
			||||||
	const getStreamerInfoQuery = {
 | 
						var streamerInfo = await db.query(queries.getStreamerInfo).then((result: pg.QueryResult) => result.rows[0]);
 | 
				
			||||||
		name: "getStreamerInfo",
 | 
					 | 
				
			||||||
		text: "SELECT displayname,imageurl FROM streamer_user_vw"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var streamerInfo = await db.query(getStreamerInfoQuery).then((result: pg.QueryResult) => result.rows[0]);;
 | 
					 | 
				
			||||||
	if (!request.session || !request.session.user) {
 | 
						if (!request.session || !request.session.user) {
 | 
				
			||||||
		response.render('main.eta', {
 | 
							response.render('main.eta', {
 | 
				
			||||||
			loggedIn: false,
 | 
								loggedIn: false,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										89
									
								
								src/queries.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/queries.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,89 @@
 | 
				
			||||||
 | 
					// User-related queries
 | 
				
			||||||
 | 
					export const updateUser = {
 | 
				
			||||||
 | 
						name: "updateUser",
 | 
				
			||||||
 | 
						text: "INSERT INTO users (userid,displayName,imageUrl) VALUES ($1,$2,$3)\
 | 
				
			||||||
 | 
						ON CONFLICT (userid) DO UPDATE SET displayName = $2, imageUrl = $3"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const insertBan = {
 | 
				
			||||||
 | 
						name: "insertBan",
 | 
				
			||||||
 | 
						text: "INSERT INTO bans (userid) VALUES ($1)"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Streamer-related queries
 | 
				
			||||||
 | 
					export const getStreamerId = {
 | 
				
			||||||
 | 
						name: "getStreamerId",
 | 
				
			||||||
 | 
						text: "SELECT userid FROM streamer"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getStreamerIdToken = {
 | 
				
			||||||
 | 
						name: "getStreamerIdToken",
 | 
				
			||||||
 | 
						text: "SELECT userid,tokenpair FROM streamer"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getStreamerInfo = {
 | 
				
			||||||
 | 
						name: "getStreamerInfo",
 | 
				
			||||||
 | 
						text: "SELECT displayname,imageurl FROM streamer_user_vw"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const updateStreamer = {
 | 
				
			||||||
 | 
						name: "updateStreamer",
 | 
				
			||||||
 | 
						text: "INSERT INTO streamer (userid,tokenPair) VALUES ($1,$2)\
 | 
				
			||||||
 | 
						ON CONFLICT (userid) DO UPDATE SET tokenPair = $2"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Request-related queries
 | 
				
			||||||
 | 
					export const getRequests = {
 | 
				
			||||||
 | 
						name: "getRequests",
 | 
				
			||||||
 | 
						text: "SELECT * FROM get_requests() LIMIT $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getRequestsVoted = {
 | 
				
			||||||
 | 
						name: "getRequestsVoted",
 | 
				
			||||||
 | 
						text: "SELECT * FROM get_requests_voted($2) LIMIT $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getAllRequests = {
 | 
				
			||||||
 | 
						name: "getAllRequests",
 | 
				
			||||||
 | 
						text: "SELECT * FROM get_requests_all() LIMIT $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getAllRequestsVoted = {
 | 
				
			||||||
 | 
						name: "getAllRequestsVoted",
 | 
				
			||||||
 | 
						text: "SELECT * FROM get_requests_all_voted($2) LIMIT $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const checkRequestExists = {
 | 
				
			||||||
 | 
						name: "checkRequestExists",
 | 
				
			||||||
 | 
					 	text: "SELECT * FROM requests WHERE url = $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const addRequest = {
 | 
				
			||||||
 | 
						name: "addRequest",
 | 
				
			||||||
 | 
						text: "CALL add_request($1,$2)"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const checkValidState = {
 | 
				
			||||||
 | 
						name: "checkValidState",
 | 
				
			||||||
 | 
						text: "SELECT * FROM states WHERE state = $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const updateRequestState = {
 | 
				
			||||||
 | 
						name: "updateRequestState",
 | 
				
			||||||
 | 
						text: "UPDATE requests SET state = $2 WHERE url = $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const updateRequestScore = {
 | 
				
			||||||
 | 
						name: "updateRequestScore",
 | 
				
			||||||
 | 
						text: "UPDATE requests SET score = score + $2 WHERE url = $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const deleteRequest = {
 | 
				
			||||||
 | 
						name: "deleteRequest",
 | 
				
			||||||
 | 
						text: "DELETE FROM requests WHERE url = $1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const checkVoteExists = {
 | 
				
			||||||
 | 
						name: "checkVoteExists",
 | 
				
			||||||
 | 
					 	text: "SELECT * FROM votes WHERE requesturl = $1 AND userid = $2"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,69 +1,35 @@
 | 
				
			||||||
 | 
					import * as queries from "./queries"
 | 
				
			||||||
import pg from "pg";
 | 
					import pg from "pg";
 | 
				
			||||||
import db from "./db";
 | 
					import db from "./db";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getRequests
 | 
					 | 
				
			||||||
const getRequestsQuery = {
 | 
					 | 
				
			||||||
	name: "getRequests",
 | 
					 | 
				
			||||||
	text: "SELECT * FROM get_requests() LIMIT $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function getRequests(count: number) {
 | 
					export async function getRequests(count: number) {
 | 
				
			||||||
	var query = Object.assign(getRequestsQuery, { values: [count] });
 | 
						var query = Object.assign(queries.getRequests, { values: [count] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
	.then((result: pg.QueryResult) => result.rows);
 | 
						.then((result: pg.QueryResult) => result.rows);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getAllRequests
 | 
					 | 
				
			||||||
const getAllRequestsQuery = {
 | 
					 | 
				
			||||||
	name: "getAllRequests",
 | 
					 | 
				
			||||||
	text: "SELECT * FROM get_requests_all() LIMIT $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function getAllRequests(count: number) {
 | 
					export async function getAllRequests(count: number) {
 | 
				
			||||||
	var query = Object.assign(getAllRequestsQuery, { values: [count] });
 | 
						var query = Object.assign(queries.getAllRequests, { values: [count] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
	.then((result: pg.QueryResult) => result.rows);
 | 
						.then((result: pg.QueryResult) => result.rows);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getRequestsVoted
 | 
					 | 
				
			||||||
const getRequestsVotedQuery = {
 | 
					 | 
				
			||||||
	name: "getRequestsVoted",
 | 
					 | 
				
			||||||
	text: "SELECT * FROM get_requests_voted($2) LIMIT $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function getRequestsVoted(count: number, user: number) {
 | 
					export async function getRequestsVoted(count: number, user: number) {
 | 
				
			||||||
	var query = Object.assign(getRequestsVotedQuery, { values: [count,user] });
 | 
						var query = Object.assign(queries.getRequestsVoted, { values: [count,user] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
	.then((result: pg.QueryResult) => result.rows);
 | 
						.then((result: pg.QueryResult) => result.rows);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getAllRequestsVoted
 | 
					 | 
				
			||||||
const getAllRequestsVotedQuery = {
 | 
					 | 
				
			||||||
	name: "getAllRequestsVoted",
 | 
					 | 
				
			||||||
	text: "SELECT * FROM get_requests_all_voted($2) LIMIT $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function getAllRequestsVoted(count: number,user: number) {
 | 
					export async function getAllRequestsVoted(count: number,user: number) {
 | 
				
			||||||
	var query = Object.assign(getAllRequestsVotedQuery, { values: [count,user] });
 | 
						var query = Object.assign(queries.getAllRequestsVoted, { values: [count,user] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
	.then((result: pg.QueryResult) => result.rows);
 | 
						.then((result: pg.QueryResult) => result.rows);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// addRequest
 | 
					 | 
				
			||||||
const validUrlRegexes = [
 | 
					const validUrlRegexes = [
 | 
				
			||||||
	/^https:\/\/www\.youtube\.com\/watch\?v=[a-zA-Z0-9_-]{11}$/
 | 
						/^https:\/\/www\.youtube\.com\/watch\?v=[a-zA-Z0-9_-]{11}$/
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const checkRequestExistsQuery = {
 | 
					 | 
				
			||||||
	name: "checkRequestExists",
 | 
					 | 
				
			||||||
 	text: "SELECT * FROM requests WHERE url = $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const addRequestQuery = {
 | 
					 | 
				
			||||||
	name: "addRequest",
 | 
					 | 
				
			||||||
	text: "CALL add_request($1,$2)"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function addRequest(url: string, requester: string): Promise<[number,string]> {
 | 
					export async function addRequest(url: string, requester: string): Promise<[number,string]> {
 | 
				
			||||||
	var validUrl = false;
 | 
						var validUrl = false;
 | 
				
			||||||
	for (var regex of validUrlRegexes) {
 | 
						for (var regex of validUrlRegexes) {
 | 
				
			||||||
| 
						 | 
					@ -73,70 +39,42 @@ export async function addRequest(url: string, requester: string): Promise<[numbe
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!validUrl) return [400, "Invalid song URL."];
 | 
						if (!validUrl) return [400, "Invalid song URL."];
 | 
				
			||||||
	var query = Object.assign(checkRequestExistsQuery, { values: [url] });
 | 
						var query = Object.assign(queries.checkRequestExists, { values: [url] });
 | 
				
			||||||
	var result = await db.query(query);
 | 
						var result = await db.query(query);
 | 
				
			||||||
	if (result.rowCount > 0) {
 | 
						if (result.rowCount > 0) {
 | 
				
			||||||
		return [200,`Song already requested by ${result.rows[0].requester}. State: ${result.rows[0].state}`]
 | 
							return [200,`Song already requested by ${result.rows[0].requester}. State: ${result.rows[0].state}`]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var query = Object.assign(addRequestQuery, { values: [url,requester] });
 | 
						var query = Object.assign(queries.addRequest, { values: [url,requester] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
		.then(() => [201,"Song request added."] as [number,string]);
 | 
							.then(() => [201,"Song request added."] as [number,string]);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// updateRequestState
 | 
					 | 
				
			||||||
const checkValidStateQuery = {
 | 
					 | 
				
			||||||
	name: "checkValidState",
 | 
					 | 
				
			||||||
	text: "SELECT * FROM states WHERE state = $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const updateRequestStateQuery = {
 | 
					 | 
				
			||||||
	name: "updateRequestState",
 | 
					 | 
				
			||||||
	text: "UPDATE requests SET state = $2 WHERE url = $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function updateRequestState(url: string, state: string): Promise<[number,string]> {
 | 
					export async function updateRequestState(url: string, state: string): Promise<[number,string]> {
 | 
				
			||||||
	var query = Object.assign(checkValidStateQuery, { values: [state] });
 | 
						var query = Object.assign(queries.checkValidState, { values: [state] });
 | 
				
			||||||
	var result = await db.query(query);
 | 
						var result = await db.query(query);
 | 
				
			||||||
	if (result.rowCount < 1) {
 | 
						if (result.rowCount < 1) {
 | 
				
			||||||
		return [400,"Invalid state"]
 | 
							return [400,"Invalid state"]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var query = Object.assign(updateRequestStateQuery, { values: [url,state] });
 | 
						var query = Object.assign(queries.updateRequestState, { values: [url,state] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
	.then(() => [200,"Song request state updated."] as [number,string]);
 | 
						.then(() => [200,"Song request state updated."] as [number,string]);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// updateRequestScore
 | 
					 | 
				
			||||||
const updateRequestScoreQuery = {
 | 
					 | 
				
			||||||
	name: "updateRequestScore",
 | 
					 | 
				
			||||||
	text: "UPDATE requests SET score = score + $2 WHERE url = $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function updateRequestScore(url: string, scoreDiff: number): Promise<[number,string]> {
 | 
					export async function updateRequestScore(url: string, scoreDiff: number): Promise<[number,string]> {
 | 
				
			||||||
	var query = Object.assign(updateRequestScoreQuery, { values: [url,scoreDiff] });
 | 
						var query = Object.assign(queries.updateRequestScore, { values: [url,scoreDiff] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
		.then(() => [200,"Song request score updated."] as [number,string]);
 | 
							.then(() => [200,"Song request score updated."] as [number,string]);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// deleteRequest
 | 
					 | 
				
			||||||
const deleteRequestQuery = {
 | 
					 | 
				
			||||||
	name: "deleteRequest",
 | 
					 | 
				
			||||||
	text: "DELETE FROM requests WHERE url = $1"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function deleteRequest(url: string): Promise<[number,string]> {
 | 
					export async function deleteRequest(url: string): Promise<[number,string]> {
 | 
				
			||||||
	var query = Object.assign(deleteRequestQuery, { values: [url] });
 | 
						var query = Object.assign(queries.deleteRequest, { values: [url] });
 | 
				
			||||||
	return db.query(query)
 | 
						return db.query(query)
 | 
				
			||||||
	.then(() => [200,"Song request deleted."] as [number,string]);
 | 
						.then(() => [200,"Song request deleted."] as [number,string]);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const checkVoteExistsQuery = {
 | 
					 | 
				
			||||||
	name: "checkVoteExists",
 | 
					 | 
				
			||||||
 	text: "SELECT * FROM votes WHERE requesturl = $1 AND userid = $2"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function addVote(url: string, user: string): Promise<[number,string]> {
 | 
					export async function addVote(url: string, user: string): Promise<[number,string]> {
 | 
				
			||||||
	var query = Object.assign(checkVoteExistsQuery, { values: [url,user] });
 | 
						var query = Object.assign(queries.checkVoteExists, { values: [url,user] });
 | 
				
			||||||
	var result = await db.query(query);
 | 
						var result = await db.query(query);
 | 
				
			||||||
	if (result.rowCount > 0) {
 | 
						if (result.rowCount > 0) {
 | 
				
			||||||
		return [200,`Song already voted on`]
 | 
							return [200,`Song already voted on`]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue