diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..09cd4e1 --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,12 @@ +PORT=3000 +DB_USER=chs-mc-website +DB_PASS=hunter2 +DB_NAME=mc_stats +DB_HOST=mariadb:3306 +MAIL_FROM=hello@example.com +MAIL_NAME='CHS Minecraft Server' +MAIL_HOST=sandbox.smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USER=whatever +MAIL_PASS=hunter2 +MAIL_SSL=false \ No newline at end of file diff --git a/backend/index.js b/backend/index.js index 9b04646..b10b5c4 100644 --- a/backend/index.js +++ b/backend/index.js @@ -56,7 +56,7 @@ app.get("/", (req, res) => { const transporter = nodemailer.createTransport({ host: process.env.MAIL_HOST, port: process.env.MAIL_PORT, - secure: true, + secure: process.env.MAIL_SSL === "true" ? true : false, auth: { user: process.env.MAIL_USER, pass: process.env.MAIL_PASS, @@ -64,40 +64,54 @@ const transporter = nodemailer.createTransport({ }); app.post("/register", async (req, res) => { - let userEmail = req.body.email; - let username = req.body.username; + let userEmail = req.body.email.toLowerCase(); - let token = crypto.randomBytes(32).toString("hex"); + if (!userEmail.endsWith("@chalmers.se")) { + res.status(400).send("Invalid email"); + return; + } - // Send email with the token - let mailOptions = { - from: `"${process.env.MAIL_NAME}>" <${process.env.MAIL_FROM}>`, - to: userEmail, - subject: "Registration Confirmation for mc.chs.se", - text: - "Please confirm your registration by clicking the following link: \nhttp://" + - req.headers.host + - "/confirm/" + - token + - "\n\n" + - "If you did not request this, please ignore this email.", - }; + let username = req.body.username.toLowerCase(); - transporter.sendMail(mailOptions, function (err) { - if (err) { - console.error("There was an error: ", err); - } else { - console.log("Email sent"); - } - }); + // check that username is only letters and numbers or underscore + if (!/^[a-zA-Z0-9_]+$/.test(username)) { + res.status(400).send("Invalid username"); + return; + } + + // check that username is under 64 characters + if (username.length > 16) { + res.status(400).send("Username is too long"); + return; + } + + let uuid = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`) + .then((response) => { + if (response.status === 404) { + res.status(400).send("Username doesn't exist"); + return; + } + return response.json().id; + }) + + let token = crypto.randomBytes(32).toString("hex"); let conn; try { conn = await pool.getConnection(); - let sql = "INSERT INTO users (email, username, active) VALUES (?, ?, 0)"; + + // Check if email already exists + let sql = "SELECT * FROM users WHERE email = ?"; + let rows = await conn.query(sql, [userEmail]); + if (rows.length > 0) { + res.status(400).send("Email already in use"); + return; + } + + sql = "INSERT INTO users (email, username, active) VALUES (?, ?, 0)"; await conn.query(sql, [userEmail, username]); sql = "SELECT id FROM users WHERE email = ?"; - const rows = await conn.query(sql, [userEmail]); + rows = await conn.query(sql, [userEmail]); let userId = rows[0].id; sql = "INSERT INTO confirmations (user_id, token) VALUES (?, ?)"; await conn.query(sql, [userId, token]); @@ -106,6 +120,25 @@ app.post("/register", async (req, res) => { } finally { if (conn) conn.end(); } + + // Send email with the token + let mailOptions = { + from: `"${process.env.MAIL_NAME}" <${process.env.MAIL_FROM}>`, + to: userEmail, + subject: "Registration Confirmation for mc.chs.se", + text: `Please confirm your registration by clicking the following link: + http://${req.headers.host}/confirm/${token} + + If you did not request this, please ignore this email.`, + }; + + transporter.sendMail(mailOptions, function (err) { + if (err) { + console.error("There was an error: ", err); + } else { + console.log("Email sent"); + } + }); }); app.get("/confirm/:token", async (req, res) => { @@ -121,9 +154,14 @@ app.get("/confirm/:token", async (req, res) => { await conn.query(sql, [token]); sql = "UPDATE users SET active = 1 WHERE id = ?"; await conn.query(sql, [rows[0].user_id]); - res.send("Your account has been activated."); + res.send(`Your account has been activated. Redirecting to the home page... + `); } else { - res.send("Invalid token."); + res.send("Invalid token. Try again. Go to back"); } } catch (err) { console.error(err); diff --git a/docker-compose.yml b/docker-compose.yml index 24d2085..86dea85 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,7 @@ services: MAIL_PORT: 2525 MAIL_USER: ed34e3c7508a9d MAIL_PASS: e278e352efca4b + MAIL_SSL: false mariadb: image: mariadb:11 container_name: mariadb