replaced /api/ with api subdomain in production, added helmet middleware

This commit is contained in:
lukew3 2021-06-03 11:19:27 -04:00
parent e36a349dc4
commit 11caa57eeb
15 changed files with 64 additions and 45 deletions

View file

@ -5,10 +5,9 @@
Make sure that the branch is ready for deployment
- Add deploy script(s) to package.json
- Make sure that firebase hosted app can connect to api when deployed
- Create a plan for apache/nginx server
- Api should probably be accessible via api.monkeytype.com or monkeytype.com/api
- Probably the previous since firebase might not work with seperate linux server
- Api should be accessible via api.monkeytype.com
- Add helmet middleware to express api?
## Bugs

View file

@ -3,6 +3,7 @@ const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cors = require("cors");
const admin = require("firebase-admin");
const helmet = require("helmet");
const { User } = require("./models/user");
const { Leaderboard } = require("./models/leaderboard");
@ -16,6 +17,7 @@ admin.initializeApp({
// MIDDLEWARE & SETUP
const app = express();
app.use(cors());
app.use(helmet());
const port = process.env.PORT || "5005";
@ -567,7 +569,7 @@ function isUsernameValid(name) {
// API
app.get("/api/nameCheck/:name", (req, res) => {
app.get("/nameCheck/:name", (req, res) => {
if (!isUsernameValid(req.params.name)) {
res.status(200).send({
resultCode: -2,
@ -598,7 +600,7 @@ app.get("/api/nameCheck/:name", (req, res) => {
});
});
app.post("/api/signUp", (req, res) => {
app.post("/signUp", (req, res) => {
const newuser = new User({
name: req.body.name,
email: req.body.email,
@ -610,20 +612,20 @@ app.post("/api/signUp", (req, res) => {
return;
});
app.post("/api/updateName", (req, res) => {
app.post("/updateName", (req, res) => {
//this might be a put/patch request
//update the name of user with given uid
const uid = req.body.uid;
const name = req.body.name;
});
app.post("/api/passwordReset", (req, res) => {
app.post("/passwordReset", (req, res) => {
const email = req.body.email;
//send email to the passed email requesting password reset
res.sendStatus(200);
});
app.get("/api/fetchSnapshot", authenticateToken, (req, res) => {
app.get("/fetchSnapshot", authenticateToken, (req, res) => {
/* Takes token and returns snap */
User.findOne({ uid: req.uid }, (err, user) => {
if (err) res.status(500).send({ error: err });
@ -644,7 +646,7 @@ function stdDev(array) {
);
}
app.post("/api/testCompleted", authenticateToken, (req, res) => {
app.post("/testCompleted", authenticateToken, (req, res) => {
User.findOne({ uid: req.uid }, (err, user) => {
if (err) res.status(500).send({ error: err });
request = req.body;
@ -963,7 +965,7 @@ app.post("/api/testCompleted", authenticateToken, (req, res) => {
});
});
app.get("/api/userResults", authenticateToken, (req, res) => {
app.get("/userResults", authenticateToken, (req, res) => {
User.findOne({ uid: req.uid }, (err, user) => {
if (err) res.status(500).send({ error: err });
});
@ -977,7 +979,7 @@ function isConfigKeyValid(name) {
return /^[0-9a-zA-Z_.\-#+]+$/.test(name);
}
app.post("/api/saveConfig", authenticateToken, (req, res) => {
app.post("/saveConfig", authenticateToken, (req, res) => {
try {
if (req.uid === undefined || req.body.obj === undefined) {
console.error(`error saving config for ${req.uid} - missing input`);
@ -1059,7 +1061,7 @@ app.post("/api/saveConfig", authenticateToken, (req, res) => {
}
});
app.post("/api/addPreset", authenticateToken, (req, res) => {
app.post("/addPreset", authenticateToken, (req, res) => {
try {
if (!isTagPresetNameValid(req.body.obj.name)) {
return { resultCode: -1 };
@ -1151,7 +1153,7 @@ app.post("/api/addPreset", authenticateToken, (req, res) => {
}
});
app.post("/api/editPreset", authenticateToken, (req, res) => {
app.post("/editPreset", authenticateToken, (req, res) => {
try {
if (!isTagPresetNameValid(req.body.presetName)) {
res.json({ resultCode: -1 });
@ -1189,7 +1191,7 @@ app.post("/api/editPreset", authenticateToken, (req, res) => {
}
});
app.post("/api/removePreset", authenticateToken, (req, res) => {
app.post("/removePreset", authenticateToken, (req, res) => {
try {
User.findOne({ uid: req.uid }, (err, user) => {
for (i = 0; i < user.presets.length; i++) {
@ -1222,8 +1224,8 @@ function isTagPresetNameValid(name) {
return /^[0-9a-zA-Z_.-]+$/.test(name);
}
//could use /api/tags/add instead
app.post("/api/addTag", authenticateToken, (req, res) => {
//could use /tags/add instead
app.post("/addTag", authenticateToken, (req, res) => {
try {
if (!isTagPresetNameValid(req.body.tagName)) return { resultCode: -1 };
User.findOne({ uid: req.uid }, (err, user) => {
@ -1259,7 +1261,7 @@ app.post("/api/addTag", authenticateToken, (req, res) => {
}
});
app.post("/api/editTag", authenticateToken, (req, res) => {
app.post("/editTag", authenticateToken, (req, res) => {
try {
if (!isTagPresetNameValid(req.body.tagName)) return { resultCode: -1 };
User.findOne({ uid: req.uid }, (err, user) => {
@ -1287,7 +1289,7 @@ app.post("/api/editTag", authenticateToken, (req, res) => {
}
});
app.post("/api/removeTag", authenticateToken, (req, res) => {
app.post("/removeTag", authenticateToken, (req, res) => {
try {
User.findOne({ uid: req.uid }, (err, user) => {
if (err) res.status(500).send({ error: err });
@ -1312,7 +1314,7 @@ app.post("/api/removeTag", authenticateToken, (req, res) => {
}
});
app.post("/api/resetPersonalBests", authenticateToken, (req, res) => {
app.post("/resetPersonalBests", authenticateToken, (req, res) => {
try {
User.findOne({ uid: req.uid }, (err, user) => {
if (err) res.status(500).send({ error: err });
@ -1389,7 +1391,7 @@ function addToLeaderboard(lb, result, username) {
return lb, retData;
}
app.post("/api/attemptAddToLeaderboards", authenticateToken, (req, res) => {
app.post("/attemptAddToLeaderboards", authenticateToken, (req, res) => {
const result = req.body.result;
let retData = {};
User.findOne({ uid: req.uid }, (err, user) => {
@ -1455,7 +1457,7 @@ app.post("/api/attemptAddToLeaderboards", authenticateToken, (req, res) => {
res.status(200);
});
app.get("/api/getLeaderboard/:type/:mode/:mode2", (req, res) => {
app.get("/getLeaderboard/:type/:mode/:mode2", (req, res) => {
Leaderboard.findOne(
{ mode: req.params.mode, mode2: req.params.mode2, type: req.params.type },
(err, lb) => {

14
package-lock.json generated
View file

@ -18,6 +18,7 @@
"cors": "^2.8.5",
"express": "^4.17.1",
"firebase-admin": "^9.9.0",
"helmet": "^4.6.0",
"howler": "^2.2.1",
"mongoose": "^5.12.12",
"nodemon": "^2.0.7",
@ -7222,6 +7223,14 @@
"minimalistic-assert": "^1.0.1"
}
},
"node_modules/helmet": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz",
"integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@ -20105,6 +20114,11 @@
"minimalistic-assert": "^1.0.1"
}
},
"helmet": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz",
"integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg=="
},
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",

View file

@ -50,6 +50,7 @@
"cors": "^2.8.5",
"express": "^4.17.1",
"firebase-admin": "^9.9.0",
"helmet": "^4.6.0",
"howler": "^2.2.1",
"mongoose": "^5.12.12",
"nodemon": "^2.0.7",

View file

@ -136,7 +136,7 @@ function signUp() {
$(".pageLogin .register .button").removeClass("disabled");
return;
}
axiosInstance.get(`/api/nameCheck/${nname}`).then((d) => {
axiosInstance.get(`/nameCheck/${nname}`).then((d) => {
console.log(d.data);
if (d.data.resultCode === -1) {
Notifications.add("Name unavailable", -1);
@ -160,7 +160,7 @@ function signUp() {
// dontCheckUserName = true;
let usr = user.user;
//maybe there's a better place for the api call
axiosInstance.post("/api/signUp", {
axiosInstance.post("/signUp", {
name: nname,
uid: usr.uid,
email: email,

View file

@ -1,7 +1,14 @@
import axios from "axios";
let baseURL;
if (window.location.hostname === "localhost") {
baseURL = "http://localhost:5005";
} else {
baseURL = "https://api.monkeytype.com";
}
const axiosInstance = axios.create({
baseURL: "http://localhost:5005",
baseURL: baseURL,
});
// Request interceptor for API calls

View file

@ -1,5 +1,5 @@
// all functions here should be changed into api calls
//export function testCompleted = axios.post('/api/testCompleted', )firebase
//export function testCompleted = axios.post('/testCompleted', )firebase
// .functions()
// .httpsCallable("testCompleted");
import axiosInstance from "./axios-instance";

View file

@ -7,7 +7,7 @@ let dbSnapshot = null;
export function updateName(uid, name) {
//db.collection(`users`).doc(uid).set({ name: name }, { merge: true });
axiosInstance.post("/api/updateName", {
axiosInstance.post("/updateName", {
uid: uid,
name: name,
});
@ -31,7 +31,7 @@ export async function initSnapshot() {
//send api request with token that returns tags, presets, and data needed for snap
if (firebase.auth().currentUser == null) return false;
await axiosInstance
.get("/api/fetchSnapshot")
.get("/fetchSnapshot")
.then((response) => {
dbSnapshot = response.data.snap;
loadTags(dbSnapshot.tags);
@ -50,7 +50,7 @@ export async function getUserResults() {
return true;
} else {
axiosInstance
.get("/api/userResults", {
.get("/userResults", {
uid: user.uid,
})
.then((response) => {
@ -412,7 +412,7 @@ export async function saveConfig(config) {
if (firebase.auth().currentUser !== null) {
AccountButton.loading(true);
axiosInstance
.post("/api/saveConfig", {
.post("/saveConfig", {
obj: config,
})
.then((response) => {

View file

@ -30,12 +30,8 @@ function update() {
Loader.show();
Promise.all([
axiosInstance.get(
`/api/getLeaderboard/daily/${boardinfo[0]}/${boardinfo[1]}`
),
axiosInstance.get(
`/api/getLeaderboard/global/${boardinfo[0]}/${boardinfo[1]}`
),
axiosInstance.get(`/getLeaderboard/daily/${boardinfo[0]}/${boardinfo[1]}`),
axiosInstance.get(`/getLeaderboard/global/${boardinfo[0]}/${boardinfo[1]}`),
])
.then((lbdata) => {
Loader.hide();

View file

@ -316,7 +316,7 @@ export function sendVerificationEmail() {
Loader.show();
let cu = firebase.auth().currentUser;
axiosInstance
.post("/api/sendEmailVerification", {})
.post("/sendEmailVerification", {})
.then(() => {
Loader.hide();
showNotification("Email sent to " + cu.email, 4000);

View file

@ -73,7 +73,7 @@ function apply() {
if (action === "add") {
Loader.show();
axiosInstance
.post("/api/addPreset", {
.post("/addPreset", {
obj: {
name: inputVal,
config: configChanges,
@ -103,7 +103,7 @@ function apply() {
} else if (action === "edit") {
Loader.show();
axiosInstance
.post("/api/editPreset", {
.post("/editPreset", {
presetName: inputVal,
presetid: presetid,
config: configChanges,
@ -128,7 +128,7 @@ function apply() {
} else if (action === "remove") {
Loader.show();
axiosInstance
.post("/api/removePreset", {
.post("/removePreset", {
presetid,
})
.then((e) => {

View file

@ -67,7 +67,7 @@ function apply() {
if (action === "add") {
Loader.show();
axiosInstance
.post("/api/addTag", {
.post("/addTag", {
tagName: inputVal,
})
.then((e) => {
@ -91,7 +91,7 @@ function apply() {
} else if (action === "edit") {
Loader.show();
axiosInstance
.post("/api/editTag", {
.post("/editTag", {
tagName: inputVal,
tagId: tagid,
})
@ -117,7 +117,7 @@ function apply() {
} else if (action === "remove") {
Loader.show();
axiosInstance
.post("/api/removeTag", {
.post("/removeTag", {
tagId: tagid,
})
.then((e) => {

View file

@ -246,7 +246,7 @@ list.resetPersonalBests = new SimplePopup(
() => {
try {
Loader.show();
axiosInstance.post("/api/resetPersonalBests").then((res) => {
axiosInstance.post("/resetPersonalBests").then((res) => {
if (res) {
Loader.hide();
Notifications.add(

View file

@ -174,7 +174,7 @@ export async function check(completedEvent) {
})
*/
axiosInstance
.post("/api/attemptAddToLeaderboards", {
.post("/attemptAddToLeaderboards", {
//user data can be retrieved from the database
result: lbRes,
})

View file

@ -1566,7 +1566,7 @@ export function finish(difficultyFailed = false) {
Notifications.add("You are offline. Result not saved.", -1);
} else {
axiosInstance
.post("/api/testCompleted", {
.post("/testCompleted", {
obj: completedEvent,
})
.then((e) => {