diff --git a/backend/api/controllers/user.js b/backend/api/controllers/user.js index 3b792cd54..210931fb4 100644 --- a/backend/api/controllers/user.js +++ b/backend/api/controllers/user.js @@ -4,6 +4,8 @@ const { isUsernameValid, isTagPresetNameValid, } = require("../../handlers/validation"); +const MonkeyError = require("../../handlers/error"); +const fetch = require("node-fetch"); // import UsersDAO from "../../dao/user"; // import BotDAO from "../../dao/bot"; @@ -78,11 +80,18 @@ class UserController { const { uid } = req.decodedToken; let discordFetch = await fetch("https://discord.com/api/users/@me", { headers: { - authorization: `${req.tokenType} ${req.accessToken}`, + authorization: `${req.body.data.tokenType} ${req.body.data.accessToken}`, }, }); discordFetch = await discordFetch.json(); const did = discordFetch.id; + if (!did) { + throw new MonkeyError( + 500, + "Could not get Discord account info", + "did is undefined" + ); + } let user; try { user = await UsersDAO.getUserByDiscordId(did); @@ -90,13 +99,27 @@ class UserController { user = null; } if (user !== null) { - return next( + throw new MonkeyError( + 400, "This Discord account is already linked to a different account" ); } await UsersDAO.linkDiscord(uid, did); await BotDAO.linkDiscord(uid, did); - return res.sendStatus(200); + return res.status(200).json({ + message: "Discord account linked", + did, + }); + } catch (e) { + return next(e); + } + } + + static async unlinkDiscord(req, res, next) { + try { + const { uid } = req.decodedToken; + await UsersDAO.unlinkDiscord(uid); + return res.status(200).send(); } catch (e) { return next(e); } diff --git a/backend/api/routes/user.js b/backend/api/routes/user.js index b57941765..b35aef1c0 100644 --- a/backend/api/routes/user.js +++ b/backend/api/routes/user.js @@ -24,4 +24,12 @@ router.post("/tags/remove", authenticateRequest, UserController.removeTag); router.post("/tags/edit", authenticateRequest, UserController.editTag); +router.post("/discord/link", authenticateRequest, UserController.linkDiscord); + +router.post( + "/discord/unlink", + authenticateRequest, + UserController.unlinkDiscord +); + module.exports = router; diff --git a/package-lock.json b/package-lock.json index 49fecd7a1..eeabfb55c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "howler": "^2.2.1", "mongodb": "^3.6.9", "mongoose": "^5.12.12", + "node-fetch": "^2.6.1", "nodemon": "^2.0.7", "path": "^0.12.7", "tinycolor2": "^1.4.2", @@ -10242,7 +10243,6 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "optional": true, "engines": { "node": "4.x || >=6.0.0" } @@ -22473,8 +22473,7 @@ "node-fetch": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "optional": true + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-forge": { "version": "0.10.0", diff --git a/package.json b/package.json index 1f1e9e39b..b1440dd96 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "howler": "^2.2.1", "mongodb": "^3.6.9", "mongoose": "^5.12.12", + "node-fetch": "^2.6.1", "nodemon": "^2.0.7", "path": "^0.12.7", "tinycolor2": "^1.4.2", diff --git a/src/js/account/verification-controller.js b/src/js/account/verification-controller.js index f6b42fc54..277999370 100644 --- a/src/js/account/verification-controller.js +++ b/src/js/account/verification-controller.js @@ -2,27 +2,32 @@ import * as Notifications from "./notifications"; import * as Settings from "./settings"; import * as DB from "./db"; import axiosInstance from "./axios-instance"; +import * as Loader from "./loader"; export let data = null; export function set(val) { data = val; } -export function verify(user) { - Notifications.add("Verifying", 0, 3); +export async function verify(user) { + Notifications.add("Linking Discord account", 0, 3); + Loader.show(); data.uid = user.uid; - - axiosInstance - .post("/verifyDiscord", { - data: data, - }) - .then((response) => { - if (response.data.status === 1) { - Notifications.add(response.data.message, 1); - DB.getSnapshot().discordId = response.data.did; - Settings.updateDiscordSection(); - } else { - Notifications.add(response.data.message, -1); - } - }); + let response; + try { + response = await axiosInstance.post("/user/discord/link", { data: data }); + } catch (e) { + Loader.hide(); + let msg = e?.response?.data?.message ?? e.message; + Notifications.add("Failed to link Discord: " + msg, -1); + return; + } + Loader.hide(); + if (response.status !== 200) { + Notifications.add(response.data.message); + } else { + Notifications.add("Accounts linked", 1); + DB.getSnapshot().discordId = response.data.did; + Settings.updateDiscordSection(); + } } diff --git a/src/js/db.js b/src/js/db.js index 755da6ca8..809f5f263 100644 --- a/src/js/db.js +++ b/src/js/db.js @@ -63,6 +63,7 @@ export async function initSnapshot() { snap.personalBests = userData.personalBests; snap.banned = userData.banned; snap.verified = userData.verified; + snap.discordId = userData.discordId; snap.globalStats = { time: userData.timeTyping, started: userData.startedTests, diff --git a/src/js/ready.js b/src/js/ready.js index f0e6203ca..415a35a40 100644 --- a/src/js/ready.js +++ b/src/js/ready.js @@ -46,6 +46,8 @@ $(document).ready(() => { }); history.replaceState("/", null, "/"); } + let page = window.location.pathname.replace("/", ""); + UI.changePage(page); } else if (window.location.pathname === "/account") { // history.replaceState("/", null, "/"); } else if (/challenge_.+/g.test(window.location.pathname)) { diff --git a/src/js/route-controller.js b/src/js/route-controller.js index 11bd0be47..b1032bff6 100644 --- a/src/js/route-controller.js +++ b/src/js/route-controller.js @@ -8,7 +8,7 @@ let mappedRoutes = { "/settings": "pageSettings", "/about": "pageAbout", "/account": "pageAccount", - "/verify": "pageTest", + "/verify": "pageLoading", }; export function handleInitialPageClasses(pathname) { diff --git a/src/js/simple-popups.js b/src/js/simple-popups.js index 06a2195c6..adf98367d 100644 --- a/src/js/simple-popups.js +++ b/src/js/simple-popups.js @@ -366,8 +366,26 @@ list.unlinkDiscord = new SimplePopup( [], "Are you sure you want to unlink your Discord account?", "Unlink", - () => { + async () => { Loader.show(); + let response; + try { + response = await axiosInstance.post("/user/discord/unlink", {}); + } catch (e) { + Loader.hide(); + let msg = e?.response?.data?.message ?? e.message; + Notifications.add("Failed to unlink Discord: " + msg, -1); + return; + } + Loader.hide(); + if (response.status !== 200) { + Notifications.add(response.data.message); + } else { + Notifications.add("Accounts unlinked", 1); + DB.getSnapshot().discordId = undefined; + Settings.updateDiscordSection(); + } + //todo rewrite to axios // CloudFunctions.unlinkDiscord({ // uid: firebase.auth().currentUser.uid, diff --git a/static/index.html b/static/index.html index 9a728c5fb..978979a18 100644 --- a/static/index.html +++ b/static/index.html @@ -2030,12 +2030,19 @@ might result in the bot not being able to give you a role.
- Link with Discord + --> + + Link with Discord