From ebd27f93c1a18f3f39384bc1c4d525ef944a901e Mon Sep 17 00:00:00 2001 From: MrFry Date: Tue, 7 Apr 2020 09:26:45 +0200 Subject: [PATCH] Authetication, logger middleware, db create tool --- .../api => middlewares}/auth.middleware.js | 12 +++- middlewares/reqlogger.middleware.js | 32 +++++++++++ modules/api/api.js | 55 +++++-------------- modules/api/apiDBStruct.json | 21 +++++-- modules/dataEditor/dataEditor.js | 1 + modules/qmining/qmining-page | 2 +- modules/qmining/qmining.js | 27 ++++----- server.js | 26 --------- utils/dbSetup.js | 39 +++++++++++++ utils/dbtools.js | 34 ++++++++++-- utils/logger.js | 9 ++- 11 files changed, 164 insertions(+), 94 deletions(-) rename {modules/api => middlewares}/auth.middleware.js (87%) create mode 100644 middlewares/reqlogger.middleware.js create mode 100644 utils/dbSetup.js diff --git a/modules/api/auth.middleware.js b/middlewares/auth.middleware.js similarity index 87% rename from modules/api/auth.middleware.js rename to middlewares/auth.middleware.js index 926f092..700b267 100644 --- a/modules/api/auth.middleware.js +++ b/middlewares/auth.middleware.js @@ -1,5 +1,5 @@ -const logger = require('../../utils/logger.js') -const dbtools = require('../../utils/dbtools.js') +const logger = require('../utils/logger.js') +const dbtools = require('../utils/dbtools.js') const exceptions = [ 'favicon', @@ -47,8 +47,15 @@ module.exports = function (options) { return } + req.session = { + user: user, + sessionID: sessionID + } + logger.DebugLog(`ID #${user.id}: ${req.url}`, 'auth', 1) + // TODO: add stat to acesses table + dbtools.Update(authDB, 'sessions', { lastAccess: new Date().toString() }, { @@ -69,6 +76,7 @@ module.exports = function (options) { function GetUserBySessionID (db, sessionID, req) { logger.DebugLog(`Getting user from db`, 'auth', 2) + // TODO: check same ip? const session = dbtools.Select(db, 'sessions', { id: sessionID })[0] diff --git a/middlewares/reqlogger.middleware.js b/middlewares/reqlogger.middleware.js new file mode 100644 index 0000000..609dbed --- /dev/null +++ b/middlewares/reqlogger.middleware.js @@ -0,0 +1,32 @@ +const logger = require('../utils/logger.js') + +// TODO: use this middleware in all modules + +module.exports = function (options) { + const loggableKeywords = options ? options.loggableKeywords : undefined + + return function (req, res, next) { + res.on('finish', function () { + if (req.url.includes('_next/static')) { + return + } + + const ip = req.headers['cf-connecting-ip'] || req.connection.remoteAddress + const hostname = req.hostname.replace('www.', '').split('.')[0] + // TODO: merge req.url and req.hostname checking + // TODO: regexp includes checking + let toLog = loggableKeywords && loggableKeywords.some((x) => { + return req.url.includes(x) + }) + + if (hostname.includes('dataeditor')) { + toLog = true + } + + logger.LogReq(req, true, res.statusCode) + if (toLog) { logger.LogReq(req) } + if (res.statusCode !== 404) { logger.LogStat(req.url, ip) } + }) + next() + } +} diff --git a/modules/api/api.js b/modules/api/api.js index 6567cf8..d3b5726 100644 --- a/modules/api/api.js +++ b/modules/api/api.js @@ -33,7 +33,8 @@ const logger = require('../../utils/logger.js') const utils = require('../../utils/utils.js') const actions = require('../../utils/actions.js') const dbtools = require('../../utils/dbtools.js') -const auth = require('../../modules/api/auth.middleware.js') +const auth = require('../../middlewares/auth.middleware.js') +const reqlogger = require('../../middlewares/reqlogger.middleware.js') const recivedFiles = 'public/recivedfiles' const uloadFiles = 'public/f' @@ -45,34 +46,11 @@ const passwordFile = 'data/dataEditorPasswords.json' const dataEditsLog = 'stats/dataEdits' const dailyDataCountFile = 'stats/dailyDataCount' const usersDBPath = 'data/dbs/users.db' -const dbStructPath = './modules/api/apiDBStruct.json' -let authDB -function CreateDB () { - const dbStruct = utils.ReadJSON(dbStructPath) - // TODO: check if path exists, create it if not - authDB = dbtools.GetDB(usersDBPath) - - // TODO: foreign key - Object.keys(dbStruct).forEach((tableName) => { - const tableData = dbStruct[tableName] - dbtools.CreateTable(authDB, tableName, tableData.tableStruct) - }) - - // TODO: fill with data - dbtools.Insert(authDB, 'users', { - pw: 2, - id: 2, - notes: 'hemnlo' - }) - dbtools.Insert(authDB, 'users', { - pw: 1, - id: 1, - notes: 'hemnlo' - }) - // console.log(dbtools.TableInfo(authDB, 'users')) +if (!utils.FileExists(usersDBPath)) { + throw new Error('No user DB exists yet! please run utils/dbSetup.js first!') } -CreateDB() +const authDB = dbtools.GetDB(usersDBPath) const cookieSecret = uuidv4() app.use(cookieParser(cookieSecret)) @@ -92,6 +70,9 @@ app.use(auth({ authDB: authDB, jsonResponse: true })) +app.use(reqlogger([ + 'stable.user.js' // TODO +])) app.use(express.static('public')) app.use(busboy({ limits: { @@ -130,9 +111,7 @@ Load() // ------------------------------------------------------------- app.post('/login', (req, res) => { - // TODO: user.logincount update in db logger.LogReq(req) - const isScript = req.body.script const pw = req.body.pw const ip = req.headers['cf-connecting-ip'] || req.connection.remoteAddress const user = dbtools.Select(authDB, 'users', { @@ -174,15 +153,10 @@ app.post('/login', (req, res) => { // TODO: cookie age res.cookie('sessionID', sessionID) - if (isScript) { - res.json({ - result: 'success', - sessionID: sessionID - }) - } else { - // FIXME: redirect to original url - res.redirect('/') - } + res.json({ + result: 'success', + sessionID: sessionID + }) logger.Log(`Successfull login with user ID: #${user.id}`, logger.GetColor('cyan')) } else { @@ -202,8 +176,9 @@ app.post('/logout', (req, res) => { id: sessionID }) // TODO: remove old sessions every once in a while - // FIXME: redirect to original url - res.clearCookie('sessionID').redirect('/') + res.clearCookie('sessionID').json({ + result: 'success' + }) }) // -------------------------------------------------------------- diff --git a/modules/api/apiDBStruct.json b/modules/api/apiDBStruct.json index 974c6f0..2782a24 100644 --- a/modules/api/apiDBStruct.json +++ b/modules/api/apiDBStruct.json @@ -1,13 +1,15 @@ { "users": { "tableStruct": { + "id": { + "type": "integer", + "primary": true, + "autoIncrement": true + }, "pw": { "type": "text", - "primary": true, - "notNull": true - }, - "id": { - "type": "number" + "notNull": true, + "unique": true }, "lastIP": { "type": "text" @@ -27,6 +29,15 @@ } }, "sessions": { + "foreignKey": { + "keysFrom": [ + "userID" + ], + "table": "users", + "keysTo": [ + "id" + ] + }, "tableStruct": { "id": { "type": "text", diff --git a/modules/dataEditor/dataEditor.js b/modules/dataEditor/dataEditor.js index a3adc7a..36e1422 100644 --- a/modules/dataEditor/dataEditor.js +++ b/modules/dataEditor/dataEditor.js @@ -71,6 +71,7 @@ AddHtmlRoutes(utils.ReadDir('modules/dataEditor/public')) // -------------------------------------------------------------- app.get('/', function (req, res) { + // TODO: log this, regexp $/^ res.end('hai') logger.LogReq(req) }) diff --git a/modules/qmining/qmining-page b/modules/qmining/qmining-page index 72ea24c..9f576a4 160000 --- a/modules/qmining/qmining-page +++ b/modules/qmining/qmining-page @@ -1 +1 @@ -Subproject commit 72ea24c07133d02a983152b4416ff98eb5dc4369 +Subproject commit 9f576a41f6a8b1de82f2a0cf901046a76ff9a1ed diff --git a/modules/qmining/qmining.js b/modules/qmining/qmining.js index de825c0..2f8d558 100644 --- a/modules/qmining/qmining.js +++ b/modules/qmining/qmining.js @@ -23,6 +23,7 @@ const bodyParser = require('body-parser') const busboy = require('connect-busboy') const app = express() +const reqlogger = require('../../middlewares/reqlogger.middleware.js') const utils = require('../../utils/utils.js') const logger = require('../../utils/logger.js') @@ -33,19 +34,6 @@ try { logger.Log('Couldnt read donate URL file!', logger.GetColor('red')) } -app.set('view engine', 'ejs') -app.set('views', [ - './modules/qmining/views', - './sharedViews' -]) -app.use(express.static('modules/qmining/public')) -app.use(express.static('public')) -app.use(busboy({ - limits: { - fileSize: 10000 * 1024 * 1024 - } -})) -app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ limit: '5mb', extended: true @@ -53,6 +41,19 @@ app.use(bodyParser.urlencoded({ app.use(bodyParser.json({ limit: '5mb' })) +app.set('view engine', 'ejs') +app.set('views', [ + './modules/qmining/views', + './sharedViews' +]) +app.use(reqlogger()) +app.use(express.static('modules/qmining/public')) +app.use(express.static('public')) +app.use(busboy({ + limits: { + fileSize: 10000 * 1024 * 1024 + } +})) // -------------------------------------------------------------- // REDIRECTS diff --git a/server.js b/server.js index 56a6a11..146d6c5 100755 --- a/server.js +++ b/server.js @@ -34,9 +34,6 @@ const cors = require('cors') const extraModulesFile = './extraModules.json' const modulesFile = './modules.json' -const loggableKeywords = [ - 'user.js' -] let modules = JSON.parse(utils.ReadFile(modulesFile)) logger.Load() @@ -57,29 +54,6 @@ try { const app = express() app.use(cors()) -app.use(function (req, res, next) { - res.on('finish', function () { - if (req.url.includes('_next/static')) { - return - } - let ip = req.headers['cf-connecting-ip'] || req.connection.remoteAddress - logger.LogReq(req, true, res.statusCode) - - let toLog = loggableKeywords.some((x) => { - return req.url.includes(x) - }) - const hostname = req.hostname.replace('www.', '').split('.')[0] - - if (hostname.includes('dataeditor')) { - toLog = true - } - - if (toLog) { logger.LogReq(req) } - if (res.statusCode !== 404) { logger.LogStat(req.url, ip) } - }) - next() -}) - Object.keys(modules).forEach(function (k, i) { let x = modules[k] try { diff --git a/utils/dbSetup.js b/utils/dbSetup.js new file mode 100644 index 0000000..ec14b52 --- /dev/null +++ b/utils/dbSetup.js @@ -0,0 +1,39 @@ + +const utils = require('../utils/utils.js') +const dbtools = require('../utils/dbtools.js') +const dbStructPath = '../modules/api/apiDBStruct.json' +const usersDBPath = '../data/dbs/users.db' + +let authDB + +console.clear() + +function CreateDB () { + const dbStruct = utils.ReadJSON(dbStructPath) + authDB = dbtools.GetDB(usersDBPath) + + Object.keys(dbStruct).forEach((tableName) => { + const tableData = dbStruct[tableName] + dbtools.CreateTable(authDB, tableName, tableData.tableStruct, tableData.foreignKey) + }) + + try { + // TODO: fill with data + dbtools.Insert(authDB, 'users', { + pw: 2, + notes: 'hemnlo' + }) + dbtools.Insert(authDB, 'users', { + pw: 1, + notes: 'hemnlo' + }) + } catch (e) { + console.error(e) + } + + // Object.keys(dbStruct).forEach((key) => { + // console.log(key) + // console.log(dbtools.TableInfo(authDB, key)) + // }) +} +CreateDB() diff --git a/utils/dbtools.js b/utils/dbtools.js index 2c6b39d..a1a0ea3 100644 --- a/utils/dbtools.js +++ b/utils/dbtools.js @@ -109,19 +109,41 @@ function Delete (db, table, conditions) { } } -function CreateTable (db, name, columns) { +function CreateTable (db, name, columns, foreignKeys) { + // CREATE TABLE users(pw text PRIMARY KEY NOT NULL, id number, lastIP text, notes text, loginCount + // number, lastLogin text, lastAccess text + // + // FOREIGN KEY(songartist, songalbum) REFERENCES album(albumartist, albumname) ) + try { const cols = Object.keys(columns).reduce((acc, key) => { const item = columns[key] - const isPrimary = item.primary ? ' PRIMARY KEY' : '' - const isNotNull = item.notNull ? ' NOT NULL' : '' + // FIXME: array, and push stuff, then join() + const flags = [] + const toCheck = { + primary: 'PRIMARY KEY', + notNull: 'NOT NULL', + unique: 'UNIQUE', + autoIncrement: 'AUTOINCREMENT' + } + Object.keys(toCheck).forEach((key) => { + if (item[key]) { + flags.push(toCheck[key]) + } + }) - acc.push(`${key} ${item.type}${isPrimary}${isNotNull}`) + acc.push(`${key} ${item.type} ${flags.join(' ')}`) return acc }, []).join(', ') - // IF NOT EXISTS // TODO - const s = `CREATE TABLE ${name}(${cols})` + let fKeys = '' + if (foreignKeys) { + const { keysFrom, table, keysTo } = foreignKeys + fKeys = `, FOREIGN KEY(${keysFrom.join(', ')}) REFERENCES ${table}(${keysTo.join(', ')})` + } + + // IF NOT EXISTS + const s = `CREATE TABLE ${name}(${cols}${fKeys})` DebugLog(s) const stmt = db.prepare(s) diff --git a/utils/logger.js b/utils/logger.js index 8f1aff3..a0329cd 100755 --- a/utils/logger.js +++ b/utils/logger.js @@ -125,7 +125,14 @@ function LogReq (req, toFile, sc) { hostname = 'NOHOST' Log('req.hostname is undefined! req.hostname: ' + req.hostname, GetColor('redbg')) } - logEntry += dl + hostname + dl + req.headers['user-agent'] + dl + req.method + dl + logEntry += dl + + hostname + dl + + req.headers['user-agent'] + dl + + req.method + dl + + if (req.session && req.session.user) { + logEntry += C('cyan') + req.session.user.id + C() + dl + } logEntry += GetRandomColor(req.url.split('?')[0]) + req.url