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 dotenv from 'dotenv'
|
||||
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('/static', express.static('static'))
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.0.1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^12.0.3",
|
||||
"express": "^4.17.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"nunjucks": "^3.2.3",
|
||||
"pg": "^8.7.1"
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import bcrypt from 'bcrypt'
|
||||
import crypto from 'crypto'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import { Router } from 'express'
|
||||
import { glauth } from '../libs/database.js'
|
||||
import execawait from '../libs/execawait.js'
|
||||
|
||||
export const SECRET = process.env.TK_SECRET ?? crypto.generateKeySync("aes", { length: 128 }).export().toString()
|
||||
const AUTH = Router()
|
||||
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.
|
||||
* @returns {string} hex of hash
|
||||
*/
|
||||
|
@ -25,11 +27,9 @@ function hash2hex(hash) {
|
|||
AUTH.post('/register', async (req, res) => {
|
||||
const { captcha, password, username } = req.body
|
||||
|
||||
// Was input sent?
|
||||
if (!username || !password || !captcha)
|
||||
return(res.send(`Not entered:${username ? '' : ' username,'}${password ? '' : ' password,'}${captcha ? '' : ' captcha'}`))
|
||||
|
||||
// is captcha valid
|
||||
if (!valid[captcha])
|
||||
return(res.send("Invalid captcha!"))
|
||||
|
||||
|
@ -38,10 +38,10 @@ AUTH.post('/register', async (req, res) => {
|
|||
if (captchaAge > 600)
|
||||
return(res.send("Invalid captcha!"))
|
||||
|
||||
// expire the captcha
|
||||
// Expire the 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)))
|
||||
return(res.send("Username does not match the requirements"))
|
||||
|
||||
|
@ -59,7 +59,6 @@ AUTH.post('/register', async (req, res) => {
|
|||
).catch(
|
||||
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!"))
|
||||
|
||||
bcrypt.compare(password, user.qam_pass).then(
|
||||
match => {
|
||||
async match => {
|
||||
if (!match)
|
||||
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 AUTH from './auth.js'
|
||||
import AUTH, { SECRET } from './auth.js'
|
||||
|
||||
const ROUTES = Router()
|
||||
|
||||
ROUTES.get('/', (_, res) => res.render("pages/landing.njk"))
|
||||
ROUTES.get('/login', (_, res) => res.render("pages/login.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)
|
||||
|
||||
export default ROUTES
|
|
@ -65,7 +65,6 @@ h6 {
|
|||
|
||||
p {
|
||||
margin: .5em 0 .25em 0;
|
||||
text-align: justify;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,5 +14,7 @@
|
|||
<input type="password" id="password" name="password" placeholder="VerySecurePassword;PleaseDon'tHackMe!LOL">
|
||||
|
||||
<input type="submit" value="Log in!">
|
||||
|
||||
<p>Logging in will store an API token in a cookie. 😉</p>
|
||||
</form>
|
||||
{% 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