Skip to content

Commit

Permalink
use hash function to give permission to Attachments
Browse files Browse the repository at this point in the history
  • Loading branch information
paolini committed Sep 17, 2023
1 parent c5e65e7 commit 9a42781
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 16 deletions.
1 change: 1 addition & 0 deletions api/.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ SERVER_URL="http://localhost:3000"
CORS_ORIGIN="http://localhost:3000" # comma separated URLS

SESSION_SECRET="" # set a string or leave empty for a random string
PERMISSION_SECRET=""

MONGO_DB="caps"

Expand Down
16 changes: 9 additions & 7 deletions api/controllers/AttachmentController.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path')
const multer = require('multer')
const assert = require('assert')

const { ValidationError, ForbiddenError, NotFoundError } = require('../exceptions/ApiException')
const { ValidationError, ForbiddenError, NotFoundError, BadRequestError } = require('../exceptions/ApiException')

const ModelController = require('./ModelController');
const Attachment = require('../models/Attachment');
Expand Down Expand Up @@ -32,15 +32,17 @@ const attachmentHandler = multer({
}
}).any()





const AttachmentController = {

view: async req => {
const { id } = req.params
const user = req.user
const obj = await ModelController.view(Attachment, id)

if (!user.admin && obj.uploader_id !== user._id) throw new ForbiddenError()

const { signedId } = req.params
const id = ModelController.idFromSignedIdIfValid(signedId)
if (!id) throw new ForbiddenError()
const obj = await ModelController.view(Attachment, id)
return obj
},

Expand Down
21 changes: 17 additions & 4 deletions api/controllers/CommentController.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const ModelController = require('./ModelController');
const Comment = require('../models/Comment');
const assert = require('assert')
const mongoose = require('mongoose')

const fields = {
"object_id": {
Expand Down Expand Up @@ -38,7 +39,9 @@ const CommentController = {
]

const pipeline = ModelController.queryFieldsToPipeline(query, fields)
const [ res ] = await Comment.aggregate([
const db = mongoose.connection.db
const comments = db.collection('comments')
const [res] = await comments.aggregate([
// lookup sui proposals
{$lookup: {
from: "proposals",
Expand All @@ -51,11 +54,21 @@ const CommentController = {
path: "$object_id",
preserveNullAndEmptyArrays: true
}},
{$lookup: {
from: "attachments",
localField: "attachments",
foreignField: "_id",
as: "attachmentsData",
}},
...restrict,
...pipeline,
])
await Comment.populate(res.items, { path: 'attachments creator_id' })

]).toArray()
console.log(`res: ${JSON.stringify(res)}`)
res.items.forEach(comment => {
comment.attachmentsData.forEach(attachment => {
attachment.signedId = ModelController.signedId(attachment._id.toString())
})
})
return res
},

Expand Down
20 changes: 19 additions & 1 deletion api/controllers/ModelController.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

const { default: mongoose } = require("mongoose");
const { BadRequestError, ValidationError, NotImplementedError, NotFoundError } = require("../exceptions/ApiException");
const crypto = require('crypto')

const PERMISSION_SECRET = process.env.PERMISSION_SECRET || crypto.randomUUID()

function queryFieldsToPipeline(query={}, fields={}) {
let $match = {};
Expand Down Expand Up @@ -162,7 +165,22 @@ const ModelController = {
} catch(err) {
throw new NotFoundError()
}
}
},

signedId: (id) => {
const hash = crypto.createHash('sha256')
hash.update(id)
hash.update(PERMISSION_SECRET)
return `${id}-${hash.digest('hex')}`
},

idFromSignedIdIfValid: (signedId) => {
console.log(`isSignedIdValid ${signedId}`)
const [id, signature] = signedId.split("-")
console.log(`id ${id} signature ${signature}`)
console.log(`signedId ${ModelController.signedId(id)}`)
return signedId === ModelController.signedId(id) ? id : null
},
}

module.exports = ModelController;
2 changes: 1 addition & 1 deletion api/controllers/ProposalsController.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const ProposalsController = {
view: async req => {
const { id } = req.params
const user = req?.user || null
return await ModelController.view(Proposal, id, user)
return await ModelController.view(Proposal, id)
},

post: async req => {
Expand Down
4 changes: 2 additions & 2 deletions api/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ router.post('/users', require_admin, response_envelope(Users.post))
router.patch('/users/:id', require_admin, response_envelope(Users.patch))


router.get('/attachments/:id/content', require_user, Attachments.viewContent)
router.get('/attachments/:id', require_user, response_envelope(Attachments.view))
router.get('/attachments/:signedId/content', require_user, Attachments.viewContent)
router.get('/attachments/:signedId', require_user, response_envelope(Attachments.view))
router.post('/attachments', require_user, Attachments.postMiddleware, response_envelope(Attachments.post))

router.get('/comments', require_user, response_envelope(Comments.index))
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function CommentCard({ comment, userUpdater }) {
<div className='mb-2 rounded border border-left-info p-1 d-flex justify-content-between align-items-end'>
<div>
<div>{comment.content}</div>
{comment.attachments.map(attachment => <div key={attachment._id}><a href={`/api/v0/attachments/${attachment._id}/content`}>{attachment.filename}</a></div>)}
{comment.attachmentsData.map(attachment => <div key={attachment._id}><a href={`/api/v0/attachments/${attachment.signedId}/content`}>{attachment.filename}</a></div>)}
<div><strong>{comment.creator_id.name}</strong> - {(new Date(comment.createdAt)).toLocaleString()}</div>
</div>
<div className='btn btn-sm btn-danger' onClick={deleteComment}>Elimina</div>
Expand Down

0 comments on commit 9a42781

Please sign in to comment.