Fix tests, run against ci
Some checks failed
ci / build-image (push) Successful in 50s
ci / test-image (push) Failing after 3s

This commit is contained in:
Jonathan Cremin 2025-06-13 09:32:37 +01:00
parent b352b65a0c
commit 677dfe25af
6 changed files with 175 additions and 113 deletions

View file

@ -1,29 +1,29 @@
import crypto from 'crypto';
import { join } from 'path';
import passwords from 'passwords';
import uuid from 'node-uuid';
import views from 'co-views';
import debugname from 'debug';
import sendgrid from '@sendgrid/mail';
import models from '../../models';
import crypto from "crypto";
import { join } from "path";
import passwords from "passwords";
import uuid from "node-uuid";
import views from "co-views";
import debugname from "debug";
import sendgrid from "@sendgrid/mail";
import models from "../../models";
const render = views(join(__dirname, '..', 'views'), { default: 'ejs' });
const debug = debugname('hostr-web:auth');
const render = views(join(__dirname, "..", "views"), { default: "ejs" });
const debug = debugname("hostr-web:auth");
sendgrid.setApiKey(process.env.SENDGRID_KEY);
const from = process.env.EMAIL_FROM;
const fromname = process.env.EMAIL_NAME;
export async function authenticate(email, password) {
const remoteIp = this.headers['x-forwarded-for'] || this.ip;
const remoteIp = this.headers["x-forwarded-for"] || this.ip;
if (!password || password.length < 6) {
debug('No password, or password too short');
return new Error('Invalid login details');
debug("No password, or password too short");
return new Error("Invalid login details");
}
const count = await models.login.count({
where: {
ip: remoteIp.split(',')[0],
ip: remoteIp.split(",")[0],
successful: false,
createdAt: {
$gt: Math.ceil(Date.now()) - 600000,
@ -32,8 +32,8 @@ export async function authenticate(email, password) {
});
if (count > 25) {
debug('Throttling brute force');
return new Error('Invalid login details');
debug("Throttling brute force");
return new Error("Invalid login details");
}
const user = await models.user.findOne({
where: {
@ -43,30 +43,29 @@ export async function authenticate(email, password) {
});
const login = await models.login.create({
ip: remoteIp.split(',')[0],
ip: remoteIp.split(",")[0],
successful: false,
});
if (user && user.password) {
login.userId = user.id;
if (await passwords.verify(password, user.password)) {
debug('Password verified');
debug("Password verified");
login.successful = true;
await login.save();
return user;
}
debug('Password invalid');
debug("Password invalid");
}
await login.save();
return false;
}
export async function setupSession(user) {
debug('Setting up session');
debug("Setting up session");
const token = uuid.v4();
debug(user)
await this.redis.set(token, user.id, 'EX', 604800);
await this.redis.set(token, user.id, "EX", 604800);
const sessionUser = {
id: user.id,
@ -76,27 +75,26 @@ export async function setupSession(user) {
joined: user.createdAt,
plan: user.plan,
uploadsToday: await models.file.count({ userId: user.id }),
md5: crypto.createHash('md5').update(user.email).digest('hex'),
md5: crypto.createHash("md5").update(user.email).digest("hex"),
token,
};
if (sessionUser.plan === 'Pro') {
if (sessionUser.plan === "Pro") {
sessionUser.maxFileSize = 524288000;
sessionUser.dailyUploadAllowance = 'unlimited';
sessionUser.dailyUploadAllowance = "unlimited";
}
this.session.user = sessionUser;
if (this.request.body.remember && this.request.body.remember === 'on') {
if (this.request.body.remember && this.request.body.remember === "on") {
const remember = await models.remember.create({
id: uuid(),
userId: user.id,
});
this.cookies.set('r', remember.id, { maxAge: 1209600000, httpOnly: true });
this.cookies.set("r", remember.id, { maxAge: 1209600000, httpOnly: true });
}
debug('Session set up');
debug("Session set up");
}
export async function signup(email, password, ip) {
const existingUser = await models.user.findOne({
where: {
@ -105,26 +103,29 @@ export async function signup(email, password, ip) {
},
});
if (existingUser) {
debug('Email already in use.');
throw new Error('Email already in use.');
debug("Email already in use.");
throw new Error("Email already in use.");
}
const cryptedPassword = await passwords.crypt(password);
const user = await models.user.create({
email,
password: cryptedPassword,
ip,
plan: 'Free',
activation: {
id: uuid(),
const user = await models.user.create(
{
email,
password: cryptedPassword,
ip,
plan: "Free",
activation: {
id: uuid(),
email,
},
},
}, {
include: [models.activation],
});
{
include: [models.activation],
},
);
await user.save();
const html = await render('email/inlined/activate', {
const html = await render("email/inlined/activate", {
activationUrl: `${process.env.WEB_BASE_URL}/activate/${user.activation.id}`,
});
const text = `Thanks for signing up to Hostr!
@ -136,18 +137,15 @@ ${process.env.WEB_BASE_URL}/activate/${user.activation.id}
`;
sendgrid.send({
to: user.email,
subject: 'Welcome to Hostr',
subject: "Welcome to Hostr",
from,
fromname,
html,
text,
categories: [
'activate',
],
categories: ["activate"],
});
}
export async function sendResetToken(email) {
const user = await models.user.findOne({
where: {
@ -159,7 +157,7 @@ export async function sendResetToken(email) {
id: uuid.v4(),
userId: user.id,
});
const html = await render('email/inlined/forgot', {
const html = await render("email/inlined/forgot", {
forgotUrl: `${process.env.WEB_BASE_URL}/forgot/${reset.id}`,
});
const text = `It seems you've forgotten your password :(
@ -167,38 +165,32 @@ Visit ${process.env.WEB_BASE_URL}/forgot/${reset.id} to set a new one.
`;
sendgrid.send({
to: user.email,
from: 'jonathan@hostr.co',
fromname: 'Jonathan from Hostr',
subject: 'Hostr Password Reset',
from: "jonathan@hostr.co",
fromname: "Jonathan from Hostr",
subject: "Hostr Password Reset",
html,
text,
categories: [
'password-reset',
],
categories: ["password-reset"],
});
} else {
throw new Error('There was an error looking up your email address.');
throw new Error("There was an error looking up your email address.");
}
}
export async function fromToken(token) {
const userId = await this.redis.get(token);
return models.user.findByPk(userId);
}
export async function fromCookie(rememberId) {
const userId = await models.remember.findByPk(rememberId);
return models.user.findByPk(userId);
}
export async function validateResetToken(resetId) {
return models.reset.findByPk(resetId);
}
export async function updatePassword(userId, password) {
const cryptedPassword = await passwords.crypt(password);
const user = await models.user.findByPk(userId);
@ -206,7 +198,6 @@ export async function updatePassword(userId, password) {
await user.save();
}
export async function activateUser(code) {
const activation = await models.activation.findOne({
where: {