fix: send api

This commit is contained in:
eneller
2026-03-18 10:27:26 +01:00
parent 823d696d86
commit 7f3326c4a5
5 changed files with 38 additions and 15 deletions

View File

@@ -0,0 +1,14 @@
export class SendRequest{
constructor(
public recipientID: string,
public amount: number,
public reference: string
){}
}
export class SendResponse{
constructor(
public balance: number,
public message: string
){}
}

View File

@@ -5,6 +5,9 @@ import User from './user';
export default class Transaction extends Model{ export default class Transaction extends Model{
@Column @Column
declare amount: number; declare amount: number;
@Column
declare reference: string;
@Column @Column
@ForeignKey(()=> User) @ForeignKey(()=> User)

View File

@@ -1,41 +1,45 @@
import express from 'express'; import express from 'express';
import { logger } from '../util/logging'; import { logger } from '../util/logging';
import { requireAuth } from '../util/auth'; import { requireAuth } from '../util/auth';
import User from '../model/user'; 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';
const router = express.Router(); const router = express.Router();
router.get('/:recipientID', requireAuth, async (req, res) => { router.post('/', requireAuth, async (req, res) => {
try { try {
let sender = res.locals.user as User; const sender = res.locals.user as User;
let amount = Number(req.query.amount); const data : SendRequest = req.body;
let recipient = await User.findOne({where: {userID: req.params.recipientID}}) const recipient = await User.findOne({where: {userID: data.recipientID}})
if ( amount <= 0) { if ( Number(data.amount) <= 0) {
// TODO return SendResponse here and everywhere else in this file
return res.status(400).json({ error: '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({ error: 'Recipient not found' });
} }
if (sender.balance < amount){ if (Number(sender.balance) < Number(data.amount)){
res.status(400).json({error: 'Insufficient balance'}) logger.error(`Insufficient balance: ${sender.balance} < ${data.amount}`)
return res.status(402).json({error: 'Insufficient balance'})
} }
await db.transaction(async (t) =>{ await db.transaction(async (t) =>{
await sender.decrement({balance: amount}); await sender.decrement({balance: data.amount});
await recipient.increment({balance: amount}); await recipient.increment({balance: data.amount});
await Transaction.create({ await Transaction.create({
amount: amount, amount: data.amount,
senderID: sender.userID, senderID: sender.userID,
receiverID: recipient.userID receiverID: recipient.userID,
reference: data.reference
}); });
}) })
res.status(200).json({balance: sender.balance, amount: amount}); return res.status(200).json({balance: sender.balance, amount: data.amount});
} catch (err) { } catch (err) {
logger.error('Failed to commit transaction:', err); logger.error('Failed to commit transaction:', err);
res.status(500).json({ error: 'Failed to commit transaction' }); return res.status(500).json({ error: 'Failed to commit transaction' });
} }
}); });

View File

@@ -30,6 +30,7 @@ async function requireAuth(req: Request, res: Response, next: NextFunction) {
if (!user) { if (!user) {
return res.status(401).json({ error: 'Unauthorized: User not found' }); return res.status(401).json({ error: 'Unauthorized: User not found' });
} }
//TODO extend req instead of using res.locals
res.locals.user = user; res.locals.user = user;
next(); next();
} catch (err) { } catch (err) {

View File

@@ -10,7 +10,8 @@
"module": "es2022", "module": "es2022",
"lib": ["es2022", "dom"], "lib": ["es2022", "dom"],
"paths": { "paths": {
"@model/*": ["server/src/model/*"] "@model/*": ["server/src/model/*"],
"@message/*": ["server/src/messages/*"],
} }
}, },
"exclude": ["node_modules"] "exclude": ["node_modules"]