From 3757bad043a8ccbdd2db5078fa257ae7b579568c Mon Sep 17 00:00:00 2001 From: "Zander M." Date: Sat, 30 Sep 2023 02:37:48 -0400 Subject: [PATCH] Get login and session-handling working and begin work on dashboard. --- .env.example | 2 +- README.md | Bin 27802 -> 27946 bytes package-lock.json | 26 ++ package.json | 1 + public/js/common-script.js | 17 + public/js/datatables-simple.js | 9 + public/stylesheets/style.css | 9 +- public/stylesheets/styles.css | 2 +- routes/index.js | 78 +++- views/dashboard.hbs | 636 +++++++++++++++++++++++++++++++++ views/index.hbs | 22 +- views/layout.hbs | 18 +- 12 files changed, 785 insertions(+), 35 deletions(-) create mode 100644 public/js/datatables-simple.js diff --git a/.env.example b/.env.example index 58387e6..1820032 100644 --- a/.env.example +++ b/.env.example @@ -59,7 +59,7 @@ API_RATE_REQUESTS=1000 API_RATE_WINDOW=60000 # --- Google ReCaptcha --- -# TechnicFlux comes with Google ReCaptcha support. +# TechnicFlux comes with optional Google ReCaptcha support. # When configured, this will enable captcha protection on your login page. # (Optional) Google ReCaptcha Credentials diff --git a/README.md b/README.md index 1185cde8062b2fd6016d3bbdee89247da243dea2..cad7f4eaa3497f6b98f24afa34b68bdda3d57112 100644 GIT binary patch delta 60 zcmbPrlX2B8#tl<~C*KJW;16R+WXNI2WJm$hB@FqK8v~ptI|K>{mZ6F>6m4z~7M276 DXbBPy delta 14 WcmZ2=i*eRX#tl<~H>-rONdf>gM+Mse diff --git a/package-lock.json b/package-lock.json index 71e9c2d..454fc57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "express-rate-limit": "^7.0.2", "express-recaptcha": "^5.1.0", "express-session": "^1.17.3", + "express-validator": "^7.0.1", "hbs": "~4.2.0", "http-errors": "~1.6.3", "mongoose": "^7.5.3", @@ -1719,6 +1720,18 @@ } ] }, + "node_modules/express-validator": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", + "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "dependencies": { + "lodash": "^4.17.21", + "validator": "^13.9.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/express/node_modules/cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -2784,6 +2797,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4514,6 +4532,14 @@ "node": ">= 0.4.0" } }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 39a11d0..d4ac98e 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "express-rate-limit": "^7.0.2", "express-recaptcha": "^5.1.0", "express-session": "^1.17.3", + "express-validator": "^7.0.1", "hbs": "~4.2.0", "http-errors": "~1.6.3", "mongoose": "^7.5.3", diff --git a/public/js/common-script.js b/public/js/common-script.js index e69de29..1073da2 100644 --- a/public/js/common-script.js +++ b/public/js/common-script.js @@ -0,0 +1,17 @@ +window.addEventListener('DOMContentLoaded', event => { + + // Toggle the side navigation + const sidebarToggle = document.body.querySelector('#sidebarToggle'); + if (sidebarToggle) { + // Uncomment Below to persist sidebar toggle between refreshes + // if (localStorage.getItem('sb|sidebar-toggle') === 'true') { + // document.body.classList.toggle('sb-sidenav-toggled'); + // } + sidebarToggle.addEventListener('click', event => { + event.preventDefault(); + document.body.classList.toggle('sb-sidenav-toggled'); + localStorage.setItem('sb|sidebar-toggle', document.body.classList.contains('sb-sidenav-toggled')); + }); + } + +}); \ No newline at end of file diff --git a/public/js/datatables-simple.js b/public/js/datatables-simple.js new file mode 100644 index 0000000..c02639b --- /dev/null +++ b/public/js/datatables-simple.js @@ -0,0 +1,9 @@ +window.addEventListener('DOMContentLoaded', event => { + // Simple-DataTables + // https://github.com/fiduswriter/Simple-DataTables/wiki + + const datatablesSimple = document.getElementById('datatablesSimple'); + if (datatablesSimple) { + new simpleDatatables.DataTable(datatablesSimple); + } +}); diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index dcc9c75..775efd4 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -2,14 +2,15 @@ body { font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; } -.pageContent { - padding: 50px; -} - a { color: #00B7FF; } +.pageContent { + position: relative; + min-height: 100vh; +} + .grecaptcha-badge { margin-bottom: 65px; } diff --git a/public/stylesheets/styles.css b/public/stylesheets/styles.css index 1898a06..1fd6112 100644 --- a/public/stylesheets/styles.css +++ b/public/stylesheets/styles.css @@ -10961,7 +10961,7 @@ body { margin-left: 1.5rem; flex-direction: column; } -.sb-sidenav .sb-sidenav-footer { +.sb-sidenav .sb-sidenav-header { padding: 0.75rem; flex-shrink: 0; } diff --git a/routes/index.js b/routes/index.js index 3802ec5..a3fd25a 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,9 @@ const express = require('express') -const router = express.Router() +const database = require('../database/database') +const { body, validationResult } = require('express-validator') const { RecaptchaV3 } = require('express-recaptcha') +const router = express.Router() + // --- Google ReCaptcha const site_key = process.env?.CAPTCHA_SITE_KEY @@ -12,25 +15,82 @@ const recaptcha = captcha_enabled ? new RecaptchaV3(site_key, site_secret, { /* GET home page. */ router.get('/', captcha_enabled ? recaptcha.middleware.render : (req, res, next) => {next()}, function (req, res) { - res.render('index', { - title: 'TechnicFlux', - captcha: captcha_enabled ? res.recaptcha : false - }) + if (!req.session.user) { + return res.render('index', { + title: 'TechnicFlux', + captcha: captcha_enabled ? res.recaptcha : false + }) + } else { + return res.render('dashboard', { + title: 'TechnicFlux', + user: req.session.user + }) + } }) /* POST home page (login info w/ captcha) */ -router.post('/', captcha_enabled ? recaptcha.middleware.verify : (req, res, next) => {next()}, function (req, res) { +router.post('/', [ + captcha_enabled ? recaptcha.middleware.verify : (req, res, next) => {next()}, + captcha_enabled ? recaptcha.middleware.render : (req, res, next) => {next()}, + body('username').notEmpty().isLength({min: 4, max: 50}).escape(), + body('password').notEmpty().isLength({min: 4, max: 50}).escape(), +], function (req, res) { + const result = validationResult(req) + // Validate captcha, if enabled. if (captcha_enabled && req.recaptcha.error) { + console.log(captcha_enabled) return res.render('index', { title: 'TechnicFlux', captcha: captcha_enabled ? res.recaptcha : false, - error: "Captcha validation failed! Ensure that javascript is enabled!" + error: "Captcha validation failed! Ensure javascript is enabled!" }) } - // Check login info - res.json({success: "yay"}) + // Check that login details pass validation + if (result.isEmpty()) { + if (req.body.username === process.env.ADMIN_USER && req.body.password === process.env.ADMIN_PASS) { + req.session.user = { + _id: 0, + username: process.env.ADMIN_USER, + display_name: `${process.env.ADMIN_USER} (Admin)`, + admin: true + } + return res.redirect('/') + } + + // Check login info + return database.user.authUser(`${req.body.username}`, + `${req.body.password}`, + true, + req.get('User-Agent') || 'Unknown' + ).then((user) => { + if (user[0] === true) { + // User login successful. + req.session.user = user[1] + res.redirect('/') + } else { + // User login failed. + return res.render('index', { + title: 'TechnicFlux', + captcha: captcha_enabled ? res.recaptcha : false, + error: "Invalid username or password! Please try again." + }) + } + }) + } else { + return res.render('index', { + title: 'TechnicFlux', + captcha: captcha_enabled ? res.recaptcha : false, + error: "Error: Malformed login data submitted." + }) + } +}) + +router.get('/logout', (req, res) => { + req.session.destroy(() => { + res.redirect('/') + } ) }) module.exports = router diff --git a/views/dashboard.hbs b/views/dashboard.hbs index e69de29..9a1b6fd 100644 --- a/views/dashboard.hbs +++ b/views/dashboard.hbs @@ -0,0 +1,636 @@ + +
+ +
+
+
+
+
+
+
Total Runs
+
+

