moving verification to oauth2

This commit is contained in:
Jack 2020-10-10 15:48:08 +01:00
parent 64a6c2e0eb
commit 9d3994e73d
6 changed files with 250 additions and 207 deletions

View file

@ -13,6 +13,7 @@ admin.initializeApp({
});
const db = admin.firestore();
const fetch = require("node-fetch");
async function getAllNames() {
// return admin
@ -474,6 +475,55 @@ exports.getPatreons = functions.https.onRequest(async (request, response) => {
}
});
exports.verifyUser = functions.https.onRequest(async (request, response) => {
response.set("Access-Control-Allow-Origin", "*");
response.set("Access-Control-Allow-Headers", "*");
response.set("Access-Control-Allow-Credentials", "true");
if (request.method === "OPTIONS") {
// Send response to OPTIONS requests
response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.set("Access-Control-Allow-Headers", "Authorization,Content-Type");
response.set("Access-Control-Max-Age", "3600");
response.status(204).send("");
return;
}
request = request.body.data;
if (request.uid == undefined) {
response.status(200).send({ data: { status: -1, message: "Need to provide uid" } });
return;
}
try {
return fetch("https://discord.com/api/users/@me", {
headers: {
authorization: `${request.tokenType} ${request.accessToken}`,
},
})
.then((res) => res.json())
.then(async (res2) => {
let did = res2.id;
await db.collection('users').doc(request.uid).update({
discordId: did
})
await db.collection("bot-commands").add({
command: "verify",
arguments: [did,request.uid],
executed: false,
requestTimestamp: Date.now(),
});
response.status(200).send({ data: { status: 1, message: "Verified", did: did } });
return;
})
.catch((e) => {
console.error('Something went wrong when trying to verify user ' + e.message);
response.status(200).send({ data: { status: -1, message: e.message } });
return;
});
} catch (e) {
response.status(200).send({ data: { status: -1, message: e } });
return;
}
});
async function incrementTestCounter(uid, userData) {
try {
if (userData.completedTests === undefined) {
@ -1434,143 +1484,138 @@ class Leaderboard {
}
}
exports.generatePairingCode = functions
.runWith({
timeoutSeconds: 100,
memory: "2GB",
})
.https.onRequest((request, response) => {
response.set("Access-Control-Allow-Origin", "*");
if (request.method === "OPTIONS") {
// Send response to OPTIONS requests
response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.set(
"Access-Control-Allow-Headers",
"Authorization,Content-Type"
);
response.set("Access-Control-Max-Age", "3600");
response.status(204).send("");
return;
}
request = request.body.data;
try {
if (request === null) {
console.error(
`error while trying to generate discord pairing code - no input`
);
response.status(200).send({ data: { status: -999 } });
return;
}
// exports.generatePairingCode = functions
// .runWith({
// timeoutSeconds: 100,
// memory: "2GB",
// })
// .https.onRequest((request, response) => {
// response.set("Access-Control-Allow-Origin", "*");
// if (request.method === "OPTIONS") {
// // Send response to OPTIONS requests
// response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
// response.set(
// "Access-Control-Allow-Headers",
// "Authorization,Content-Type"
// );
// response.set("Access-Control-Max-Age", "3600");
// response.status(204).send("");
// return;
// }
// request = request.body.data;
// try {
// if (request === null) {
// console.error(
// `error while trying to generate discord pairing code - no input`
// );
// response.status(200).send({ data: { status: -999 } });
// return;
// }
return db
.collection("users")
.doc(request.uid)
.get()
.then(async (userDoc) => {
userDocData = userDoc.data();
if (
userDocData.discordPairingCode !== undefined &&
userDocData.discordPairingCode !== null
) {
console.log(
`user ${request.uid} already has code ${userDocData.discordPairingCode}`
);
response.status(200).send({
data: {
status: -999,
pairingCode: userDocData.discordPairingCode,
},
});
} else {
let stepSize = 1000;
let existingCodes = [];
let query = await db
.collection(`users`)
.where("discordPairingCode", ">", "")
.limit(stepSize)
.get();
let lastDoc;
while (query.docs.length > 0) {
lastDoc = query.docs[query.docs.length - 1];
query.docs.forEach((doc) => {
let docData = doc.data();
if (
docData.discordPairingCode !== undefined &&
docData.discordPairingCode !== null
) {
existingCodes.push(docData.discordPairingCode);
}
});
query = await db
.collection(`users`)
.where("discordPairingCode", ">", "")
.limit(stepSize)
.startAfter(lastDoc)
.get();
}
// return db
// .collection("users")
// .doc(request.uid)
// .get()
// .then(async (userDoc) => {
// userDocData = userDoc.data();
// if (
// userDocData.discordPairingCode !== undefined &&
// userDocData.discordPairingCode !== null
// ) {
// console.log(
// `user ${request.uid} already has code ${userDocData.discordPairingCode}`
// );
// response.status(200).send({
// data: {
// status: -999,
// pairingCode: userDocData.discordPairingCode,
// },
// });
// } else {
// let stepSize = 1000;
// let existingCodes = [];
// let query = await db
// .collection(`users`)
// .where("discordPairingCode", ">", "")
// .limit(stepSize)
// .get();
// let lastDoc;
// while (query.docs.length > 0) {
// lastDoc = query.docs[query.docs.length - 1];
// query.docs.forEach((doc) => {
// let docData = doc.data();
// if (
// docData.discordPairingCode !== undefined &&
// docData.discordPairingCode !== null
// ) {
// existingCodes.push(docData.discordPairingCode);
// }
// });
// query = await db
// .collection(`users`)
// .where("discordPairingCode", ">", "")
// .limit(stepSize)
// .startAfter(lastDoc)
// .get();
// }
let randomCode = generate(9);
// let randomCode = generate(9);
while (existingCodes.includes(randomCode)) {
randomCode = generate(9);
}
// while (existingCodes.includes(randomCode)) {
// randomCode = generate(9);
// }
return db
.collection("users")
.doc(request.uid)
.update(
{
discordPairingCode: randomCode,
},
{ merge: true }
)
.then((res) => {
console.log(`generated ${randomCode} for user ${request.uid}`);
response.status(200).send({
data: {
status: 1,
pairingCode: randomCode,
},
});
return;
})
.catch((e) => {
console.error(
`error while trying to set discord pairing code ${randomCode} for user ${request.uid} - ${e}`
);
response.status(200).send({
data: {
status: -999,
},
});
return;
});
}
});
} catch (e) {
console.error(
`error while trying to generate discord pairing code for user ${request.uid} - ${e}`
);
response.status(200).send({
data: {
status: -999,
},
});
return;
}
});
// return db
// .collection("users")
// .doc(request.uid)
// .update(
// {
// discordPairingCode: randomCode,
// },
// { merge: true }
// )
// .then((res) => {
// console.log(`generated ${randomCode} for user ${request.uid}`);
// response.status(200).send({
// data: {
// status: 1,
// pairingCode: randomCode,
// },
// });
// return;
// })
// .catch((e) => {
// console.error(
// `error while trying to set discord pairing code ${randomCode} for user ${request.uid} - ${e}`
// );
// response.status(200).send({
// data: {
// status: -999,
// },
// });
// return;
// });
// }
// });
// } catch (e) {
// console.error(
// `error while trying to generate discord pairing code for user ${request.uid} - ${e}`
// );
// response.status(200).send({
// data: {
// status: -999,
// },
// });
// return;
// }
// });
exports.unlinkDiscord = functions.https.onRequest((request, response) => {
response.set("Access-Control-Allow-Origin", "*");
if (request.method === "OPTIONS") {
// Send response to OPTIONS requests
response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.set(
"Access-Control-Allow-Headers",
"Authorization,Content-Type"
);
response.set("Access-Control-Allow-Headers", "Authorization,Content-Type");
response.set("Access-Control-Max-Age", "3600");
response.status(204).send("");
return;
@ -1578,40 +1623,46 @@ exports.unlinkDiscord = functions.https.onRequest((request, response) => {
request = request.body.data;
try {
if (request === null || request.uid === undefined) {
response.status(200).send({ data: { status: -999, message: "Empty request" } });
response
.status(200)
.send({ data: { status: -999, message: "Empty request" } });
return;
}
return db.collection(`users`).doc(request.uid).update({
discordId: null
}).then(f => {
response.status(200).send({
data: {
status: 1,
message: "Unlinked"
},
return db
.collection(`users`)
.doc(request.uid)
.update({
discordId: null,
})
.then((f) => {
response.status(200).send({
data: {
status: 1,
message: "Unlinked",
},
});
return;
})
.catch((e) => {
response.status(200).send({
data: {
status: -999,
message: e.message,
},
});
return;
});
return;
}).catch(e => {
response.status(200).send({
data: {
status: -999,
message: e.message
},
});
return;
})
} catch (e) {
response.status(200).send({
data: {
status: -999,
message: e
message: e,
},
});
return;
}
});
async function checkLeaderboards(
resultObj,
type,

35
package-lock.json generated
View file

@ -611,7 +611,7 @@
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"requires": {
"lodash": ">=4.17.19"
"lodash": "^4.17.14"
}
},
"async-each": {
@ -1773,7 +1773,7 @@
"jsonschema": "^1.0.2",
"jsonwebtoken": "^8.2.1",
"leven": "^3.1.0",
"lodash": ">=4.17.19",
"lodash": "^4.17.14",
"marked": "^0.7.0",
"marked-terminal": "^3.3.0",
"minimatch": "^3.0.4",
@ -2272,7 +2272,7 @@
"cli-width": "^2.0.0",
"external-editor": "^3.0.3",
"figures": "^2.0.0",
"lodash": ">=4.17.19",
"lodash": "^4.17.11",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rxjs": "^6.4.0",
@ -2429,6 +2429,17 @@
"requires": {
"node-fetch": "^1.0.1",
"whatwg-fetch": ">=0.10.0"
},
"dependencies": {
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
"requires": {
"encoding": "^0.1.11",
"is-stream": "^1.0.1"
}
}
}
},
"isstream": {
@ -2979,7 +2990,7 @@
"requires": {
"async": "^1.3.0",
"flat-arguments": "^1.0.0",
"lodash": ">=4.17.19",
"lodash": "^4.17.5",
"minimist": "^1.1.0"
},
"dependencies": {
@ -3014,13 +3025,9 @@
}
},
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
"requires": {
"encoding": "^0.1.11",
"is-stream": "^1.0.1"
}
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"node-forge": {
"version": "0.9.1",
@ -3712,7 +3719,7 @@
"home-dir": "^1.0.0",
"is-url": "^1.2.2",
"join-path": "^1.1.1",
"lodash": ">=4.17.19",
"lodash": "^4.17.4",
"mime-types": "^2.1.16",
"minimatch": "^3.0.4",
"morgan": "^1.8.2",
@ -3958,7 +3965,7 @@
"resolved": "https://registry.npmjs.org/toxic/-/toxic-1.0.1.tgz",
"integrity": "sha512-WI3rIGdcaKULYg7KVoB0zcjikqvcYYvcuT6D89bFPz2rVR0Rl0PK6x8/X62rtdLtBKIE985NzVf/auTtGegIIg==",
"requires": {
"lodash": ">=4.17.19"
"lodash": "^4.17.10"
}
},
"traverse": {
@ -4233,7 +4240,7 @@
"requires": {
"http-parser-js": ">=0.4.0 <0.4.11",
"safe-buffer": ">=5.1.0",
"websocket-extensions": ">=0.1.4"
"websocket-extensions": ">=0.1.1"
}
},
"websocket-extensions": {

View file

@ -1454,17 +1454,11 @@
When you connect your monkey-type account to your Discord
account, you will be automatically assigned a new role every
time you achieve a new personal best in a 60 second test.
<div class="howto hidden">
To pair your accounts, direct message 'George' (our bot) on
Discord with the message '!verify
<span class="howtocode">-</span>
'.
</div>
</div>
<div class="buttons">
<div class="button generateCodeButton">
Generate pairing code
</div>
<a class="button" href="https://discord.com/api/oauth2/authorize?client_id=757704816532258856&redirect_uri=https%3A%2F%2Fmonkey-type.com%2Fverify&response_type=token&scope=identify" style="text-decoration: none;">
Verify with Discord
</a>
</div>
<div class="info hidden">
<div>
@ -1475,12 +1469,6 @@
<i class="fas fa-unlink" aria-hidden="true"></i>
</div>
</div>
<div class="code hidden">
<div style="width: min-content; white-space: nowrap;">
<div class="top">code</div>
<div class="bottom">-</div>
</div>
</div>
</div>
<div class="sectionSpacer"></div>
</div>

View file

@ -252,6 +252,17 @@ firebase.auth().onAuthStateChanged(function (user) {
// showNotification('Signed in', 1000);
$(".pageLogin .preloader").addClass("hidden");
$("#menu .icon-button.account .text").text(displayName);
if (verifyUserWhenLoggedIn !== null) {
showNotification('Verifying', 1000);
verifyUserWhenLoggedIn.uid = user.uid;
verifyUser(verifyUserWhenLoggedIn).then(data => {
showNotification(data.data.message, 3000);
if (data.data.status === 1) {
dbSnapshot.discordId = data.data.did;
updateDiscordSettingsSection()
}
})
}
}
});

View file

@ -41,6 +41,7 @@ let caretAnimating = true;
let lastSecondNotRound = false;
let paceCaret = null;
let missedWords = [];
let verifyUserWhenLoggedIn = null;
let themeColors = {
bg: "#323437",
@ -207,6 +208,8 @@ const generatePairingCode = firebase
.httpsCallable("generatePairingCode");
const saveLbMemory = firebase.functions().httpsCallable("saveLbMemory");
const unlinkDiscord = firebase.functions().httpsCallable("unlinkDiscord");
const verifyUser = firebase.functions().httpsCallable("verifyUser");
function refreshThemeColorObject() {
@ -4872,7 +4875,18 @@ $(document).ready(() => {
setCustomThemeInputs();
applyCustomThemeColors();
}
if (window.location.pathname === "/account") {
if (window.location.pathname === "/verify") {
const fragment = new URLSearchParams(window.location.hash.slice(1));
if (fragment.has("access_token")) {
const accessToken = fragment.get("access_token");
const tokenType = fragment.get("token_type");
verifyUserWhenLoggedIn = {
accessToken: accessToken,
tokenType: tokenType
}
history.replaceState("/", null, "/");
}
}else if (window.location.pathname === "/account") {
history.replaceState("/", null, "/");
} else if (window.location.pathname !== "/") {
let page = window.location.pathname.replace("/", "");

View file

@ -611,48 +611,20 @@ function updateDiscordSettingsSection() {
$(".pageSettings .section.discordIntegration").removeClass("hidden");
if (
dbSnapshot.pairingCode == undefined &&
dbSnapshot.discordId == undefined
) {
//show button
$(".pageSettings .section.discordIntegration .howto").addClass("hidden");
$(".pageSettings .section.discordIntegration .buttons").removeClass(
"hidden"
);
$(".pageSettings .section.discordIntegration .info").addClass("hidden");
$(".pageSettings .section.discordIntegration .code").addClass("hidden");
} else if (
dbSnapshot.pairingCode != undefined &&
dbSnapshot.discordId == undefined
) {
//show code
$(".pageSettings .section.discordIntegration .code .bottom").text(
dbSnapshot.pairingCode
);
$(".pageSettings .section.discordIntegration .howtocode").text(
dbSnapshot.pairingCode
);
$(".pageSettings .section.discordIntegration .howto").removeClass(
"hidden"
);
$(".pageSettings .section.discordIntegration .buttons").addClass(
"hidden"
);
$(".pageSettings .section.discordIntegration .info").addClass("hidden");
$(".pageSettings .section.discordIntegration .code").removeClass(
"hidden"
);
} else if (
dbSnapshot.discordId != undefined
) {
$(".pageSettings .section.discordIntegration .howto").addClass("hidden");
} else{
$(".pageSettings .section.discordIntegration .buttons").addClass(
"hidden"
);
$(".pageSettings .section.discordIntegration .info").removeClass(
"hidden"
);
$(".pageSettings .section.discordIntegration .code").addClass("hidden");
}
}
}