diff --git a/api/.env b/api/.env index 90dbc198..5f4bf1ce 100644 --- a/api/.env +++ b/api/.env @@ -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" diff --git a/api/controllers/AttachmentController.js b/api/controllers/AttachmentController.js index 92e48241..bb49008c 100644 --- a/api/controllers/AttachmentController.js +++ b/api/controllers/AttachmentController.js @@ -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'); @@ -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 }, diff --git a/api/controllers/CommentController.js b/api/controllers/CommentController.js index c82ab189..f5c2156f 100644 --- a/api/controllers/CommentController.js +++ b/api/controllers/CommentController.js @@ -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": { @@ -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", @@ -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 }, diff --git a/api/controllers/ModelController.js b/api/controllers/ModelController.js index 599f277e..3331520e 100644 --- a/api/controllers/ModelController.js +++ b/api/controllers/ModelController.js @@ -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 = {}; @@ -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; diff --git a/api/controllers/ProposalsController.js b/api/controllers/ProposalsController.js index ba05a672..d3afdef9 100644 --- a/api/controllers/ProposalsController.js +++ b/api/controllers/ProposalsController.js @@ -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 => { diff --git a/api/router.js b/api/router.js index ad8096de..f9b53712 100644 --- a/api/router.js +++ b/api/router.js @@ -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)) diff --git a/frontend/src/components/Comments.js b/frontend/src/components/Comments.js index e79aaf44..413e988c 100644 --- a/frontend/src/components/Comments.js +++ b/frontend/src/components/Comments.js @@ -44,7 +44,7 @@ function CommentCard({ comment, userUpdater }) {
{comment.content}
- {comment.attachments.map(attachment =>
{attachment.filename}
)} + {comment.attachmentsData.map(attachment =>
{attachment.filename}
)}
{comment.creator_id.name} - {(new Date(comment.createdAt)).toLocaleString()}
Elimina