Skip to content

Commit aa9a4b7

Browse files
committed
fix security flaws
* update code * initial mechanism for user tracking initial mechanism for user tracking fix security flaws
1 parent 75aec9c commit aa9a4b7

23 files changed

+626
-17
lines changed

.env.dev

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
PORT=5000
22
NODE_ENV="development"
33
JWT_SECRET="thisismysupersecrettokenjustkidding"
4-
DATABASE_URL"mongodb://mongo:27017/donut-development"
4+
DATABASE_URL="mongodb://mongo:27017/donut-development"
55
SENDGRID_API_KEY='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'
66
SOCKET_PORT=8810
7-
clientbaseurl = "http://localhost:3000/"
7+
clientbaseurl = "http://localhost:3000"
8+
SOCKET_PORT=8810
9+
REDIS_HOST="redis"
10+
REDIS_PORT=6379
11+
REDIS_PASSWORD="auth"
12+
REDIS_DB=0
13+
REDIS_ACTIVITY_DB=1

app.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ const socket = require('socket.io')
88
const multer = require('multer')
99
const bodyParser = require('body-parser')
1010
const cors = require('cors')
11+
const helmet = require('helmet')
12+
const hpp = require('hpp')
1113
var winston = require('./config/winston')
14+
const rateLimiter = require('./app/middleware/rateLimiter')
15+
const sanitizer = require('./app/middleware/sanitise')
1216
const fileConstants = require('./config/fileHandlingConstants')
1317

1418
const indexRouter = require('./app/routes/index')
@@ -23,13 +27,15 @@ const projectRouter = require('./app/routes/project')
2327
const notificationRouter = require('./app/routes/notification')
2428
const proposalRouter = require('./app/routes/proposal')
2529
const analyticsRouter = require('./app/routes/analytics')
30+
const activityRouter = require('./app/routes/activity')
2631

2732
const app = express()
2833
const server = require('http').Server(app)
2934

3035
app.use(cors())
3136

3237
app.use(bodyParser.json({ limit: '200mb' }))
38+
app.use(cookieParser())
3339
app.use(bodyParser.urlencoded(fileConstants.fileParameters))
3440

3541
const memoryStorage = multer.memoryStorage()
@@ -71,6 +77,23 @@ app.use((req, res, next) => {
7177
next()
7278
})
7379

80+
// TO PREVENT DOS ATTACK AND RATE LIMITER
81+
app.use(rateLimiter.customRateLimiter)
82+
83+
// TO PREVENT XSS ATTACK
84+
app.use(sanitizer.cleanBody)
85+
app.use(helmet())
86+
87+
// TO PREVENT CLICK JACKING
88+
app.use((req, res, next) => {
89+
res.append('X-Frame-Options', 'Deny')
90+
res.set('Content-Security-Policy', "frame-ancestors 'none';")
91+
next()
92+
})
93+
94+
// TO PREVENT THE QUERY PARAMETER POLLUTION
95+
app.use(hpp())
96+
7497
app.use('/notification', notificationRouter)
7598
app.use('/', indexRouter)
7699
app.use('/auth', authRouter)
@@ -83,6 +106,7 @@ app.use('/comment', commentRouter)
83106
app.use('/project', projectRouter)
84107
app.use('/proposal', proposalRouter)
85108
app.use('/analytics', analyticsRouter)
109+
app.use('/activity', activityRouter)
86110

