/* eslint-disable no-return-assign, no-unused-vars, */ // TODO: This file was created by bulk-decaffeinate. // Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ const should = require('chai').should() const SandboxedModule = require('sandboxed-module') const assert = require('assert') const path = require('path') const sinon = require('sinon') const modulePath = path.join( __dirname, '../../../app/js/StaticServerForbidSymlinks' ) const { expect } = require('chai') describe('StaticServerForbidSymlinks', function() { beforeEach(function() { this.settings = { path: { compilesDir: '/compiles/here' } } this.fs = {} this.ForbidSymlinks = SandboxedModule.require(modulePath, { requires: { 'settings-sharelatex': this.settings, 'logger-sharelatex': { log() {}, warn() {}, error() {} }, fs: this.fs } }) this.dummyStatic = (rootDir, options) => (req, res, next) => // console.log "dummyStatic serving file", rootDir, "called with", req.url // serve it next() this.StaticServerForbidSymlinks = this.ForbidSymlinks( this.dummyStatic, this.settings.path.compilesDir ) this.req = { params: { project_id: '12345' } } this.res = {} return (this.req.url = '/12345/output.pdf') }) describe('sending a normal file through', function() { beforeEach(function() { return (this.fs.realpath = sinon .stub() .callsArgWith( 1, null, `${this.settings.path.compilesDir}/${this.req.params.project_id}/output.pdf` )) }) return it('should call next', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(200) return done() } return this.StaticServerForbidSymlinks(this.req, this.res, done) }) }) describe('with a missing file', function() { beforeEach(function() { return (this.fs.realpath = sinon .stub() .callsArgWith( 1, { code: 'ENOENT' }, `${this.settings.path.compilesDir}/${this.req.params.project_id}/unknown.pdf` )) }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a symlink file', function() { beforeEach(function() { return (this.fs.realpath = sinon .stub() .callsArgWith(1, null, `/etc/${this.req.params.project_id}/output.pdf`)) }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a relative file', function() { beforeEach(function() { return (this.req.url = '/12345/../67890/output.pdf') }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a unnormalized file containing .', function() { beforeEach(function() { return (this.req.url = '/12345/foo/./output.pdf') }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a file containing an empty path', function() { beforeEach(function() { return (this.req.url = '/12345/foo//output.pdf') }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a non-project file', function() { beforeEach(function() { return (this.req.url = '/.foo/output.pdf') }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a file outside the compiledir', function() { beforeEach(function() { return (this.req.url = '/../bar/output.pdf') }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a file with no leading /', function() { beforeEach(function() { return (this.req.url = './../bar/output.pdf') }) return it('should send a 404', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(404) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) describe('with a github style path', function() { beforeEach(function() { this.req.url = '/henryoswald-latex_example/output/output.log' return (this.fs.realpath = sinon .stub() .callsArgWith( 1, null, `${this.settings.path.compilesDir}/henryoswald-latex_example/output/output.log` )) }) return it('should call next', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(200) return done() } return this.StaticServerForbidSymlinks(this.req, this.res, done) }) }) return describe('with an error from fs.realpath', function() { beforeEach(function() { return (this.fs.realpath = sinon.stub().callsArgWith(1, 'error')) }) return it('should send a 500', function(done) { this.res.sendStatus = function(resCode) { resCode.should.equal(500) return done() } return this.StaticServerForbidSymlinks(this.req, this.res) }) }) })