0

+
+
+
+
+
+
Total Downloads
+
+

0

+
+
+
+
+
+
Total Likes
+
+

0

+
+
+
+
+
+
+ + DataTable Example +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePositionOfficeAgeStart dateSalary
NamePositionOfficeAgeStart dateSalary
Tiger NixonSystem ArchitectEdinburgh612011/04/25$320,800
Garrett WintersAccountantTokyo632011/07/25$170,750
Ashton CoxJunior Technical AuthorSan Francisco662009/01/12$86,000
Cedric KellySenior Javascript DeveloperEdinburgh222012/03/29$433,060
Airi SatouAccountantTokyo332008/11/28$162,700
Brielle WilliamsonIntegration SpecialistNew York612012/12/02$372,000
Herrod ChandlerSales AssistantSan Francisco592012/08/06$137,500
Rhona DavidsonIntegration SpecialistTokyo552010/10/14$327,900
Colleen HurstJavascript DeveloperSan Francisco392009/09/15$205,500
Sonya FrostSoftware EngineerEdinburgh232008/12/13$103,600
Jena GainesOffice ManagerLondon302008/12/19$90,560
Quinn FlynnSupport LeadEdinburgh222013/03/03$342,000
Charde MarshallRegional DirectorSan Francisco362008/10/16$470,600
Haley KennedySenior Marketing DesignerLondon432012/12/18$313,500
Tatyana FitzpatrickRegional DirectorLondon192010/03/17$385,750
Michael SilvaMarketing DesignerLondon662012/11/27$198,500
Paul ByrdChief Financial Officer (CFO)New York642010/06/09$725,000
Gloria LittleSystems AdministratorNew York592009/04/10$237,500
Bradley GreerSoftware EngineerLondon412012/10/13$132,000
Dai RiosPersonnel LeadEdinburgh352012/09/26$217,500
Jenette CaldwellDevelopment LeadNew York302011/09/03$345,000
Yuri BerryChief Marketing Officer (CMO)New York402009/06/25$675,000
Caesar VancePre-Sales SupportNew York212011/12/12$106,450
Doris WilderSales AssistantSidney232010/09/20$85,600
Angelica RamosChief Executive Officer (CEO)London472009/10/09$1,200,000
Gavin JoyceDeveloperEdinburgh422010/12/22$92,575
Jennifer ChangRegional DirectorSingapore282010/11/14$357,650
Brenden WagnerSoftware EngineerSan Francisco282011/06/07$206,850
Fiona GreenChief Operating Officer (COO)San Francisco482010/03/11$850,000
Shou ItouRegional MarketingTokyo202011/08/14$163,000
Michelle HouseIntegration SpecialistSidney372011/06/02$95,400
Suki BurksDeveloperLondon532009/10/22$114,500
Prescott BartlettTechnical AuthorLondon272011/05/07$145,000
Gavin CortezTeam LeaderSan Francisco222008/10/26$235,500
Martena MccrayPost-Sales supportEdinburgh462011/03/09$324,050
Unity ButlerMarketing DesignerSan Francisco472009/12/09$85,675
Howard HatfieldOffice ManagerSan Francisco512008/12/16$164,500
Hope FuentesSecretarySan Francisco412010/02/12$109,850
Vivian HarrellFinancial ControllerSan Francisco622009/02/14$452,500
Timothy MooneyOffice ManagerLondon372008/12/11$136,200
Jackson BradshawDirectorNew York652008/09/26$645,750
Olivia LiangSupport EngineerSingapore642011/02/03$234,500
Bruno NashSoftware EngineerLondon382011/05/03$163,500
Sakura YamamotoSupport EngineerTokyo372009/08/19$139,575
Thor WaltonDeveloperNew York612013/08/11$98,540
Finn CamachoSupport EngineerSan Francisco472009/07/07$87,500
Serge BaldwinData CoordinatorSingapore642012/04/09$138,575
Zenaida FrankSoftware EngineerNew York632010/01/04$125,250
Zorita SerranoSoftware EngineerSan Francisco562012/06/01$115,000
Jennifer AcostaJunior Javascript DeveloperEdinburgh432013/02/01$75,650
Cara StevensSales AssistantNew York462011/12/06$145,600
Hermione ButlerRegional DirectorLondon472011/03/21$356,250
Lael GreerSystems AdministratorLondon212009/02/27$103,500
Jonas AlexanderDeveloperSan Francisco302010/07/14$86,500
Shad DeckerRegional DirectorEdinburgh512008/11/13$183,000
Michael BruceJavascript DeveloperSingapore292011/06/27$183,000
Donna SniderCustomer SupportNew York272011/01/25$112,000
+
+
+
+
+
+
+
+
Copyright © Zandercraft 2023. + Distributed under the MIT License. + We are not affiliated with Mojang, AB or Syndicate LLC. +
+ +
+
+
+
+
+ + + + + + + diff --git a/views/index.hbs b/views/index.hbs index 89a0631..d7edfc1 100644 --- a/views/index.hbs +++ b/views/index.hbs @@ -13,13 +13,13 @@ {{error}} {{/if}} -
+
- +
- +
@@ -37,6 +37,22 @@
+ {{#if captcha}} {{{captcha}}} diff --git a/views/layout.hbs b/views/layout.hbs index 0f6ce5f..5cd982e 100644 --- a/views/layout.hbs +++ b/views/layout.hbs @@ -9,28 +9,12 @@ +
{{{body}}}
- -