Reputation: 3174
I'm using filepicker.io with a Meteor application and am working on security for my application. Filepicker provides support for creating and signing policies but with the server side of Meteor I feel like creating expiring policies for each user requesting a file is overkill.
What I would like to do is provide the user an indirect link to a file. The server intercepts this request with a server side route (iron-router), the server then checks if the user has permissions for the file via a Files collection with metadata about said file.
As I have it now, If the user has access I would provide them a file link with the signature and policy as parameters to that link. Instead I would prefer to only return the image or file asset and no link at all. E.g. the server side would access the file or image over a link that only the server knows, but the server would stream that file or image to the client without sharing the actual link to the file.
The intended code looks something like the following, where I don't really know what to do at the end:
@route "file",
path: "/file/:_id"
where: "server"
action: ->
if @request.cookies.meteor_login_token
user = Meteor.users.findOne(
{"services.resume.loginTokens.hashedToken":
Accounts._hashLoginToken(@request.cookies.meteor_login_token)}
)
if user
# the files collection has metadata about each file
# these files are uploaded through filepicker
# this include file.url which is the actual link
file = share.Files.findOne(
{_id: @params._id, accessibleBy: user._id}
)
if not file
@response.writeHead(403)
@response.end()
return
else
#return the file/image from filepicker,
#e.g. file.url without actually returning the url
@response.end()
In my research it seems like a stream might be the solution, but its not obvious to me how I would do that within a node.js Fiber as is the case on the a Meteor server-side.
Upvotes: 2
Views: 170
Reputation: 4081
You could use webapp
to create an HTTP endpoint, then use node's http
to get the image from Filepicker
and then pipe it to the response:
var http = Npm.require('http'),
url = Npm.require('url');
WebApp.connectHandlers.use('/file', function(req, res, next) {
// URL format: /file/:_id
var id = url.parse(req.url, true).path.substr(1); // this is _id
// replace the following parameters with filepicker stuff
http.request({
host: 'www.devbattles.com',
path: '/en/images/upload/1427871558.png'
}, function(result){
// here we just pipe the http result
res.writeHead(200, {
'Content-Type': result.headers['content-type']
});
result.pipe(res);
}).end();
});
If you were to copy this code (for example) to /server/filepickerPipe.js
and then opened up http://server.com/file/test
, you'd see this picture.
There's the possibility of serving all this over DDP. I'm also going to have to start serving files from a 3rd party, so I might look into it and create a package to just do it over DDP and not mess with HTTP endpoints. However, this is a solution for now.
Upvotes: 1