refactor: messaging

This commit is contained in:
eneller
2026-06-26 12:49:17 +02:00
parent 37fdc28e1f
commit ceab2dee0a
5 changed files with 25 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
export class LoginRequest{ export class LoginRequest{
constructor( constructor(
username: string, public username: string,
password: string public password: string
){} ){}
} }
export class LoginResponse{ export class LoginResponse{

View File

@@ -0,0 +1,5 @@
export class GenericMessage{
constructor(
public message: string
){}
}

View File

@@ -9,6 +9,5 @@ export class SendRequest{
export class SendResponse{ export class SendResponse{
constructor( constructor(
public balance: number, public balance: number,
public message: string
){} ){}
} }

View File

@@ -2,34 +2,33 @@ import express from 'express';
import { logger } from '../util/logging'; import { logger } from '../util/logging';
import User from '../model/user'; import User from '../model/user';
import { getJWT, requireAuth } from '../util/auth'; import { getJWT, requireAuth } from '../util/auth';
import { LoginRequest } from '@message/Login'; import { LoginRequest } from '../messages/Login';
import { SendRequest, SendResponse } from '@message/Send'; import { GenericMessage as Msg } from '../messages/Message';
const router = express.Router(); const router = express.Router();
router.post('/login', async (req, res) => { router.post('/login', async (req, res) => {
try { try {
const { username, password } = req.body; const data : LoginRequest = req.body;
const user = await User.findOne({where: { userID: username}}); const user = await User.findOne({where: { userID: data.username}});
if (!user) return res.status(401).json({ message: 'Invalid credentials' }); if (!user) return res.status(401).json(new Msg('Invalid credentials'));
const isMatch = (password == user.password); const isMatch = (data.password == user.password);
//TODO hash passwords //TODO hash passwords
//const isMatch = await bcrypt.compare(password, user.passwordHash); //const isMatch = await bcrypt.compare(password, user.passwordHash);
if (!isMatch) return res.status(401).json({ message: 'Invalid credentials' }); if (!isMatch) return res.status(401).json(new Msg('Invalid credentials'));
// successfully authenticated // successfully authenticated
let jwt = await getJWT(user); let jwt = await getJWT(user);
res.cookie('jwt', jwt, { res.cookie('jwt', jwt, {
httpOnly: true, // Prevent XSS httpOnly: true, // Prevent XSS
secure: process.env.NODE_ENV === 'production',// HTTPS only secure: process.env.NODE_ENV === 'production', // HTTPS only
sameSite: 'strict', // CSRF protection sameSite: 'strict', // CSRF protection
maxAge: 86400000, // 1 day maxAge: 86400000, // 1 day
}); });
res.json({ message: 'Logged in successfully' }); res.json(new Msg('Logged in successfully'));
}catch (err) { }catch (err) {
logger.error('Failed to authenticate:', err); logger.error('Failed to authenticate:', err);
res.status(500).json({ message: 'Failed to authenticate' }); res.status(500).json(new Msg('Failed to authenticate'));
} }
}); });

View File

@@ -5,6 +5,7 @@ import User from '../model/user';
import { db } from '../util/db'; import { db } from '../util/db';
import Transaction from '../model/transaction'; import Transaction from '../model/transaction';
import { SendRequest, SendResponse} from '../messages/Send'; import { SendRequest, SendResponse} from '../messages/Send';
import { GenericMessage as Err} from '../messages/Message';
const router = express.Router(); const router = express.Router();
@@ -15,15 +16,14 @@ router.post('/', requireAuth, async (req, res) => {
const data : SendRequest = req.body; const data : SendRequest = req.body;
const recipient = await User.findOne({where: {userID: data.recipientID}}) const recipient = await User.findOne({where: {userID: data.recipientID}})
if ( Number(data.amount) <= 0) { if ( Number(data.amount) <= 0) {
// TODO return SendResponse here and everywhere else in this file return res.status(400).json(new Err('Invalid transfer amount'));
return res.status(400).json({ error: 'Invalid transfer amount' });
} }
if (!recipient) { if (!recipient) {
return res.status(404).json({ error: 'Recipient not found' }); return res.status(404).json(new Err('Recipient not found' ));
} }
if (Number(sender.balance) < Number(data.amount)){ if (Number(sender.balance) < Number(data.amount)){
logger.error(`Insufficient balance: ${sender.balance} < ${data.amount}`) logger.debug(`Insufficient balance: ${sender.balance} < ${data.amount}`)
return res.status(402).json({error: 'Insufficient balance'}) return res.status(402).json(new Err('Insufficient balance'))
} }
await db.transaction(async (t) =>{ await db.transaction(async (t) =>{
@@ -36,10 +36,10 @@ router.post('/', requireAuth, async (req, res) => {
reference: data.reference reference: data.reference
}); });
}) })
return res.status(200).json({balance: sender.balance, amount: data.amount}); return res.status(200).json(new SendResponse(sender.balance))
} catch (err) { } catch (err) {
logger.error('Failed to commit transaction:', err); logger.error('Failed to commit transaction:', err);
return res.status(500).json({ error: 'Failed to commit transaction' }); return res.status(500).json(new Err('Failed to commit transaction' ));
} }
}); });