87111
// catch 404 and forward to error handler
88112
app.use(function (req, res, next) {
@@ -102,7 +126,7 @@ app.use(function (err, req, res, next) {
102126

103127
// render the error page
104128
res.status(err.status || 500)
105-
res.render('error')
129+
res.render('error', { csrfToken: req.csrfToken() })
106130

107131
// Socket event error handler (On max event)
108132
req.io.on('error', function (err) {

app/controllers/activity.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const User = require('../models/User')
2+
const Activity = require('../models/Activity')
3+
4+
const HttpStatus = require('http-status-codes')
5+
module.exports = {
6+
7+
getActivity: async (req, res, next) => {
8+
// userID whose activity will be fetched by admin
9+
const { id } = req.params
10+
11+
try {
12+
// Check if user exists
13+
const user = await User.findById(req.user._id)
14+
if (!user) {
15+
return res.status(HttpStatus.BAD_REQUEST).json({ msg: 'No such user exists!' })
16+
}
17+
18+
// check if not admin
19+
if (user.isAdmin !== true) {
20+
return res.status(HttpStatus.BAD_REQUEST).json({ msg: 'You don\'t have permission!' })
21+
}
22+
23+
const data = await Activity.findOne({ userId: id })
24+
return res.status(HttpStatus.OK).json({ activity: data.activity })
25+
} catch (error) {
26+
if (process.env.NODE_ENV !== 'production') {
27+
console.log(error.name, '-', error.message)
28+
}
29+
return res.status(HttpStatus.BAD_REQUEST).json({ error: error.message })
30+
}
31+
}
32+
}

app/controllers/auth.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const User = require('../models/User')
22
const HttpStatus = require('http-status-codes')
3+
const activityHelper = require('../utils/activity-helper')
4+
35
module.exports = {
46
authenticateUser: async (req, res, next) => {
5-
const email = req.body.email
6-
const password = req.body.password
7+
const email = escape(req.body.email)
8+
const password = escape(req.body.password)
79
try {
810
const user = await User.findByCredentials(email, password)
911
const token = await user.generateAuthToken()
@@ -13,9 +15,11 @@ module.exports = {
1315
}
1416
},
1517
logout: (req, res, next) => {
18+
activityHelper.addActivityToDb(req, res)
1619
res.status(HttpStatus.OK).json({ success: 'ok' })
1720
},
1821
logoutAll: (req, res, next) => {
22+
activityHelper.addActivityToDb(req, res)
1923
res.status(HttpStatus.OK).json({ success: 'ok' })
2024
}
2125
}

app/controllers/comment.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const HttpStatus = require('http-status-codes')
33
const CommentModel = require('../models/Comment')
44
const permission = require('../utils/permission')
55
const helper = require('../utils/paginate')
6+
const activityTracker = require('../utils/activity-helper')
7+
const collectionTypes = require('../utils/collections')
68

79
module.exports = {
810
// CREATE COMMENT (ISSUE IN CREATE COMMENT )
@@ -14,7 +16,8 @@ module.exports = {
1416
comment.userId = userId
1517
comment.postId = id // added postId
1618
await comment.save()
17-
res.status(HttpStatus.CREATED).json({ comment: comment })
19+
activityTracker.addToRedis(req, res, next, collectionTypes.COMMENT, comment._id)
20+
return res.status(HttpStatus.CREATED).json({ comment: comment })
1821
} catch (error) {
1922
HANDLER.handleError(res, error)
2023
}
@@ -63,7 +66,8 @@ module.exports = {
6366
comment[update] = req.body[update]
6467
})
6568
await comment.save()
66-
res.status(HttpStatus.OK).json({ comment: comment })
69+
activityTracker.addToRedis(req, res, next, collectionTypes.COMMENT, comment._id)
70+
return res.status(HttpStatus.OK).json({ comment: comment })
6771
} catch (error) {
6872
HANDLER.handleError(res, error)
6973
}

app/controllers/event.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const permission = require('../utils/permission')
55
const helper = require('../utils/paginate')
66
const notificationHelper = require('../utils/notif-helper')
77
const settingsHelper = require('../utils/settingHelpers')
8+
const activityTracker = require('../utils/activity-helper')
9+
const collectionTypes = require('../utils/collections')
10+
811
const notification = {
912
heading: '',
1013
content: '',
@@ -22,6 +25,7 @@ module.exports = {
2225
notification.content = `${event.eventName} is added!`
2326
notification.tag = 'New!'
2427
notificationHelper.addToNotificationForAll(req, res, notification, next)
28+
activityTracker.addToRedis(req, res, next, collectionTypes.EVENT, event._id)
2529
res.status(HttpStatus.CREATED).json({ event: event })
2630
} catch (error) {
2731
res.status(HttpStatus.BAD_REQUEST).json({ error: error })
@@ -53,6 +57,7 @@ module.exports = {
5357
notification.content = `${event.eventName} is updated!`
5458
notification.tag = 'Update'
5559
notificationHelper.addToNotificationForAll(req, res, notification, next)
60+
activityTracker.addToRedis(req, res, next, collectionTypes.EVENT, event._id)
5661
res.status(HttpStatus.OK).json({ event: event })
5762
} catch (error) {
5863
HANDLER.handleError(res, error)
@@ -163,7 +168,11 @@ module.exports = {
163168
notification.content = `Event ${deleteEvent.eventName} is deleted!`
164169
notification.tag = 'Deleted'
165170
notificationHelper.addToNotificationForAll(req, res, notification, next)
166-
return res.status(HttpStatus.OK).json({ deleteEvent: deleteEvent, message: 'Deleted the event' })
171+
activityTracker.addToRedis(req, res, next, collectionTypes.EVENT, deleteEvent._id)
172+
return res.status(HttpStatus.OK).json({
173+
deleteEvent: deleteEvent,
174+
message: 'Deleted the event'
175+
})
167176
}
168177
return res.status(HttpStatus.BAD_REQUEST).json({ msg: 'Not permitted!' })
169178
} catch (error) {

app/controllers/organization.js

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ const Event = require('../models/Event')
1010
const permission = require('../utils/permission')
1111
const TAGS = require('../utils/notificationTags')
1212
const Organisation = require('../models/Organisation')
13+
const activityTracker = require('../utils/activity-helper')
14+
const collectionTypes = require('../utils/collections')
15+
1316
const notification = {
1417
heading: '',
1518
content: '',
@@ -29,6 +32,7 @@ module.exports = {
2932
notification.content = `${orgData.name} is created!`
3033
notification.tag = TAGS.NEW
3134
notificationHelper.addToNotificationForAll(req, res, notification, next)
35+
activityTracker.addToRedis(req, res, next, collectionTypes.ORG, org._id)
3236
return res.status(HttpStatus.CREATED).json({ orgData })
3337
} catch (error) {
3438
HANDLER.handleError(res, error)
@@ -71,6 +75,7 @@ module.exports = {
7175
helper.mapToDb(req, org)
7276
}
7377
await org.save()
78+
activityTracker.addToRedis(req, res, next, collectionTypes.ORG, org._id)
7479
return res.status(HttpStatus.OK).json({ organization: org })
7580
} catch (error) {
7681
HANDLER.handleError(res, error)
@@ -127,6 +132,7 @@ module.exports = {
127132
notification.content = `${org.name} is deleted!`
128133
notification.tag = TAGS.DELETE
129134
notificationHelper.addToNotificationForAll(req, res, notification, next)
135+
activityTracker.addToRedis(req, res, next, collectionTypes.ORG, org._id)
130136
return res.status(HttpStatus.OK).json({ organization: org })
131137
} catch (error) {
132138
HANDLER.handleError(res, error)
@@ -228,6 +234,7 @@ module.exports = {
228234
.status(HttpStatus.BAD_REQUEST)
229235
.json({ msg: 'Invalid update' })
230236
}
237+
activityTracker.addToRedis(req, res, next, collectionTypes.ORG, organization._id)
231238
// else not admin
232239
return res
233240
.status(HttpStatus.BAD_REQUEST)

app/controllers/post.js

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const imgUploadHelper = require('../utils/uploader')
66
const permission = require('../utils/permission')
77
const helper = require('../utils/paginate')
88
const settingsHelper = require('../utils/settingHelpers')
9+
const activityTracker = require('../utils/activity-helper')
10+
const collectionTypes = require('../utils/collections')
911

1012
module.exports = {
1113
// CREATE POST
@@ -19,6 +21,7 @@ module.exports = {
1921
try {
2022
await post.save()
2123
// req.io.emit('new post created', { data: post.content })
24+
activityTracker.addToRedis(req, res, next, collectionTypes.POST, post._id)
2225
return res.status(HttpStatus.CREATED).json({ post })
2326
} catch (error) {
2427
HANDLER.handleError(res, error)

app/controllers/project.js

+4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ const HttpStatus = require('http-status-codes')
44
const helper = require('../utils/paginate')
55
const permission = require('../utils/permission')
66
const settingsHelper = require('../utils/settingHelpers')
7+
const activityTracker = require('../utils/activity-helper')
8+
const collectionTypes = require('../utils/collections')
79

810
module.exports = {
911
createProject: async (req, res, next) => {
1012
try {
1113
const project = await new Project(req.body)
1214
project.createdBy = req.user._id
1315
await project.save()
16+
activityTracker.addToRedis(req, res, next, collectionTypes.PROJECT, project._id)
1417
return res.status(HttpStatus.CREATED).json({ project })
1518
} catch (error) {
1619
HANDLER.handleError(res, error)
@@ -98,6 +101,7 @@ module.exports = {
98101
await Project.findByIdAndRemove(id)
99102
return res.status(HttpStatus.OK).json({ msg: 'Project deleted!' })
100103
}
104+
activityTracker.addToRedis(req, res, next, collectionTypes.PROJECT, project._id)
101105
return res.status(HttpStatus.BAD_REQUEST).json({ msg: 'Not permitted!' })
102106
} catch (error) {
103107
HANDLER.handleError(res, error)

0 commit comments

Comments
 (0)