From a25753bcfcb0b28afa492a00c4c4630035770f35 Mon Sep 17 00:00:00 2001 From: Ayushya Amitabh Date: Sun, 31 May 2020 18:57:17 -0400 Subject: [PATCH] v1.3.0-beta/release --- app/src/Api.js | 5 +- app/src/index.css | 1 + functions/app.js | 28 +++- functions/index.js | 7 +- functions/modules/authenticator.js | 60 ++++---- functions/modules/createRoom.js | 31 ++-- functions/modules/index.js | 6 - functions/modules/joinRoom.js | 77 ++++------ functions/modules/sendMessage.js | 4 +- functions/modules/updatePlayer.js | 58 +++---- functions/modules2/authenticator.js | 42 ++++++ functions/modules2/cleanUpRoom.js | 32 ++++ functions/modules2/createRoom.js | 65 ++++++++ functions/modules2/deleteRoom.js | 62 ++++++++ functions/modules2/index.js | 29 ++++ functions/modules2/joinRoom.js | 141 ++++++++++++++++++ functions/modules2/leaveRoom.js | 19 +++ functions/modules2/scheduledCleanUp.js | 36 +++++ functions/modules2/sendMessage.js | 46 ++++++ functions/modules2/timeDiff.js | 7 + .../{modules => modules2}/tokenRefresher.js | 0 .../{modules => modules2}/tokenValidator.js | 0 functions/modules2/updatePlayer.js | 82 ++++++++++ .../{modules => modules2}/updateVoxeet.js | 0 24 files changed, 682 insertions(+), 156 deletions(-) create mode 100644 functions/modules2/authenticator.js create mode 100644 functions/modules2/cleanUpRoom.js create mode 100644 functions/modules2/createRoom.js create mode 100644 functions/modules2/deleteRoom.js create mode 100644 functions/modules2/index.js create mode 100644 functions/modules2/joinRoom.js create mode 100644 functions/modules2/leaveRoom.js create mode 100644 functions/modules2/scheduledCleanUp.js create mode 100644 functions/modules2/sendMessage.js create mode 100644 functions/modules2/timeDiff.js rename functions/{modules => modules2}/tokenRefresher.js (100%) rename functions/{modules => modules2}/tokenValidator.js (100%) create mode 100644 functions/modules2/updatePlayer.js rename functions/{modules => modules2}/updateVoxeet.js (100%) diff --git a/app/src/Api.js b/app/src/Api.js index ba48afb..5f24bbe 100644 --- a/app/src/Api.js +++ b/app/src/Api.js @@ -1,9 +1,8 @@ /*global chrome*/ const API_HOST = window.location.href.startsWith('http://localhost') - ? 'http://localhost:5000/watch-party-crx/us-central1/widgets' - : // : 'https://us-central1-watch-party-crx.cloudfunctions.net/widgets'; - 'http://localhost:5000/watch-party-crx/us-central1/widgets'; + ? 'http://localhost:5000/watch-party-crx/us-central1/widgets2' + : 'https://us-central1-watch-party-crx.cloudfunctions.net/widgets2'; export const PLAYER_STATUS = { PLAYING: 'PLAYING', diff --git a/app/src/index.css b/app/src/index.css index 7d2983e..84864fe 100644 --- a/app/src/index.css +++ b/app/src/index.css @@ -151,6 +151,7 @@ body.amazon-prime textarea:focus { .party-notification-container .MuiPaper-root { color: white; background-color: black; + font-size: 1rem !important; } @keyframes showbutton { 0% { diff --git a/functions/app.js b/functions/app.js index c1fd928..f1d466d 100644 --- a/functions/app.js +++ b/functions/app.js @@ -1,19 +1,33 @@ const FunctionModules = require('./modules/index'); +const FunctionModules2 = require('./modules2/index'); const express = require('express'); const cors = require('cors'); -const app = express(); +// VERSION 1 +const app = express(); app.use(cors({ origin: true })); app.use(FunctionModules.authenticator); - -app.get('/validator', FunctionModules.tokenValidator); -app.get('/refresher/:token', FunctionModules.tokenRefresher); app.post('/create', FunctionModules.createRoom); app.post('/join', FunctionModules.joinRoom); app.post('/message', FunctionModules.sendMessage); -app.post('/updatePlayer', FunctionModules.updatePlayer); -app.post('/updateVoxeet', FunctionModules.updateVoxeet); app.delete('/leave/:rid/users/:uid', FunctionModules.leaveRoom); app.delete('/delete/:rid', FunctionModules.deleteRoom); +app.post('/updatePlayer', FunctionModules.updatePlayer); +// VERSION 2 +const app2 = express(); +app2.use(cors({ origin: true })); +app2.use(FunctionModules2.authenticator); +app2.get('/validator', FunctionModules2.tokenValidator); +app2.get('/refresher/:token', FunctionModules2.tokenRefresher); +app2.post('/create', FunctionModules2.createRoom); +app2.post('/join', FunctionModules2.joinRoom); +app2.post('/message', FunctionModules2.sendMessage); +app2.post('/updatePlayer', FunctionModules2.updatePlayer); +app2.post('/updateVoxeet', FunctionModules2.updateVoxeet); +app2.delete('/leave/:rid/users/:uid', FunctionModules2.leaveRoom); +app2.delete('/delete/:rid', FunctionModules2.deleteRoom); -module.exports = app; +module.exports = { + v1: app, + v2: app2, +}; diff --git a/functions/index.js b/functions/index.js index c68da7b..c0bf5a5 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1,4 +1,4 @@ -const FunctionModules = require('./modules/index'); +const FunctionModules = require('./modules2/index'); const functions = require('firebase-functions'); const secret = require('./FirebaseSecret.json'); const admin = require('firebase-admin'); @@ -11,7 +11,10 @@ const FIREBASE_OPTIONS = { admin.initializeApp(FIREBASE_OPTIONS); -exports.widgets = functions.https.onRequest(REST); +// VERSION 1 +exports.widgets = functions.https.onRequest(REST.v1); +// VERSION 2 +exports.widgets2 = functions.https.onRequest(REST.v2); exports.scheduledCleanUp = functions.pubsub .schedule('every 60 minutes') diff --git a/functions/modules/authenticator.js b/functions/modules/authenticator.js index 878697c..9bf1a02 100644 --- a/functions/modules/authenticator.js +++ b/functions/modules/authenticator.js @@ -6,37 +6,31 @@ module.exports = (req, res, next) => { res.status(200).send(); return next(); } - if (req.headers.authorization) { - try { - const token = req.headers.authorization.split(' ')[1]; - const reqToken = token.split(':')[0]; - const reqUid = token.split(':')[1]; - admin - .auth() - .verifyIdToken(reqToken) - .then((user) => { - if (user.uid === reqUid) { - console.info('Verified Token - UID - ', reqUid); - if (req.method === 'POST') { - const bodydata = JSON.parse(req.body); - bodydata.uid = user.uid; - req.body = JSON.stringify(bodydata); - } - if (req.method === 'GET' || req.method === 'DELETE') { - req.body = JSON.stringify({ uid: user.uid }); - } - return next(); - } else { - return res.status(401).send({ message: 'Unauthorized' }); - } - }) - .catch((err) => { - console.error('Failed Auth - ', req.headers.authorization, '\n', err); - return res.status(500).send({ message: 'Unable to verify user token' }); - }); - } catch (err) { - console.log(err); - return res.status(401).send({ message: 'Something went wrong when authorizing' }); - } - } else return res.status(401).send({ message: 'Got no user token' }); + const token = req.headers.authorization.split(' ')[1]; + const reqToken = token.split(':')[0]; + const reqUid = token.split(':')[1]; + admin + .auth() + .verifyIdToken(reqToken) + .then((user) => { + if (user.uid === reqUid) { + console.info('Verified Token - UID - ', reqUid); + if (req.method === 'POST') { + const bodydata = JSON.parse(req.body); + bodydata.uid = user.uid; + req.body = JSON.stringify(bodydata); + } + if (req.method === 'GET' || req.method === 'DELETE') { + req.body = JSON.stringify({ uid: user.uid }); + } + return next(); + } else { + return res.status(401).send({ message: 'Unauthorized' }); + } + }) + .catch((err) => { + console.error('Failed Auth - ', req.headers.authorization, '\n', err); + return res.status(500).send({ message: 'Unable to verify user token', error: err }); + }); + return null; }; diff --git a/functions/modules/createRoom.js b/functions/modules/createRoom.js index 5927774..9e8cd71 100644 --- a/functions/modules/createRoom.js +++ b/functions/modules/createRoom.js @@ -4,26 +4,16 @@ module.exports = async (req, res) => { const bodydata = JSON.parse(req.body); console.log('Requested Create - UID - ', bodydata.uid); if (!bodydata.userName) res.status(400).send({ message: 'Missing user name' }); - if (!bodydata.partyName) res.status(400).send({ message: 'Missing party name' }); - if (!bodydata.partyPin) res.status(400).send({ message: 'Missing party pin' }); - const roomNameTaken = await admin + const roomId = await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) - .get() - .then((docSnap) => docSnap.exists); - if (roomNameTaken) return res.status(409).send({ message: 'That party name is already taken' }); - await admin - .firestore() - .collection('rooms') - .doc(bodydata.partyName) - .set({ - name: bodydata.partyName, - pin: bodydata.partyPin, + .add({ + name: bodydata.roomName, player: bodydata.player, createdAt: new Date(), updatedAt: new Date(), }) + .then((ref) => ref.id) .catch((err) => { res.status(500).send({ message: 'Unable to start party.' }); console.error(err); @@ -31,7 +21,7 @@ module.exports = async (req, res) => { await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(roomId) .collection('messages') .add({ uid: '', @@ -40,15 +30,12 @@ module.exports = async (req, res) => { time: new Date(), }) .catch((err) => { - console.error( - `Failed to add system create party message : \n\t Room: ${bodydata.partyName}`, - err - ); + console.error(`Failed to add system create party message : \n\t Room: ${roomId}`, err); }); await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(roomId) .collection('users') .doc(bodydata.uid) .set({ @@ -57,9 +44,9 @@ module.exports = async (req, res) => { }) .catch((err) => { console.error( - `Failed to set admin when creating party : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + `Failed to set admin when creating party : \n\t Room: ${roomId} \n\t User: ${bodydata.uid}`, err ); }); - res.status(201).send({ roomId: bodydata.partyName, message: 'Started a party!' }); + res.status(201).send({ roomId, message: 'Started a party!' }); }; diff --git a/functions/modules/index.js b/functions/modules/index.js index 19d7b75..aabb20c 100644 --- a/functions/modules/index.js +++ b/functions/modules/index.js @@ -8,9 +8,6 @@ const leaveRoom = require('./leaveRoom'); const deleteRoom = require('./deleteRoom'); const timeDiff = require('./timeDiff'); const updatePlayer = require('./updatePlayer'); -const tokenValidator = require('./tokenValidator'); -const tokenRefresher = require('./tokenRefresher'); -const updateVoxeet = require('./updateVoxeet'); module.exports = { authenticator, @@ -23,7 +20,4 @@ module.exports = { scheduledCleanUp, cleanUpRoom, timeDiff, - tokenValidator, - tokenRefresher, - updateVoxeet, }; diff --git a/functions/modules/joinRoom.js b/functions/modules/joinRoom.js index b882c70..d68f97d 100644 --- a/functions/modules/joinRoom.js +++ b/functions/modules/joinRoom.js @@ -2,72 +2,46 @@ const admin = require('firebase-admin'); module.exports = async (req, res) => { const bodydata = JSON.parse(req.body); - console.log('Requested Join - UID - ', bodydata.uid, '\n\tRoom - ', bodydata.partyName); - // GET ROOM EXISTS, ROOM SOURCE, & ROOM PIN - const [exists, roomSource, roomPin] = await admin + console.log('Requested Join - UID - ', bodydata.uid, '\n\tRoom - ', bodydata.roomId); + const [exists, roomSource] = await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(bodydata.roomId) .get() - .then((roomSnap) => [ - roomSnap.exists, - roomSnap.exists ? roomSnap.data().player.source : '', - roomSnap.exists ? roomSnap.data().pin : '', - ]) + .then((roomSnap) => [roomSnap.exists, roomSnap.exists ? roomSnap.data().player.source : '']) .catch((err) => { console.error( - `Failed to get room when joining room : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + `Failed to get room when joining room : \n\t Room: ${bodydata.roomId} \n\t User: ${bodydata.uid}`, err ); }); - if (exists && roomPin !== bodydata.partyPin) - return res.status(401).send({ message: 'Incorrect party pin' }); - // GET IF USER EXISTS AND IS ADMIN - const [userExists, userAdmin, userName] = await admin + const [userExists, userAdmin] = await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(bodydata.roomId) .collection('users') .doc(bodydata.uid) .get() - .then((userSnap) => [ - userSnap.exists, - userSnap.exists ? userSnap.data().admin : false, - userSnap.exists ? userSnap.data().name : '', - ]) + .then((userSnap) => [userSnap.exists, userSnap.exists ? userSnap.data().admin : false]) .catch((err) => { console.error( - `Failed to get user when joining room : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + `Failed to get user when joining room : \n\t Room: ${bodydata.roomId} \n\t User: ${bodydata.uid}`, err ); }); - // IF USER PRE-EXISTS AND SAME SOURCE - JOIN - if (userExists && exists && roomSource === bodydata.source) { - // UPDATE NAME IF NEEDED - if (userName !== bodydata.userName) { - await admin - .firestore() - .collection('rooms') - .doc(bodydata.partyName) - .collection('users') - .doc(body.uid) - .update({ name: bodydata.userName }); - } - res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' }); - } - // USER DOES NOT PRE-EXIST BUT SAME SOURCE AND RIGHT PIN + if (userExists && exists && roomSource === bodydata.source) + res.status(200).send({ roomId: bodydata.roomId, message: 'Joined a party' }); else if ( !userExists && exists && - bodydata.partyName && + bodydata.roomId && bodydata.userName && - roomSource === bodydata.source && - roomPin === bodydata.partyPin + roomSource === bodydata.source ) { await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(bodydata.roomId) .collection('messages') .add({ uid: '', @@ -77,14 +51,14 @@ module.exports = async (req, res) => { }) .catch((err) => { console.error( - `Failed to add system join party message : \n\t Room: ${partyName} \n\t ${bodydata.uid}`, + `Failed to add system join party message : \n\t Room: ${roomId} \n\t ${bodydata.uid}`, err ); }); await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(bodydata.roomId) .collection('users') .doc(bodydata.uid) .set({ @@ -93,37 +67,36 @@ module.exports = async (req, res) => { }) .catch((err) => { console.error( - `Failed to set admin when joining party : \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`, + `Failed to set admin when joining party : \n\t Room: ${roomId} \n\t User: ${bodydata.uid}`, err ); }); await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(bodydata.roomId) .update({ updatedAt: new Date(), }) .catch((err) => { console.error( - `Failed to set updated time when joining party : \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`, + `Failed to set updated time when joining party : \n\t Room: ${roomId} \n\t User: ${bodydata.uid}`, err ); }); - res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' }); - } - // ONLY WRONG SOURCE + res.status(200).send({ roomId: bodydata.roomId, message: 'Joined a party' }); + } else if (!userExists && !bodydata.userName) + res.status(400).send({ message: 'Missing user name' }); else if (exists && roomSource !== bodydata.source) { - // MOVE SOURCE IF ADMIN if (userAdmin === true) { await admin .firestore() .collection('rooms') - .doc(bodydata.partyName) + .doc(bodydata.roomId) .update({ player: { showName: null, - source: null, + source: roomSource, status: 'NOT_PLAYING', time: 0, updatedBy: bodydata.uid, @@ -131,7 +104,7 @@ module.exports = async (req, res) => { }) .catch(() => { console.error( - `Failed to update player source when admin joining party \n\t Room: ${partyName} \n\t User: ${bodydata.uid}` + `Failed to update player source when admin joining party \n\t Room: ${roomId} \n\t User: ${bodydata.uid}` ); res.status(500).send({ message: 'Unable to move party, please try again' }); }); diff --git a/functions/modules/sendMessage.js b/functions/modules/sendMessage.js index 577d89f..d9b4581 100644 --- a/functions/modules/sendMessage.js +++ b/functions/modules/sendMessage.js @@ -1,7 +1,7 @@ const admin = require('firebase-admin'); module.exports = async (req, res) => { - const { name, text, time, uid, roomId, type } = JSON.parse(req.body); + const { name, text, uid, roomId, type } = JSON.parse(req.body); const roomExists = await admin .firestore() @@ -24,7 +24,7 @@ module.exports = async (req, res) => { }) .catch((err) => { console.error(`Failed to send message to party : \n\t Room: ${roomId} \n\t ${uid}`, err); - res.status(500).send({ message: "Couldn't send your message", ...messageErr }); + res.status(500).send({ message: "Couldn't send your message", error: messageErr }); }); await admin .firestore() diff --git a/functions/modules/updatePlayer.js b/functions/modules/updatePlayer.js index 777a155..a38087c 100644 --- a/functions/modules/updatePlayer.js +++ b/functions/modules/updatePlayer.js @@ -2,18 +2,18 @@ const admin = require('firebase-admin'); module.exports = async (req, res) => { const { player, roomId, uid, showChanged, userName } = JSON.parse(req.body); - // const statusString = - // player.status === 'PLAYING' - // ? 'started playing from' - // : player.status === 'PAUSED' - // ? 'paused at' - // : player.status === 'NOT_PLAYING' - // ? 'stopped at' - // : 'is at'; - // const timeString = - // player.time > 3600 - // ? new Date(player.time * 1000).toISOString().substr(11, 8) - // : new Date(player.time * 1000).toISOString().substr(14, 5); + const statusString = + player.status === 'PLAYING' + ? 'started playing from' + : player.status === 'PAUSED' + ? 'paused at' + : player.status === 'NOT_PLAYING' + ? 'stopped at' + : 'is at'; + const timeString = + player.time > 3600 + ? new Date(player.time * 1000).toISOString().substr(11, 8) + : new Date(player.time * 1000).toISOString().substr(14, 5); const [roomExists, roomData] = await admin .firestore() .collection('rooms') @@ -55,23 +55,23 @@ module.exports = async (req, res) => { console.error(`Failed to update player : \n\t Room: ${roomId} \n\t ${uid}`, err); res.status(500).send({ message: "Uh oh party could't be synced", err }); }); - // await admin - // .firestore() - // .collection('rooms') - // .doc(roomId) - // .collection('messages') - // .add({ - // uid: '', - // name: '', - // text: `${userName} ${statusString} ${timeString}`, - // time: new Date(), - // }) - // .catch((err) => { - // console.error( - // `Failed to add system update player message : \n\t Room: ${roomId} \n\t ${uid}`, - // err - // ); - // }); + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${userName} ${statusString} ${timeString}`, + time: new Date(), + }) + .catch((err) => { + console.error( + `Failed to add system update player message : \n\t Room: ${roomId} \n\t ${uid}`, + err + ); + }); return res.status(200).send({ message: 'Synced party player' }); } else { return res.status(208).send({ message: 'Player already up to date' }); diff --git a/functions/modules2/authenticator.js b/functions/modules2/authenticator.js new file mode 100644 index 0000000..878697c --- /dev/null +++ b/functions/modules2/authenticator.js @@ -0,0 +1,42 @@ +const admin = require('firebase-admin'); + +module.exports = (req, res, next) => { + res.set('Access-Control-Allow-Origin', ['*']); + if (req.method === 'OPTIONS') { + res.status(200).send(); + return next(); + } + if (req.headers.authorization) { + try { + const token = req.headers.authorization.split(' ')[1]; + const reqToken = token.split(':')[0]; + const reqUid = token.split(':')[1]; + admin + .auth() + .verifyIdToken(reqToken) + .then((user) => { + if (user.uid === reqUid) { + console.info('Verified Token - UID - ', reqUid); + if (req.method === 'POST') { + const bodydata = JSON.parse(req.body); + bodydata.uid = user.uid; + req.body = JSON.stringify(bodydata); + } + if (req.method === 'GET' || req.method === 'DELETE') { + req.body = JSON.stringify({ uid: user.uid }); + } + return next(); + } else { + return res.status(401).send({ message: 'Unauthorized' }); + } + }) + .catch((err) => { + console.error('Failed Auth - ', req.headers.authorization, '\n', err); + return res.status(500).send({ message: 'Unable to verify user token' }); + }); + } catch (err) { + console.log(err); + return res.status(401).send({ message: 'Something went wrong when authorizing' }); + } + } else return res.status(401).send({ message: 'Got no user token' }); +}; diff --git a/functions/modules2/cleanUpRoom.js b/functions/modules2/cleanUpRoom.js new file mode 100644 index 0000000..f33a8ff --- /dev/null +++ b/functions/modules2/cleanUpRoom.js @@ -0,0 +1,32 @@ +const admin = require('firebase-admin'); + +module.exports = async (roomId) => { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .listDocuments() + .then((messages) => messages.forEach((message) => message.delete())) + .catch((err) => { + console.error(`Failed to run auto clean up (delete room messages) @ ${roomId}`, err); + }); + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('users') + .listDocuments() + .then((users) => users.forEach((user) => user.delete())) + .catch((err) => { + console.error(`Failed to run auto clean up (delete room users) @ ${roomId}`, err); + }); + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .delete() + .catch((err) => { + console.error(`Failed to run auto clean up (delete room) @ ${roomId}`, err); + }); +}; diff --git a/functions/modules2/createRoom.js b/functions/modules2/createRoom.js new file mode 100644 index 0000000..5927774 --- /dev/null +++ b/functions/modules2/createRoom.js @@ -0,0 +1,65 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const bodydata = JSON.parse(req.body); + console.log('Requested Create - UID - ', bodydata.uid); + if (!bodydata.userName) res.status(400).send({ message: 'Missing user name' }); + if (!bodydata.partyName) res.status(400).send({ message: 'Missing party name' }); + if (!bodydata.partyPin) res.status(400).send({ message: 'Missing party pin' }); + const roomNameTaken = await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .get() + .then((docSnap) => docSnap.exists); + if (roomNameTaken) return res.status(409).send({ message: 'That party name is already taken' }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .set({ + name: bodydata.partyName, + pin: bodydata.partyPin, + player: bodydata.player, + createdAt: new Date(), + updatedAt: new Date(), + }) + .catch((err) => { + res.status(500).send({ message: 'Unable to start party.' }); + console.error(err); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${bodydata.userName} started the party.`, + time: new Date(), + }) + .catch((err) => { + console.error( + `Failed to add system create party message : \n\t Room: ${bodydata.partyName}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .set({ + admin: true, + name: bodydata.userName, + }) + .catch((err) => { + console.error( + `Failed to set admin when creating party : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + res.status(201).send({ roomId: bodydata.partyName, message: 'Started a party!' }); +}; diff --git a/functions/modules2/deleteRoom.js b/functions/modules2/deleteRoom.js new file mode 100644 index 0000000..e0b37fb --- /dev/null +++ b/functions/modules2/deleteRoom.js @@ -0,0 +1,62 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + console.log('Requested Delete - Room - ', req.params.rid); + console.log(req.body); + const isAdmin = await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('users') + .doc(JSON.parse(req.body).uid) + .get() + .then((v) => { + if (v.exists) { + return v.data().admin; + } + return false; + }); + if (!isAdmin) { + console.log('[UNAUTHORIZED] Requested Delete - Room - ', req.params.rid); + res.status(401).send({ message: 'Not authorized to end this party.' }); + return; + } + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('messages') + .listDocuments() + .then((messages) => messages.forEach((message) => message.delete())) + .catch((err) => { + console.error( + `Failed to delete room messages : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('users') + .listDocuments() + .then((users) => users.forEach((user) => user.delete())) + .catch((err) => { + console.error( + `Failed to delete room users : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .delete() + .catch((err) => { + console.error( + `Failed to delete room : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ); + }); + res.status(200).send({ message: 'Ended the party' }); +}; diff --git a/functions/modules2/index.js b/functions/modules2/index.js new file mode 100644 index 0000000..19d7b75 --- /dev/null +++ b/functions/modules2/index.js @@ -0,0 +1,29 @@ +const authenticator = require('./authenticator'); +const cleanUpRoom = require('./cleanUpRoom'); +const scheduledCleanUp = require('./scheduledCleanUp'); +const createRoom = require('./createRoom'); +const joinRoom = require('./joinRoom'); +const sendMessage = require('./sendMessage'); +const leaveRoom = require('./leaveRoom'); +const deleteRoom = require('./deleteRoom'); +const timeDiff = require('./timeDiff'); +const updatePlayer = require('./updatePlayer'); +const tokenValidator = require('./tokenValidator'); +const tokenRefresher = require('./tokenRefresher'); +const updateVoxeet = require('./updateVoxeet'); + +module.exports = { + authenticator, + createRoom, + joinRoom, + sendMessage, + updatePlayer, + leaveRoom, + deleteRoom, + scheduledCleanUp, + cleanUpRoom, + timeDiff, + tokenValidator, + tokenRefresher, + updateVoxeet, +}; diff --git a/functions/modules2/joinRoom.js b/functions/modules2/joinRoom.js new file mode 100644 index 0000000..b882c70 --- /dev/null +++ b/functions/modules2/joinRoom.js @@ -0,0 +1,141 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const bodydata = JSON.parse(req.body); + console.log('Requested Join - UID - ', bodydata.uid, '\n\tRoom - ', bodydata.partyName); + // GET ROOM EXISTS, ROOM SOURCE, & ROOM PIN + const [exists, roomSource, roomPin] = await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .get() + .then((roomSnap) => [ + roomSnap.exists, + roomSnap.exists ? roomSnap.data().player.source : '', + roomSnap.exists ? roomSnap.data().pin : '', + ]) + .catch((err) => { + console.error( + `Failed to get room when joining room : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + if (exists && roomPin !== bodydata.partyPin) + return res.status(401).send({ message: 'Incorrect party pin' }); + // GET IF USER EXISTS AND IS ADMIN + const [userExists, userAdmin, userName] = await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .get() + .then((userSnap) => [ + userSnap.exists, + userSnap.exists ? userSnap.data().admin : false, + userSnap.exists ? userSnap.data().name : '', + ]) + .catch((err) => { + console.error( + `Failed to get user when joining room : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + // IF USER PRE-EXISTS AND SAME SOURCE - JOIN + if (userExists && exists && roomSource === bodydata.source) { + // UPDATE NAME IF NEEDED + if (userName !== bodydata.userName) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(body.uid) + .update({ name: bodydata.userName }); + } + res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' }); + } + // USER DOES NOT PRE-EXIST BUT SAME SOURCE AND RIGHT PIN + else if ( + !userExists && + exists && + bodydata.partyName && + bodydata.userName && + roomSource === bodydata.source && + roomPin === bodydata.partyPin + ) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${bodydata.userName} joined the party.`, + time: new Date(), + }) + .catch((err) => { + console.error( + `Failed to add system join party message : \n\t Room: ${partyName} \n\t ${bodydata.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .set({ + admin: false, + name: bodydata.userName, + }) + .catch((err) => { + console.error( + `Failed to set admin when joining party : \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .update({ + updatedAt: new Date(), + }) + .catch((err) => { + console.error( + `Failed to set updated time when joining party : \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' }); + } + // ONLY WRONG SOURCE + else if (exists && roomSource !== bodydata.source) { + // MOVE SOURCE IF ADMIN + if (userAdmin === true) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .update({ + player: { + showName: null, + source: null, + status: 'NOT_PLAYING', + time: 0, + updatedBy: bodydata.uid, + }, + }) + .catch(() => { + console.error( + `Failed to update player source when admin joining party \n\t Room: ${partyName} \n\t User: ${bodydata.uid}` + ); + res.status(500).send({ message: 'Unable to move party, please try again' }); + }); + res.status(200).send({ message: `Moved party to ${roomSource}` }); + } else res.status(417).send({ message: `This party is on ${roomSource}` }); + } else res.status(404).send({ message: 'Party Not Found' }); +}; diff --git a/functions/modules2/leaveRoom.js b/functions/modules2/leaveRoom.js new file mode 100644 index 0000000..fe0ba5b --- /dev/null +++ b/functions/modules2/leaveRoom.js @@ -0,0 +1,19 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + console.log('Requested Leave - UID - ', req.params.uid, '\n\tRoom - ', req.params.rid); + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('users') + .doc(req.params.uid) + .delete() + .catch((err) => + console.error( + `Failed to remove user from party : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ) + ); + res.status(200).send({ message: 'Left the party' }); +}; diff --git a/functions/modules2/scheduledCleanUp.js b/functions/modules2/scheduledCleanUp.js new file mode 100644 index 0000000..8fcb181 --- /dev/null +++ b/functions/modules2/scheduledCleanUp.js @@ -0,0 +1,36 @@ +const admin = require('firebase-admin'); +const FunctionModules = require('./index'); + +module.exports = async () => { + const startedTime = new Date(); + const roomList = await admin + .firestore() + .collection('rooms') + .listDocuments() + .then((rL) => rL) + .catch((err) => { + console.error( + `Failed to run auto clean up (get room list) @ ${new Date().toLocaleTimeString()}`, + err + ); + }); + roomList.forEach((roomRef) => { + roomRef + .get() + .then(async (roomSnap) => { + if ( + FunctionModules.timeDiff(roomSnap.createTime.toDate(), startedTime) >= 24 || + FunctionModules.timeDiff(roomSnap.updateTime.toDate(), startedTime) >= 12 + ) + await FunctionModules.cleanUpRoom(roomSnap.id); + console.info(`Deleted room ${roomSnap.id} from auto cleanup`); + return; + }) + .catch((err) => { + console.error( + `Failed to run auto clean up (get room snap) @ ${new Date().toLocaleTimeString()}`, + err + ); + }); + }); +}; diff --git a/functions/modules2/sendMessage.js b/functions/modules2/sendMessage.js new file mode 100644 index 0000000..d9b4581 --- /dev/null +++ b/functions/modules2/sendMessage.js @@ -0,0 +1,46 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const { name, text, uid, roomId, type } = JSON.parse(req.body); + + const roomExists = await admin + .firestore() + .collection('rooms') + .doc(roomId) + .get() + .then((roomSnap) => roomSnap.exists); + if (roomExists) { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .add({ + name, + text: text || '', + time: new Date(), + uid, + type: type || '', + }) + .catch((err) => { + console.error(`Failed to send message to party : \n\t Room: ${roomId} \n\t ${uid}`, err); + res.status(500).send({ message: "Couldn't send your message", error: messageErr }); + }); + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .update({ + updatedAt: new Date(), + }) + .catch((err) => { + console.error( + `Failed to set updated time when sending messasge to party : \n\t Room: ${roomId} \n\t User: ${uid}`, + err + ); + }); + res.status(200).send({ message: 'Sent a message' }); + } else { + res.status(404).send({ message: 'Looks like this party is over' }); + } +}; diff --git a/functions/modules2/timeDiff.js b/functions/modules2/timeDiff.js new file mode 100644 index 0000000..5acc187 --- /dev/null +++ b/functions/modules2/timeDiff.js @@ -0,0 +1,7 @@ +module.exports = (ds1, ds2) => { + const d1 = new Date(ds1); + const d2 = new Date(ds2); + var diff = (d2.getTime() - d1.getTime()) / 1000; + diff /= 60 * 60; + return Math.abs(Math.round(diff)); +}; diff --git a/functions/modules/tokenRefresher.js b/functions/modules2/tokenRefresher.js similarity index 100% rename from functions/modules/tokenRefresher.js rename to functions/modules2/tokenRefresher.js diff --git a/functions/modules/tokenValidator.js b/functions/modules2/tokenValidator.js similarity index 100% rename from functions/modules/tokenValidator.js rename to functions/modules2/tokenValidator.js diff --git a/functions/modules2/updatePlayer.js b/functions/modules2/updatePlayer.js new file mode 100644 index 0000000..777a155 --- /dev/null +++ b/functions/modules2/updatePlayer.js @@ -0,0 +1,82 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const { player, roomId, uid, showChanged, userName } = JSON.parse(req.body); + // const statusString = + // player.status === 'PLAYING' + // ? 'started playing from' + // : player.status === 'PAUSED' + // ? 'paused at' + // : player.status === 'NOT_PLAYING' + // ? 'stopped at' + // : 'is at'; + // const timeString = + // player.time > 3600 + // ? new Date(player.time * 1000).toISOString().substr(11, 8) + // : new Date(player.time * 1000).toISOString().substr(14, 5); + const [roomExists, roomData] = await admin + .firestore() + .collection('rooms') + .doc(roomId) + .get() + .then((docSnap) => [docSnap.exists, docSnap.data()]); + if (!roomExists) return res.status(404).send({ message: 'Party not found.' }); + const userExists = await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('users') + .doc(uid) + .get() + .then((userSnap) => userSnap.exists); + if (userExists) { + if (showChanged === true) { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${userName} changed \n${player.showName ? 'to ' + player.showName : ''}`, + time: new Date(), + }); + } + if (roomData.status !== player.status) { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .update({ + player, + }) + .catch((err) => { + console.error(`Failed to update player : \n\t Room: ${roomId} \n\t ${uid}`, err); + res.status(500).send({ message: "Uh oh party could't be synced", err }); + }); + // await admin + // .firestore() + // .collection('rooms') + // .doc(roomId) + // .collection('messages') + // .add({ + // uid: '', + // name: '', + // text: `${userName} ${statusString} ${timeString}`, + // time: new Date(), + // }) + // .catch((err) => { + // console.error( + // `Failed to add system update player message : \n\t Room: ${roomId} \n\t ${uid}`, + // err + // ); + // }); + return res.status(200).send({ message: 'Synced party player' }); + } else { + return res.status(208).send({ message: 'Player already up to date' }); + } + } else { + return res.status(401).send({ message: 'Not in room to sync' }); + } +}; diff --git a/functions/modules/updateVoxeet.js b/functions/modules2/updateVoxeet.js similarity index 100% rename from functions/modules/updateVoxeet.js rename to functions/modules2/updateVoxeet.js