diff options
author | gumi <git@gumi.ca> | 2018-04-11 15:54:27 -0400 |
---|---|---|
committer | gumi <git@gumi.ca> | 2018-04-11 15:54:27 -0400 |
commit | b8cfb2a02fdfa74086b2e34a87af1f687a0b8fd0 (patch) | |
tree | 2305f447c037f002db0036d99d5ce810824507f2 /src/routers/tmwa/middlewares/account.js | |
parent | ac5a25d7aea0626aa0f42d6bc31399aee6e7e90f (diff) | |
download | api-b8cfb2a02fdfa74086b2e34a87af1f687a0b8fd0.tar.gz api-b8cfb2a02fdfa74086b2e34a87af1f687a0b8fd0.tar.bz2 api-b8cfb2a02fdfa74086b2e34a87af1f687a0b8fd0.tar.xz api-b8cfb2a02fdfa74086b2e34a87af1f687a0b8fd0.zip |
EXPERIMENTAL: automated password resets for tmwa
Diffstat (limited to 'src/routers/tmwa/middlewares/account.js')
-rw-r--r-- | src/routers/tmwa/middlewares/account.js | 127 |
1 files changed, 126 insertions, 1 deletions
diff --git a/src/routers/tmwa/middlewares/account.js b/src/routers/tmwa/middlewares/account.js index 1249618..9c3afce 100644 --- a/src/routers/tmwa/middlewares/account.js +++ b/src/routers/tmwa/middlewares/account.js @@ -1,4 +1,6 @@ -module.exports = exports = (req, res, next) => { +const randomNumber = require("random-number-csprng"); + +const create_account = (req, res, next) => { if (!req.body || !Reflect.has(req.body, "username") || !Reflect.has(req.body, "password") || !Reflect.has(req.body, "email") || !req.body.username.match(/^[a-zA-Z0-9]{4,23}$/) || @@ -61,3 +63,126 @@ module.exports = exports = (req, res, next) => { }); }); }; + + + +const reset_password = async (req, res, next) => { + if (req.body && Reflect.has(req.body, "email") && + Reflect.has(req.body, "username") && + req.body.username.match(/^[a-zA-Z0-9]{4,23}$/) && + req.body.email.match(/^(?:[a-zA-Z0-9.$&+=_~-]{1,34}@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,35}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,34}[a-zA-Z0-9])?){0,9})$/) && + req.body.email.length >= 3 && req.body.email.length < 40) + { + req.app.locals.tmwa.db_pool.getConnection(async (err, db) => { + if (err) { + res.status(500).json({ + status: "error", + error: "couldn't reach the database" + }); + console.warn("TMWA.account: a connection with the database couldn't be established"); + return; + } + + // XXX: we might want to use uuid instead, and put the value in the url directly + const rng = await randomNumber(1000000, 999999999999); + const code = String(rng).padStart(12, "0"); + + const query_params = { // SET + "PASSWORD": code, + "STATE": 3, + }; + + db.query(`UPDATE ${req.app.locals.tmwa.db_tables.register} SET ? WHERE USERNAME = ? AND EMAIL = ? AND STATE = 1`, [query_params, req.body.username, req.body.email], (err, rows, fields) => { + if (err) { + res.status(500).json({ + status: "error", + error: "couldn't send a password reset" + }); + console.error("TMWA.account: an unexpected sql error occured: %s", err.code); + } else { + res.status(200).json({ + status: "success" + }); + req.app.locals.rate_limiting.add(req.ip); + setTimeout(() => req.app.locals.rate_limiting.delete(req.ip), 5000); + + // TODO: make the request expire and change the STATE back to 1 upon expiration + } + + db.release(); // return this connection to the pool + }); + }); + return; + } + + if (!req.body || !Reflect.has(req.body, "username") || + !Reflect.has(req.body, "password") || !Reflect.has(req.body, "code") || + !req.body.username.match(/^[a-zA-Z0-9]{4,23}$/) || + !req.body.password.match(/^[a-zA-Z0-9]{4,23}$/) || + !req.body.code.match(/^[a-zA-Z0-9-_]{6,128}$/)) + { + res.status(400).json({ + status: "error", + error: "malformed request" + }); + req.app.locals.rate_limiting.add(req.ip); + setTimeout(() => req.app.locals.rate_limiting.delete(req.ip), 300000); + return; + } + + req.app.locals.tmwa.db_pool.getConnection((err, db) => { + if (err) { + res.status(500).json({ + status: "error", + error: "couldn't reach the database" + }); + console.warn("TMWA.account: a connection with the database couldn't be established"); + return; + } + + const query_params = { // SET + "PASSWORD": req.body.password, + "STATE": 5, + }; + + db.query(`UPDATE ${req.app.locals.tmwa.db_tables.register} SET ? WHERE USERNAME = ? AND PASSWORD = ? AND STATE = 4`, [query_params, req.body.username, req.body.code], (err, rows, fields) => { + if (err) { + res.status(500).json({ + status: "error", + error: "couldn't change the password" + }); + console.error("TMWA.account: an unexpected sql error occured: %s", err.code); + } else if (rows.affectedRows < 1) { + res.status(403).json({ + status: "error", + error: "invalid code" + }); + req.app.locals.rate_limiting.add(req.ip); + setTimeout(() => req.app.locals.rate_limiting.delete(req.ip), 2000); + return; + } else { + res.status(200).json({ + status: "success" + }); + console.info("TMWA.account: a password was reset: %s [%s]", query_params.USERNAME, req.ip); + req.app.locals.rate_limiting.add(req.ip); + setTimeout(() => req.app.locals.rate_limiting.delete(req.ip), 300000); + } + + db.release(); // return this connection to the pool + }); + }); +}; + + + +module.exports = exports = (req, res, next) => { + switch(req.method) { + case "POST": + return create_account(req, res, next); + case "PUT": + return reset_password(req, res, next); + default: + next(); // fallthrough to default endpoint (404) + } +}; |