summaryrefslogtreecommitdiff
path: root/app/auth.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/auth.js')
-rw-r--r--app/auth.js41
1 files changed, 17 insertions, 24 deletions
diff --git a/app/auth.js b/app/auth.js
index cd771ca..7859a24 100644
--- a/app/auth.js
+++ b/app/auth.js
@@ -1,23 +1,18 @@
-"use strict";
+import {readFile as rf, writeFile as wf} from "node:fs/promises";
+import {readFileSync, rename} from "node:fs";
+import {randomBytes} from "node:crypto";
+import argon2 from "argon2";
-const fs = require("fs");
-const util = require("util");
-const crypto = require("crypto");
-const argon2 = require("argon2");
-const {sj, parseCookies, res204, err400, err401, err500} = require("./utils");
+import {sj, parseCookies, res204, err400, err401, err500} from "./utils.js";
-const rf = util.promisify(fs.readFile);
-const wf = util.promisify(fs.writeFile);
-const randHex = len => crypto.randomBytes(len).toString("hex");
-
-module.exports = config => {
+import {DOMAIN, SECURE, auth as authConfig} from "./config.js";
const {
TOKEN_RENEW_AGE, TOKEN_MAX_AGE, TOKEN_LENGTH, SESSION_ID_LENGTH,
USERNAME_MAX_LENGTH, PASSWORD_MIN_LENGTH, PASSWORD_MAX_LENGTH,
- RATE_LIMIT_MAX_LEVEL, RATE_LIMIT_MAX_WAITING,
- fingerprintIP} = config.auth;
-const {DOMAIN, SECURE} = config;
-const exports = {};
+ RATE_LIMIT_MAX_LEVEL, RATE_LIMIT_MAX_WAITING, fingerprintIP,
+} = authConfig;
+
+const randHex = len => randomBytes(len).toString("hex");
// Run once immediately, then every interval until not called
function debounce(fn, interval=100) {
@@ -42,10 +37,10 @@ function debounce(fn, interval=100) {
function loadJSONSync(path) {
const obj = {};
try {
- Object.assign(obj, JSON.parse(fs.readFileSync(path)));
+ Object.assign(obj, JSON.parse(readFileSync(path)));
} catch(e) {
console.log(Date.now()+` Error loading ${path}, creating fallback empty set`);
- fs.rename(path, path+".bad."+Date.now(), err => {});
+ rename(path, path+".bad."+Date.now(), err => {});
}
return obj;
}
@@ -64,9 +59,9 @@ const userIDsFile = "private/userIDs.json";
const userNames = loadJSONSync(userIDsFile), userIDs = {};
for (const [uid, username] of Object.entries(userNames)) userIDs[username.toLowerCase()] = uid;
const writeUIDs = debounce(() => wf(userIDsFile, JSON.stringify(userNames)));
-const getUID = exports.getUID = username =>
+export const getUID = username =>
userIDs.hasOwnProperty(username.toLowerCase()) && userIDs[username.toLowerCase()];
-const getUsername = exports.getUsername = uid =>
+export const getUsername = uid =>
userNames.hasOwnProperty(uid) && userNames[uid];
const createUID = username => { let uid;
do { uid = randHex(5); } while (getUsername(uid));
@@ -385,7 +380,7 @@ const rateLimit = fn => (req, res, ...rest) => {
}, rateLimitTime(rl.level));
}
-function authed(fn) { return rateLimit((req, res, ...rest) => {
+export function authed(fn) { return rateLimit((req, res, ...rest) => {
const token = parseCookies(req)?.token;
if (!token) return err401(res);
@@ -421,9 +416,9 @@ function authed(fn) { return rateLimit((req, res, ...rest) => {
req.uid = uid;
req.sessionID = tokenData.sessionID;
return fn(req, res, ...rest);
-}); } exports.authed = authed;
+}); }
-exports.attach = (app) => { // TODO make endpoints RESTier?
+export const attach = (app) => { // TODO make endpoints RESTier?
app.jpost("/login", rateLimit(login)); // {username, password[, keepSession]} -> {success[, msg][, mustChangePassword]}
app.post("/logout", rateLimit(logout));
app.jpost("/change-password", rateLimit(changePassword)); // {password, newPassword[, username[, keepSession]]} -> {success[, msg]}
@@ -444,5 +439,3 @@ exports.attach = (app) => { // TODO make endpoints RESTier?
// - https://github.com/zxcvbn-ts/zxcvbn
// - non-login-event user notification system (warnings, must change password...)
// - encrypt `private/` on disk using TPM?
-
-return exports; };