You can now log in - fantastic! :D
This commit is contained in:
parent
a10f234a2a
commit
c0adc5e96b
3
index.js
3
index.js
|
@ -1,3 +1,5 @@
|
||||||
|
import cookieParser from 'cookie-parser'
|
||||||
|
import crypto from 'crypto'
|
||||||
import { dbInit } from './libs/database.js'
|
import { dbInit } from './libs/database.js'
|
||||||
import dotenv from 'dotenv'
|
import dotenv from 'dotenv'
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
|
@ -19,6 +21,7 @@ await dbInit()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
APP.use(cookieParser(process.env.CK_SECRET ?? crypto.generateKeySync("aes", { length: 128 }).export().toString(), {}))
|
||||||
APP.use(express.urlencoded({ extended: true }))
|
APP.use(express.urlencoded({ extended: true }))
|
||||||
APP.use('/static', express.static('static'))
|
APP.use('/static', express.static('static'))
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,10 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
"dotenv": "^12.0.3",
|
"dotenv": "^12.0.3",
|
||||||
"express": "^4.17.2",
|
"express": "^4.17.2",
|
||||||
|
"jsonwebtoken": "^8.5.1",
|
||||||
"nunjucks": "^3.2.3",
|
"nunjucks": "^3.2.3",
|
||||||
"pg": "^8.7.1"
|
"pg": "^8.7.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import bcrypt from 'bcrypt'
|
import bcrypt from 'bcrypt'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
|
import jwt from 'jsonwebtoken'
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import { glauth } from '../libs/database.js'
|
import { glauth } from '../libs/database.js'
|
||||||
import execawait from '../libs/execawait.js'
|
import execawait from '../libs/execawait.js'
|
||||||
|
|
||||||
|
export const SECRET = process.env.TK_SECRET ?? crypto.generateKeySync("aes", { length: 128 }).export().toString()
|
||||||
const AUTH = Router()
|
const AUTH = Router()
|
||||||
let valid = {}
|
let valid = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ...
|
* This is needed because GLAuth (GLAuth's bcrypt) and Node (Node's bcrypt) read hashes differently.
|
||||||
* @param {string} hash The hash to be converted to hex.
|
* @param {string} hash The hash to be converted to hex.
|
||||||
* @returns {string} hex of hash
|
* @returns {string} hex of hash
|
||||||
*/
|
*/
|
||||||
|
@ -25,11 +27,9 @@ function hash2hex(hash) {
|
||||||
AUTH.post('/register', async (req, res) => {
|
AUTH.post('/register', async (req, res) => {
|
||||||
const { captcha, password, username } = req.body
|
const { captcha, password, username } = req.body
|
||||||
|
|
||||||
// Was input sent?
|
|
||||||
if (!username || !password || !captcha)
|
if (!username || !password || !captcha)
|
||||||
return(res.send(`Not entered:${username ? '' : ' username,'}${password ? '' : ' password,'}${captcha ? '' : ' captcha'}`))
|
return(res.send(`Not entered:${username ? '' : ' username,'}${password ? '' : ' password,'}${captcha ? '' : ' captcha'}`))
|
||||||
|
|
||||||
// is captcha valid
|
|
||||||
if (!valid[captcha])
|
if (!valid[captcha])
|
||||||
return(res.send("Invalid captcha!"))
|
return(res.send("Invalid captcha!"))
|
||||||
|
|
||||||
|
@ -38,10 +38,10 @@ AUTH.post('/register', async (req, res) => {
|
||||||
if (captchaAge > 600)
|
if (captchaAge > 600)
|
||||||
return(res.send("Invalid captcha!"))
|
return(res.send("Invalid captcha!"))
|
||||||
|
|
||||||
// expire the captcha
|
// Expire the captcha.
|
||||||
delete valid[captcha]
|
delete valid[captcha]
|
||||||
|
|
||||||
// does the username match the requirements
|
// Does the username match the requirements?
|
||||||
if (!(/^(?=[a-zA-Z0-9]{2,20}$).*$/.test(username)))
|
if (!(/^(?=[a-zA-Z0-9]{2,20}$).*$/.test(username)))
|
||||||
return(res.send("Username does not match the requirements"))
|
return(res.send("Username does not match the requirements"))
|
||||||
|
|
||||||
|
@ -59,7 +59,6 @@ AUTH.post('/register', async (req, res) => {
|
||||||
).catch(
|
).catch(
|
||||||
err => res.json({ _: "Sorry an error occured!", err })
|
err => res.json({ _: "Sorry an error occured!", err })
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -77,11 +76,32 @@ AUTH.post('/login', async (req, res) => {
|
||||||
return(res.send("User doesn't exist!"))
|
return(res.send("User doesn't exist!"))
|
||||||
|
|
||||||
bcrypt.compare(password, user.qam_pass).then(
|
bcrypt.compare(password, user.qam_pass).then(
|
||||||
match => {
|
async match => {
|
||||||
if (!match)
|
if (!match)
|
||||||
return res.send("Password's is incorrect!")
|
return res.send("Password's is incorrect!")
|
||||||
|
|
||||||
return res.send("Welcome " + user.name + "!")
|
const bearer = {
|
||||||
|
name: user.name,
|
||||||
|
id: user.uidnumber,
|
||||||
|
group: (await glauth.query("SELECT name FROM groups WHERE gidnumber = $1::int", [ user.primarygroup ])).rows[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = jwt.sign(
|
||||||
|
bearer,
|
||||||
|
SECRET,
|
||||||
|
{ expiresIn: '1h' }
|
||||||
|
)
|
||||||
|
|
||||||
|
const fourHoursInMillis = 60 * 60 * 1000
|
||||||
|
res.cookie(
|
||||||
|
'api-token',
|
||||||
|
token,
|
||||||
|
{
|
||||||
|
expires: new Date(Date.now() + fourHoursInMillis),
|
||||||
|
httpOnly: true,
|
||||||
|
signed: true
|
||||||
|
}
|
||||||
|
).redirect('/manager')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
|
import jwt from 'jsonwebtoken'
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import AUTH from './auth.js'
|
import AUTH, { SECRET } from './auth.js'
|
||||||
|
|
||||||
const ROUTES = Router()
|
const ROUTES = Router()
|
||||||
|
|
||||||
ROUTES.get('/', (_, res) => res.render("pages/landing.njk"))
|
ROUTES.get('/', (_, res) => res.render("pages/landing.njk"))
|
||||||
ROUTES.get('/login', (_, res) => res.render("pages/login.njk"))
|
ROUTES.get('/login', (_, res) => res.render("pages/login.njk"))
|
||||||
ROUTES.get('/register', (_, res) => res.render("pages/register.njk"))
|
ROUTES.get('/register', (_, res) => res.render("pages/register.njk"))
|
||||||
|
ROUTES.get(
|
||||||
|
'/manager',
|
||||||
|
(req, res) => {
|
||||||
|
const apiToken = req.signedCookies['api-token'] ?? null
|
||||||
|
if (!apiToken)
|
||||||
|
return res.redirect('/login')
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!jwt.verify(apiToken, SECRET))
|
||||||
|
return res.redirect('/login')
|
||||||
|
|
||||||
|
const bearer = jwt.decode(apiToken)
|
||||||
|
|
||||||
|
res.render('pages/manager.njk', { user: bearer })
|
||||||
|
} catch (error) {
|
||||||
|
res.redirect('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
ROUTES.use('/auth', AUTH)
|
ROUTES.use('/auth', AUTH)
|
||||||
|
|
||||||
export default ROUTES
|
export default ROUTES
|
|
@ -65,7 +65,6 @@ h6 {
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: .5em 0 .25em 0;
|
margin: .5em 0 .25em 0;
|
||||||
text-align: justify;
|
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,5 +14,7 @@
|
||||||
<input type="password" id="password" name="password" placeholder="VerySecurePassword;PleaseDon'tHackMe!LOL">
|
<input type="password" id="password" name="password" placeholder="VerySecurePassword;PleaseDon'tHackMe!LOL">
|
||||||
|
|
||||||
<input type="submit" value="Log in!">
|
<input type="submit" value="Log in!">
|
||||||
|
|
||||||
|
<p>Logging in will store an API token in a cookie. 😉</p>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
15
views/pages/manager.njk
Normal file
15
views/pages/manager.njk
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends "templates/base.njk" %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<title>{{ user.name }}@qam</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{# <img class="logo" src="https://qwik.space/assets/images/logo.svg" alt="qwik's logo"> #}
|
||||||
|
<header>Welcome {{ user.name }}! :D</header>
|
||||||
|
<h1>This is your account manager!</h1>
|
||||||
|
<p>
|
||||||
|
Currently no features are implemented, but we want to implement at least password changing.
|
||||||
|
It would also be nice to have proper account deletion. (For now, if you want to delete your account contact an admin!)
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user