mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 09:07:09 +00:00
Refactor user authentication code to use database
This commit is contained in:
@@ -2,16 +2,23 @@ const dns = require('dns');
|
||||
const { Netmask } = require('netmask');
|
||||
const cfg = require('../../../lib/config');
|
||||
const jwt = require('../../../lib/jwt');
|
||||
const user = require('../../../lib/db/user');
|
||||
|
||||
async function authorisedIP (req, res) {
|
||||
const validIPs = cfg._("global.users.login.ip") || {};
|
||||
for (const key in validIPs) {
|
||||
const block = new Netmask(key);
|
||||
const validIPs = await user.ip({active: true}); // Get all active IP logins
|
||||
validIPs.forEach( i => i.$block = new Netmask(i.ip) );
|
||||
validIPs.sort( (a, b) => b.$block.bitmask - a.$block.netmask ); // More specific IPs have precedence
|
||||
for (const ip of validIPs) {
|
||||
const block = ip.$block;
|
||||
if (block.contains(req.ip)) {
|
||||
const payload = Object.assign({
|
||||
const payload = {
|
||||
...ip,
|
||||
ip: req.ip,
|
||||
autologin: true
|
||||
}, validIPs[key]);
|
||||
};
|
||||
delete payload.$block;
|
||||
delete payload.hash;
|
||||
delete payload.active;
|
||||
jwt.issue(payload, req, res);
|
||||
return true;
|
||||
}
|
||||
@@ -20,7 +27,7 @@ async function authorisedIP (req, res) {
|
||||
}
|
||||
|
||||
async function authorisedHost (req, res) {
|
||||
const validHosts = cfg._("global.users.login.host") || {};
|
||||
const validHosts = await user.host({active: true}); // Get all active host logins
|
||||
for (const key in validHosts) {
|
||||
try {
|
||||
const ip = await dns.promises.resolve(key);
|
||||
@@ -42,6 +49,17 @@ async function authorisedHost (req, res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Check client TLS certificates
|
||||
// Probably will do this via Nginx with
|
||||
// ssl_verify_client optional;
|
||||
// and then putting either of the
|
||||
// $ssl_client_s_dn or $ssl_client_escaped_cert
|
||||
// variables into an HTTP header for Node
|
||||
// to check (naturally, it must be ensured
|
||||
// that a user cannot just insert the header
|
||||
// in a request).
|
||||
|
||||
|
||||
async function auth (req, res, next) {
|
||||
|
||||
if (res.headersSent) {
|
||||
|
||||
60
lib/www/server/lib/db/user/index.js
Normal file
60
lib/www/server/lib/db/user/index.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const { pool } = require('../connection');
|
||||
|
||||
const IPUser = Symbol("IPUser");
|
||||
const HostUser = Symbol("HostUser");
|
||||
const NamedUser = Symbol("NamedUser");
|
||||
|
||||
async function userOfType(type, opts = {}) {
|
||||
opts = {active: true, ...opts};
|
||||
|
||||
let propertyName;
|
||||
switch (type) {
|
||||
case IPUser:
|
||||
propertyName = "ip";
|
||||
break;
|
||||
case HostUser:
|
||||
propertyName = "host";
|
||||
break;
|
||||
case NamedUser:
|
||||
propertyName = "hash";
|
||||
break;
|
||||
}
|
||||
|
||||
if (propertyName) {
|
||||
|
||||
const text = `
|
||||
SELECT *
|
||||
FROM keystore
|
||||
WHERE type = 'user' AND data ? $1
|
||||
`;
|
||||
|
||||
const res = await pool.query(text, [ propertyName ]);
|
||||
|
||||
const users = res.rows.map( row => ({
|
||||
...row.data,
|
||||
id: row.key,
|
||||
hash: undefined
|
||||
}) ).filter( row => opts.active == null || opts.active === row.active );
|
||||
|
||||
return users;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async function ip (opts = {}) {
|
||||
return await userOfType(IPUser, opts);
|
||||
}
|
||||
|
||||
async function host (opts = {}) {
|
||||
return await userOfType(HostUser, opts);
|
||||
}
|
||||
|
||||
async function named (opts = {}) {
|
||||
return await userOfType(NamedUser, opts);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ip,
|
||||
host,
|
||||
named
|
||||
}
|
||||
Reference in New Issue
Block a user