diff --git a/init.sql b/init.sql index 00b4abd1..93286b38 100644 --- a/init.sql +++ b/init.sql @@ -17,18 +17,33 @@ INSERT INTO `config`(`flag`, `value`) VALUES ("default_avatar","/statics/avatar. INSERT INTO `config`(`flag`, `value`) VALUES ("ip_detect_method","connection"); INSERT INTO `config`(`flag`, `value`) VALUES ("ip_detect_header","X-Forwarded-From"); -INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_posts","12"); -INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_register","1"); -INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_react","64"); -INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_comment","60"); +INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_create",'{ + "article": 12, + "posts": 12, + "notes": 30, + "react": 64, + "comment": 60 +}'); INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_remove",' { + "article": 12, - "posts": 12, - "react": 128, + "posts": 20, + "notes": 30, + "react": 128, + "comment": 60 + +}'); +INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_edit",' +{ + + "article": 12, + "posts": 20, + "notes": 30, + "react": 128, "comment": 60 + }'); -INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_articles","12"); INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_login","30"); INSERT INTO `config`(`flag`, `value`) VALUES ("ip_rate_limit_bypass_whitelist","[127.0.0.1]"); diff --git a/modules/rate_control.mjs b/modules/rate_control.mjs new file mode 100644 index 00000000..bcf5fa4d --- /dev/null +++ b/modules/rate_control.mjs @@ -0,0 +1,16 @@ +function rateControlMiddleware(log, redisConnection){ + this.middleware = function(req, res, next){ + next(); + } +} + +export default function(log, redisConnection){ + try{ + let middleware = new rateControlMiddleware(log, redisConnection).middleware; + log("log", "RateControl", "Rate control middleware instance created."); + return middleware; + }catch(err){ + log("error", "RateControl", "Rate control middleware failed to load."); + log("error", "RateControl", err); + } +} \ No newline at end of file diff --git a/modules/router.mjs b/modules/router.mjs index 08c96107..65eaddb9 100644 --- a/modules/router.mjs +++ b/modules/router.mjs @@ -8,8 +8,25 @@ import { default as fs } from "fs"; import { fileURLToPath } from "url"; import { join } from "path"; import { default as bodyParser } from "body-parser"; +import { default as RCM } from "./rate_control.mjs"; +import { default as SCM } from "./session_check.mjs"; function initializeRouter(mysqlConnection, redisConnection, siteConfig, log, salt, redisPrefix){ + let ipWhiteList = siteConfig.ip_rate_limit_bypass_whitelist; + let ipRateLimits = { + "create": JSON.parse(siteConfig.ip_rate_limit_create), + "remove": JSON.parse(siteConfig.ip_rate_limit_remove), + "edit": JSON.parse(siteConfig.ip_rate_limit_edit), + "login": siteConfig.ip_rate_limit_login, + "get": siteConfig.ip_rate_limit_get + }; + let timestamp = function(){ + return new Date().getTime(); + }; + let expireThreshold = 3600000; + let isTimestampExpired = function(val){ + return val + expireThreshold < timestamp(); + }; let getReqInfo = function(req){ let ip = null; let ua = null; @@ -21,9 +38,7 @@ function initializeRouter(mysqlConnection, redisConnection, siteConfig, log, sal ip = req.headers[siteConfig.ip_detect_header]; }else{ log("error", "IAPI", "Dictated IP detection method is header, but header is not found."); - if(req.headers.hasOwnProperty("X-Forwarded-From")){ - ip = req.headers["X-Forwarded-From"]; - }else if(req.headers.hasOwnProperty("x-forwarded-from")){ + if(req.headers.hasOwnProperty("x-forwarded-from")){ ip = req.headers["x-forwarded-from"]; }else{ ip = req.connection.remoteAddress; @@ -35,8 +50,6 @@ function initializeRouter(mysqlConnection, redisConnection, siteConfig, log, sal } if(req.headers.hasOwnProperty("user-agent")){ ua = req.headers["user-agent"]; - }else if(req.headers.hasOwnProperty("User-Agent")){ - ua = req.headers["User-Agent"]; }else{ ua = "Unknown/0"; } @@ -54,6 +67,33 @@ function initializeRouter(mysqlConnection, redisConnection, siteConfig, log, sal "Access-Control-Allow-Origin": "*" }; + let sessionCheckMiddleware = SCM(log, redisConnection); + try { + blorumRouter.use(sessionCheckMiddleware); + log("log", "Router", "Session check middleware applied."); + } catch (error) { + log("log", "Router", "Failed to apply session check middleware."); + process.exit(1); + } + + let rateControlMiddleware = RCM(log, redisConnection); + try { + blorumRouter.use(rateControlMiddleware); + log("log", "Router", "Rate control middleware applied."); + } catch (error) { + log("log", "Router", "Failed to apply rate control middleware."); + } + + blorumRouter.use(bodyParser.json({limit: '50mb'})); + blorumRouter.use(function(err, req, res, next){ + if (err instanceof SyntaxError) { + res.set(commonHeader); + res.status(400).send('Bad Request'); + } else { + next(); + } + }); + blorumRouter.get('/', function (req, res) { res.set("Content-Type","application/json"); res.set(commonHeader); @@ -112,17 +152,6 @@ function initializeRouter(mysqlConnection, redisConnection, siteConfig, log, sal }); //JSON API - blorumRouter.use(bodyParser.json({limit: '50mb'})); - blorumRouter.use(function(err, req, res, next){ - if (err instanceof SyntaxError) { - res.set(commonHeader); - res.status(400).send('Bad Request'); - } else { - next(); - } - } - ); - blorumRouter.post('/user/login', function (req, res) { res.set("Content-Type","application/json"); res.set(commonHeader); @@ -132,6 +161,10 @@ function initializeRouter(mysqlConnection, redisConnection, siteConfig, log, sal if(isAllString(b.username, b.password)){ iapi.userLogin(reqInfo.ip, reqInfo.ua, b.username, b.password).then(function(result){ res.set(commonHeader); + let parsedPermission = ""; //Todo + res.cookie("blorum_uid", result.uid, {httpOnly: true}); + res.cookie("blorum_token", result.token, {httpOnly: true}); + res.cookie("blorum_permissions", parsedPermission, {httpOnly: true}); res.status(200).send(result); }).catch(function(err){ res.set(commonHeader); diff --git a/modules/session_check.mjs b/modules/session_check.mjs new file mode 100644 index 00000000..e26de3cf --- /dev/null +++ b/modules/session_check.mjs @@ -0,0 +1,16 @@ +function SessionCheckMiddleware(log, redisConnection){ + this.middleware = function(req, res, next){ + next(); + } +} + +export default function(log, redisConnection){ + try{ + let middleware = new SessionCheckMiddleware(log, redisConnection).middleware; + log("log", "SessionCheck", "Session check middleware instance created."); + return middleware; + }catch(err){ + log("error", "SessionCheck", "Session check middleware failed to load."); + log("error", "SessionCheck", err); + } +} \ No newline at end of file diff --git a/modules/utils.mjs b/modules/utils.mjs index 36843252..a7318a5d 100644 --- a/modules/utils.mjs +++ b/modules/utils.mjs @@ -2,7 +2,7 @@ import { default as blake3 } from "blake3"; import { default as crypto } from "crypto"; import Redis from "ioredis"; -const version = "1.0.0 in_dev (unf, debug) dv 10003"; +const version = "1.0.0 in_dev (unf, debug) dv 10004"; const c = { "reset": "\x1b[0m", diff --git a/statics/avatar.png b/statics/avatar.png new file mode 100644 index 00000000..d261651e Binary files /dev/null and b/statics/avatar.png differ