From b6728eb995a5d8695f5977f6bf6036723065fc1e Mon Sep 17 00:00:00 2001 From: Curt Grimes Date: Tue, 30 Apr 2019 15:09:41 -0500 Subject: [PATCH] Add ability to have vanity links --- app/.env.sample | 1 + app/api/routes/rooms/index.js | 60 +- app/components/ShareButton.vue | 52 +- app/components/toasts/Share.vue | 98 ++- app/nuxt.config.js | 4 + app/package-lock.json | 1147 +++++++++++++++++++++++++----- app/package.json | 3 +- app/pages/captioner.vue | 41 +- app/socket.io/server.js | 4 - app/store/actions.js | 4 + app/store/mutations.js | 16 +- app/store/settingsState.js | 3 + app/store/share.js | 75 +- scripts/write-task-definition.js | 1 + 14 files changed, 1258 insertions(+), 251 deletions(-) diff --git a/app/.env.sample b/app/.env.sample index 7b436a7..b6151bd 100644 --- a/app/.env.sample +++ b/app/.env.sample @@ -24,5 +24,6 @@ FIREBASE_DATABASE_URL= FIREBASE_PROJECT_ID= FIREBASE_STORAGE_BUCKET= FIREBASE_MESSAGING_SENDER_ID= +FIREBASE_NODE_SERVICE_ACCOUNT_KEY= ADMIN_TOKEN= \ No newline at end of file diff --git a/app/api/routes/rooms/index.js b/app/api/routes/rooms/index.js index 38a68d2..e82ff4d 100644 --- a/app/api/routes/rooms/index.js +++ b/app/api/routes/rooms/index.js @@ -7,6 +7,11 @@ const openGraphScraper = require('open-graph-scraper'); const vibrant = require('node-vibrant') const url = require('url'); const twitch = require('./twitch'); +const admin = require('firebase-admin'); + +admin.initializeApp({ + credential: admin.credential.cert(JSON.parse(process.env.FIREBASE_NODE_SERVICE_ACCOUNT_KEY)) +}); const expireHours = 48; @@ -71,13 +76,43 @@ rooms.post('/', async (req, res, next) => { } let roomKey, roomId, roomKeyAlreadyExists; - do { - roomId = nanoidGenerate('23456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghjkmnpqrstuvwxyz-', 8); - roomKey = 'rooms:' + roomId; - roomKeyAlreadyExists = await redisClient.existsAsync(roomKey) === 1; - } - while (roomKeyAlreadyExists); // repeat roomkey generation on collision + if (req.body.urlType === 'vanity') { + if (!req.body.uid) { + // Need a user ID to continue + res.sendStatus(403); + return; + } + + // Check that they're allowed to request this vanity URL + let db = admin.firestore(); + let vanity = await db.collection('users') + .doc(req.body.uid) + .collection('privileges') + .doc('share') + .get() + .then((document) => { + if (document.exists) { + return document.data().vanity; + } + }); + if (vanity) { + // They have a vanity URL + roomId = vanity; + roomKey = 'rooms:' + roomId; + } else { + // They don't have a vanity URL + res.sendStatus(403); + return; + } + } else { + do { + roomId = nanoidGenerate('23456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghjkmnpqrstuvwxyz-', 8); + roomKey = 'rooms:' + roomId; + roomKeyAlreadyExists = await redisClient.existsAsync(roomKey) === 1; + } + while (roomKeyAlreadyExists); // repeat roomkey generation on collision + } const ownerKey = nanoid(50); const backlink = req.body.backlink ? ['backlink', req.body.backlink] : []; @@ -86,13 +121,22 @@ rooms.post('/', async (req, res, next) => { const appearance = req.body.appearance && req.body.appearance.length <= 1000 ? ['appearance', req.body.appearance] : []; redisClient.hmset(roomKey, 'ownerKey', ownerKey, ...backlink, ...appearance); - redisClient.expire(roomKey, 60 * 60 * expireHours); + + if (req.body.urlType === 'random') { + // Random URLs expire + redisClient.expire(roomKey, 60 * 60 * expireHours); + } res.send(JSON.stringify({ roomId, ownerKey, url: process.env.HOSTNAME + '/s/' + roomId, - expireDate: new Date((new Date()).getTime() + (1000 * 60 * 60 * expireHours)), + + // Vanity URLs never expire + expires: req.body.urlType === 'random', + expireDate: req.body.urlType === 'random' ? + (new Date((new Date()).getTime() + (1000 * 60 * 60 * expireHours))) : + null, })); return; }); diff --git a/app/components/ShareButton.vue b/app/components/ShareButton.vue index 61dba1e..a4f3bda 100644 --- a/app/components/ShareButton.vue +++ b/app/components/ShareButton.vue @@ -1,10 +1,9 @@ + + +