diff options
Diffstat (limited to 'server.js')
-rw-r--r-- | server.js | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/server.js b/server.js new file mode 100644 index 0000000..e347e37 --- /dev/null +++ b/server.js @@ -0,0 +1,205 @@ +const express = require('express'); +const bodyParser = require('body-parser'); +const cors = require('cors') +const crypto = require('crypto'); +const pkg = require('./package.json'); + +// App constants +const port = process.env.PORT || 5000; +const apiPrefix = '/api'; + +// Store data in-memory, not suited for production use! +const db = { + test: { + user: 'test', + currency: '$', + description: `Test account`, + balance: 75, + transactions: [ + { id: '1', date: '2020-10-01', object: 'Pocket money', amount: 50 }, + { id: '2', date: '2020-10-03', object: 'Book', amount: -10 }, + { id: '3', date: '2020-10-04', object: 'Sandwich', amount: -5 } + ], + } +}; + +// Create the Express app & setup middlewares +const app = express(); +app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.json()); +app.use(cors({ + origin: /http:\/\/(127(\.\d){3}|localhost)/, + optionsSuccessStatus: 200 +})); +app.options('*', cors()); + +// *************************************************************************** + +// Configure routes +const router = express.Router(); + +// Get server infos +router.get('/', (req, res) => { + return res.send(`${pkg.description} v${pkg.version}`); +}); + +// ---------------------------------------------- + +// Create an account +router.post('/accounts', (req, res) => { + // Check mandatory request parameters + if (!req.body.user || !req.body.currency) { + return res.status(400).json({ error: 'Missing parameters' }); + } + + // Check if account already exists + if (db[req.body.user]) { + return res.status(409).json({ error: 'User already exists' }); + } + + // Convert balance to number if needed + let balance = req.body.balance; + if (balance && typeof balance !== 'number') { + balance = parseFloat(balance); + if (isNaN(balance)) { + return res.status(400).json({ error: 'Balance must be a number' }); + } + } + + // Create account + const account = { + user: req.body.user, + currency: req.body.currency, + description: req.body.description || `${req.body.user}'s budget`, + balance: balance || 0, + transactions: [], + }; + db[req.body.user] = account; + + return res.status(201).json(account); +}); + +// ---------------------------------------------- + +// Get all data for the specified account +router.get('/accounts/:user', (req, res) => { + const account = db[req.params.user]; + // Check if account exists + if (!account) { + return res.status(404).json({ error: 'User does not exist' }); + } + + return res.json(account); +}); + +// ---------------------------------------------- + +// Remove specified account +router.delete('/accounts/:user', (req, res) => { + const account = db[req.params.user]; + + // Check if account exists + if (!account) { + return res.status(404).json({ error: 'User does not exist' }); + } + + // Removed account + delete db[req.params.user]; + + res.sendStatus(204); +}); + +// ---------------------------------------------- + +// Add a transaction to a specific account +router.post('/accounts/:user/transactions', (req, res) => { + const account = db[req.params.user]; + + // Check if account exists + if (!account) { + return res.status(404).json({ error: 'User does not exist' }); + } + + // Check mandatory requests parameters + if (!req.body.date || !req.body.object || !req.body.amount) { + return res.status(400).json({ error: 'Missing parameters' }); + } + + // Convert amount to number if needed + let amount = req.body.amount; + if (amount && typeof amount !== 'number') { + amount = parseFloat(amount); + } + + // Check that amount is a valid number + if (amount && isNaN(amount)) { + return res.status(400).json({ error: 'Amount must be a number' }); + } + + // Generates an ID for the transaction + const id = crypto + .createHash('md5') + .update(req.body.date + req.body.object + req.body.amount) + .digest('hex'); + + // Check that transaction does not already exist + if (account.transactions.some((transaction) => transaction.id === id)) { + return res.status(409).json({ error: 'Transaction already exists' }); + } + + // Add transaction + const transaction = { + id, + date: req.body.date, + object: req.body.object, + amount, + }; + account.transactions.push(transaction); + + // Update balance + account.balance += transaction.amount; + + return res.status(201).json(transaction); +}); + +// ---------------------------------------------- + +// Remove specified transaction from account +router.delete('/accounts/:user/transactions/:id', (req, res) => { + const account = db[req.params.user]; + + // Check if account exists + if (!account) { + return res.status(404).json({ error: 'User does not exist' }); + } + + const transactionIndex = account.transactions.findIndex( + (transaction) => transaction.id === req.params.id + ); + + // Check if transaction exists + if (transactionIndex === -1) { + return res.status(404).json({ error: 'Transaction does not exist' }); + } + + // Remove transaction + account.transactions.splice(transactionIndex, 1); + + res.sendStatus(204); +}); + +// *************************************************************************** + +// set custom header +app.use((req, res, next) => { + res.append('tsec', 'fxrAJnJLVzgp9PFMJKmmRLVHVscfyw3Mjdr'); + next(); +}) + +// Add 'api` prefix to all routes +app.use(apiPrefix, router); + +// Start the server +app.listen(port, () => { + console.log(`Server listening on port ${port}`); +}); |