From 9068afa4669a1cda574a9c89029f88e0f7470e27 Mon Sep 17 00:00:00 2001 From: Haris Razis Date: Sat, 9 Jan 2021 19:22:52 +0200 Subject: [PATCH] Fix database query built from user-controlled sources Add celebrate middleware to PUT/POST/DELETE --- server/index.js | 3 +- server/package-lock.json | 153 ++++++++++++++++++++++++++---- server/package.json | 1 + server/routes/athletes.js | 86 ++++++++++------- server/routes/auth.js | 27 +++--- server/routes/data.js | 26 ++--- server/routes/user.js | 55 ++++++----- server/schemas/joi.js | 37 ++++++++ web/src/store/modules/athletes.ts | 3 +- web/src/store/modules/user.ts | 18 ++-- 10 files changed, 299 insertions(+), 110 deletions(-) create mode 100644 server/schemas/joi.js diff --git a/server/index.js b/server/index.js index 80a9747..3405e6d 100644 --- a/server/index.js +++ b/server/index.js @@ -27,8 +27,9 @@ app.use(rateLimit({ max: 100 })); +app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ - extended: true + extended: false })); app.use( diff --git a/server/package-lock.json b/server/package-lock.json index 1f1c941..01f9986 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -11,6 +11,7 @@ "@influxdata/influxdb-client": "^1.9.0", "bcrypt": "^5.0.0", "body-parser": "^1.19.0", + "celebrate": "^13.0.4", "chalk": "^4.1.0", "cookie-session": "^1.4.0", "cors": "^2.8.5", @@ -28,11 +29,42 @@ "socket.io-redis": "^6.0.1" } }, + "node_modules/@hapi/hoek": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.1.tgz", + "integrity": "sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw==" + }, + "node_modules/@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@influxdata/influxdb-client": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.9.0.tgz", "integrity": "sha512-wJ+qfGukxMxpDE5d2XHiOspKheWTb1PdPOd2eD3MVuh8hjr6fqyJ3zuacTp/WVubeyppPhM4vYcDjkKCg1OEhA==" }, + "node_modules/@sideway/address": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.0.tgz", + "integrity": "sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -444,6 +476,16 @@ "node": ">=6" } }, + "node_modules/celebrate": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/celebrate/-/celebrate-13.0.4.tgz", + "integrity": "sha512-gUtAjEtFyY9PvuuQJq1uyuF46gLetVZzyUKXBDBqqvgzCjTSfwXP8L+WcGt1NrLQvUxXdlzhFolW2Bt9DDEV+g==", + "dependencies": { + "escape-html": "1.0.3", + "joi": "17.x.x", + "lodash": "4.17.x" + } + }, "node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1314,6 +1356,18 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "node_modules/joi": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.3.0.tgz", + "integrity": "sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -1354,6 +1408,11 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -1533,9 +1592,9 @@ } }, "node_modules/mongoose": { - "version": "5.11.10", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.10.tgz", - "integrity": "sha512-daE2L6VW7WNywv7tL2KUkBViWvODbzr50Of1kJpIbzW3w3N5/TYcgSmhCsEDWfYGQXbun2rdd7+sOdsEC8zQSQ==", + "version": "5.11.11", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.11.tgz", + "integrity": "sha512-JgKKAosJf6medPOZi2LmO7sMz7Sg00mgjyPAKari3alzL+R/n8D+zKK29iGtJpNNtv9IKy14H37CWuiaZ7016w==", "dependencies": { "@types/mongodb": "^3.5.27", "bson": "^1.1.4", @@ -1627,9 +1686,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", + "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", "dependencies": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -1689,9 +1748,9 @@ } }, "node_modules/nodemon": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz", - "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz", + "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==", "hasInstallScript": true, "dependencies": { "chokidar": "^3.2.2", @@ -2851,11 +2910,42 @@ } }, "dependencies": { + "@hapi/hoek": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.1.tgz", + "integrity": "sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw==" + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@influxdata/influxdb-client": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.9.0.tgz", "integrity": "sha512-wJ+qfGukxMxpDE5d2XHiOspKheWTb1PdPOd2eD3MVuh8hjr6fqyJ3zuacTp/WVubeyppPhM4vYcDjkKCg1OEhA==" }, + "@sideway/address": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.0.tgz", + "integrity": "sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -3179,6 +3269,16 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, + "celebrate": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/celebrate/-/celebrate-13.0.4.tgz", + "integrity": "sha512-gUtAjEtFyY9PvuuQJq1uyuF46gLetVZzyUKXBDBqqvgzCjTSfwXP8L+WcGt1NrLQvUxXdlzhFolW2Bt9DDEV+g==", + "requires": { + "escape-html": "1.0.3", + "joi": "17.x.x", + "lodash": "4.17.x" + } + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -3859,6 +3959,18 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "joi": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.3.0.tgz", + "integrity": "sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -3893,6 +4005,11 @@ "package-json": "^6.3.0" } }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -4009,9 +4126,9 @@ } }, "mongoose": { - "version": "5.11.10", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.10.tgz", - "integrity": "sha512-daE2L6VW7WNywv7tL2KUkBViWvODbzr50Of1kJpIbzW3w3N5/TYcgSmhCsEDWfYGQXbun2rdd7+sOdsEC8zQSQ==", + "version": "5.11.11", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.11.tgz", + "integrity": "sha512-JgKKAosJf6medPOZi2LmO7sMz7Sg00mgjyPAKari3alzL+R/n8D+zKK29iGtJpNNtv9IKy14H37CWuiaZ7016w==", "requires": { "@types/mongodb": "^3.5.27", "bson": "^1.1.4", @@ -4078,9 +4195,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", + "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -4130,9 +4247,9 @@ } }, "nodemon": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz", - "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz", + "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==", "requires": { "chokidar": "^3.2.2", "debug": "^3.2.6", diff --git a/server/package.json b/server/package.json index 8fe15c5..d13450e 100644 --- a/server/package.json +++ b/server/package.json @@ -13,6 +13,7 @@ "@influxdata/influxdb-client": "^1.9.0", "bcrypt": "^5.0.0", "body-parser": "^1.19.0", + "celebrate": "^13.0.4", "chalk": "^4.1.0", "cookie-session": "^1.4.0", "cors": "^2.8.5", diff --git a/server/routes/athletes.js b/server/routes/athletes.js index 96e01a7..6a1bb35 100644 --- a/server/routes/athletes.js +++ b/server/routes/athletes.js @@ -1,41 +1,61 @@ const express = require('express') const router = express.Router(); const mongoose = require('mongoose'); -const {requireAuth} = require('../middlewares/middleware'); +const {celebrate} = require('celebrate'); +const {requireAuth} = require('../middlewares/middleware'); +const {athleteUpdateSchema, guid} = require('../schemas/joi'); const Athlete = mongoose.model('Athlete'); -router.get('/api/athletes', requireAuth, async (req, res) => { - const athletes = await Athlete.find(); - res.send(athletes); -}); - -router.get('/api/athletes/:id', requireAuth, async (req, res) => { - const athlete = await Athlete.findById(req.params.id); - res.send(athlete) -}); - -router.get('/api/athletes/:id/edit', requireAuth, async (req, res) => { - const athlete = await Athlete.findById(req.params.id) - res.send(athlete) -}); - -router.put('/api/athletes/:id', requireAuth, async (req, res) => { - const {name, _trainer} = req.body - const updateAthlete = {name, _trainer} - - if (name || _trainer) - await Athlete.findByIdAndUpdate(req.params.id, updateAthlete, {}, (err, athlete) => { - if (err) - return res.status(400).json({errors: 'Something went wrong!0'}); - - res.send(athlete) - }) - -}); - -router.delete('/api/athlete/:id', requireAuth, async (req, res) => { - await Athlete.findByIdAndDelete(req.params.id) -}); +router.get('/api/athletes', + requireAuth, + async (req, res) => { + const athletes = await Athlete.find(); + res.send(athletes); + }); + +router.get('/api/athletes/:id', + requireAuth, + celebrate(guid), + async (req, res) => { + const athlete = await Athlete.findById(req.params.id); + res.send(athlete) + }); + +router.get('/api/athletes/:id/edit', + requireAuth, + celebrate(guid), + async (req, res) => { + const athlete = await Athlete.findById(req.params.id) + res.send(athlete) + } +) +; + +router.put('/api/athletes/:id', + requireAuth, + celebrate(athleteUpdateSchema, guid), + async (req, res) => { + const {name, _trainer} = req.body + const updateAthlete = {name, _trainer} + + if (name || _trainer) + await Athlete.findByIdAndUpdate(req.params.id, updateAthlete, {}, (err, athlete) => { + if (err) + return res.status(400).json({errors: 'Something went wrong!'}); + + res.send(athlete) + }) + + }); + +router.delete('/api/athlete/:id', + requireAuth, + celebrate(guid), + async (req, res) => { + await Athlete.findByIdAndDelete(req.params.id) + } +) +; module.exports = router; diff --git a/server/routes/auth.js b/server/routes/auth.js index 8194f13..649900e 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -1,8 +1,12 @@ const express = require('express'); const passport = require('passport') const router = express.Router(); +const {celebrate} = require('celebrate'); + +const {userAuthSchema} = require('../schemas/joi') router.post('/auth/login', + celebrate(userAuthSchema), (req, res, next) => { passport.authenticate('local', {}, (err, user, info) => { if (err) @@ -14,19 +18,20 @@ router.post('/auth/login', return res.status(200).json({user: req.user}); }); })(req, res, next); - } -); + }); -router.post('/auth/logout', (req, res) => { - req.logout(); - res.redirect('/'); -}); +router.post('/auth/logout', + (req, res) => { + req.logout(); + res.redirect('/'); + }); -router.get('/auth/current_user', (req, res) => { - if (!req.user) - return res.status(404).json({errors: 'No current user!'}) +router.get('/auth/current_user', + (req, res) => { + if (!req.user) + return res.status(404).json({errors: 'No current user!'}) - res.send(req.user); -}); + res.send(req.user); + }); module.exports = router; diff --git a/server/routes/data.js b/server/routes/data.js index 76ffed5..5fafa03 100644 --- a/server/routes/data.js +++ b/server/routes/data.js @@ -7,21 +7,25 @@ const Athlete = mongoose.model('Athlete'); const {influx_bucket} = require('../config/keys') const {iQuery} = require('../actions/influx_actions') -router.get('/api/data', requireAuth, async (req, res) => { - const query = `from(bucket: "${influx_bucket}") |> range(start: -1h)`; - const data = await iQuery(query); +router.get('/api/data', + requireAuth, + async (req, res) => { + const query = `from(bucket: "${influx_bucket}") |> range(start: -1h)`; + const data = await iQuery(query); - res.send(data); -}); + res.send(data); + }); -router.get('/api/data/:id', requireAuth, async (req, res) => { - const athlete = await Athlete.findById(req.params.id); +router.get('/api/data/:id', + requireAuth, + async (req, res) => { + const athlete = await Athlete.findById(req.params.id); - const query = `from(bucket: "${influx_bucket}") |> range(start: -1h) |> filter(fn: (r) => r.client == "${athlete.id}")`; - const data = await iQuery(query); + const query = `from(bucket: "${influx_bucket}") |> range(start: -1h) |> filter(fn: (r) => r.client == "${athlete.id}")`; + const data = await iQuery(query); - res.send(data) -}); + res.send(data) + }); module.exports = router; diff --git a/server/routes/user.js b/server/routes/user.js index 1375f40..32eded9 100644 --- a/server/routes/user.js +++ b/server/routes/user.js @@ -2,32 +2,37 @@ const express = require('express') const router = express.Router(); const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); -const {requireAuth} = require('../middlewares/middleware'); +const {celebrate} = require('celebrate'); +const {requireAuth} = require('../middlewares/middleware'); const User = mongoose.model('User') - -router.put('/api/user/:id', requireAuth, async (req, res) => { - const {username, email, password, newPassword} = req.body - - if (password && newPassword) { - bcrypt.compare(password, req.user.password, async (err, isMatch) => { - if (err) - return res.status(400).json({errors: 'Current password is wrong!'}); - - if (isMatch) { - const user = {username, email, newPassword} - await User.findByIdAndUpdate(req.params.id, user) - - res.send(req.user); - } - }); - } else if (username || email) { - const user = {username, email} - await User.findByIdAndUpdate(req.params.id, user) - - res.send(req.user); - } - -}); +const {userUpdateSchema, guid} = require('../schemas/joi'); + +router.put('/api/user/:id', + requireAuth, + celebrate(userUpdateSchema, guid), + async (req, res) => { + const {username, email, password, newPassword} = req.body + + if (password && newPassword) { + bcrypt.compare(password, req.user.password, async (err, isMatch) => { + if (err) + return res.status(400).json({errors: 'Current password is wrong!'}); + + if (isMatch) { + const user = {username, email, newPassword} + await User.findByIdAndUpdate(req.params.id, user) + + res.send(req.user); + } + }); + } else if (username || email) { + const user = {username, email} + await User.findByIdAndUpdate(req.params.id, user) + + res.send(req.user); + } + + }); module.exports = router; diff --git a/server/schemas/joi.js b/server/schemas/joi.js new file mode 100644 index 0000000..ee9eac2 --- /dev/null +++ b/server/schemas/joi.js @@ -0,0 +1,37 @@ +const {Joi} = require('celebrate'); + +const guid = { + params:{ + userId: Joi.string().guid().required() + } +} + +const userAuthSchema = { + body: { + username: Joi.string().required(), + password: Joi.string().required(), + } +}; + +const userUpdateSchema = { + body: { + _id: Joi.string().required(), + username: Joi.string().required(), + email: Joi.any(), + password: Joi.string().allow(''), + newPassword: Joi.string().allow(''), + } +}; + +const athleteUpdateSchema = { + body: { + _id: Joi.string().required(), + id: Joi.string().required(), + socketID: Joi.string().required(), + name: Joi.string().required(), + __v: Joi.number().integer(), + _trainer: Joi.string().allow(''), + } +} + +module.exports = {guid, userAuthSchema, userUpdateSchema, athleteUpdateSchema} \ No newline at end of file diff --git a/web/src/store/modules/athletes.ts b/web/src/store/modules/athletes.ts index 1b57d26..5fb5aa3 100644 --- a/web/src/store/modules/athletes.ts +++ b/web/src/store/modules/athletes.ts @@ -1,6 +1,5 @@ import {Action, Module, Mutation, VuexModule} from 'vuex-module-decorators' import axios, {AxiosResponse} from "axios"; -import qs from 'qs'; import {UserInterface} from "@/store/modules/user"; @@ -74,7 +73,7 @@ export default class Athletes extends VuexModule { axios({ method: 'PUT', url: `/api/athletes/${athlete._id}`, - data: qs.stringify({...athlete}) + data: {...athlete} }) .then((resp: AxiosResponse) => { this.context.commit('save_athlete', resp.data) diff --git a/web/src/store/modules/user.ts b/web/src/store/modules/user.ts index 1c71106..1de72e1 100644 --- a/web/src/store/modules/user.ts +++ b/web/src/store/modules/user.ts @@ -95,17 +95,15 @@ export default class User extends VuexModule { }) }) } - + @Action - private updateUser(user: UserInterface) { + private specificUser(id: string) { return new Promise((resolve, reject) => { axios({ - method: 'PUT', - url: `/api/user/${user._id}`, - data: qs.stringify({...user}) + method: 'GET', + url: `/api/user/${id}` }) .then((resp: AxiosResponse) => { - this.context.commit('auth_success', resp.data); resolve(resp) }) .catch((err: Error) => { @@ -115,13 +113,15 @@ export default class User extends VuexModule { } @Action - private specificUser(id: string) { + private updateUser(user: UserInterface) { return new Promise((resolve, reject) => { axios({ - method: 'GET', - url: `/api/user/${id}` + method: 'PUT', + url: `/api/user/${user._id}`, + data: {...user} }) .then((resp: AxiosResponse) => { + this.context.commit('auth_success', resp.data); resolve(resp) }) .catch((err: Error) => {