StaticServerForbidSymlinksTests.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /* eslint-disable
  2. no-return-assign,
  3. no-unused-vars,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  11. */
  12. const should = require('chai').should()
  13. const SandboxedModule = require('sandboxed-module')
  14. const assert = require('assert')
  15. const path = require('path')
  16. const sinon = require('sinon')
  17. const modulePath = path.join(
  18. __dirname,
  19. '../../../app/js/StaticServerForbidSymlinks'
  20. )
  21. const { expect } = require('chai')
  22. describe('StaticServerForbidSymlinks', function () {
  23. beforeEach(function () {
  24. this.settings = {
  25. path: {
  26. compilesDir: '/compiles/here'
  27. }
  28. }
  29. this.fs = {}
  30. this.ForbidSymlinks = SandboxedModule.require(modulePath, {
  31. requires: {
  32. 'settings-sharelatex': this.settings,
  33. 'logger-sharelatex': {
  34. log() {},
  35. warn() {},
  36. error() {}
  37. },
  38. fs: this.fs
  39. }
  40. })
  41. this.dummyStatic = (rootDir, options) => (req, res, next) =>
  42. // console.log "dummyStatic serving file", rootDir, "called with", req.url
  43. // serve it
  44. next()
  45. this.StaticServerForbidSymlinks = this.ForbidSymlinks(
  46. this.dummyStatic,
  47. this.settings.path.compilesDir
  48. )
  49. this.req = {
  50. params: {
  51. project_id: '12345'
  52. }
  53. }
  54. this.res = {}
  55. return (this.req.url = '/12345/output.pdf')
  56. })
  57. describe('sending a normal file through', function () {
  58. beforeEach(function () {
  59. return (this.fs.realpath = sinon
  60. .stub()
  61. .callsArgWith(
  62. 1,
  63. null,
  64. `${this.settings.path.compilesDir}/${this.req.params.project_id}/output.pdf`
  65. ))
  66. })
  67. return it('should call next', function (done) {
  68. this.res.sendStatus = function (resCode) {
  69. resCode.should.equal(200)
  70. return done()
  71. }
  72. return this.StaticServerForbidSymlinks(this.req, this.res, done)
  73. })
  74. })
  75. describe('with a missing file', function () {
  76. beforeEach(function () {
  77. return (this.fs.realpath = sinon
  78. .stub()
  79. .callsArgWith(
  80. 1,
  81. { code: 'ENOENT' },
  82. `${this.settings.path.compilesDir}/${this.req.params.project_id}/unknown.pdf`
  83. ))
  84. })
  85. return it('should send a 404', function (done) {
  86. this.res.sendStatus = function (resCode) {
  87. resCode.should.equal(404)
  88. return done()
  89. }
  90. return this.StaticServerForbidSymlinks(this.req, this.res)
  91. })
  92. })
  93. describe('with a symlink file', function () {
  94. beforeEach(function () {
  95. return (this.fs.realpath = sinon
  96. .stub()
  97. .callsArgWith(1, null, `/etc/${this.req.params.project_id}/output.pdf`))
  98. })
  99. return it('should send a 404', function (done) {
  100. this.res.sendStatus = function (resCode) {
  101. resCode.should.equal(404)
  102. return done()
  103. }
  104. return this.StaticServerForbidSymlinks(this.req, this.res)
  105. })
  106. })
  107. describe('with a relative file', function () {
  108. beforeEach(function () {
  109. return (this.req.url = '/12345/../67890/output.pdf')
  110. })
  111. return it('should send a 404', function (done) {
  112. this.res.sendStatus = function (resCode) {
  113. resCode.should.equal(404)
  114. return done()
  115. }
  116. return this.StaticServerForbidSymlinks(this.req, this.res)
  117. })
  118. })
  119. describe('with a unnormalized file containing .', function () {
  120. beforeEach(function () {
  121. return (this.req.url = '/12345/foo/./output.pdf')
  122. })
  123. return it('should send a 404', function (done) {
  124. this.res.sendStatus = function (resCode) {
  125. resCode.should.equal(404)
  126. return done()
  127. }
  128. return this.StaticServerForbidSymlinks(this.req, this.res)
  129. })
  130. })
  131. describe('with a file containing an empty path', function () {
  132. beforeEach(function () {
  133. return (this.req.url = '/12345/foo//output.pdf')
  134. })
  135. return it('should send a 404', function (done) {
  136. this.res.sendStatus = function (resCode) {
  137. resCode.should.equal(404)
  138. return done()
  139. }
  140. return this.StaticServerForbidSymlinks(this.req, this.res)
  141. })
  142. })
  143. describe('with a non-project file', function () {
  144. beforeEach(function () {
  145. return (this.req.url = '/.foo/output.pdf')
  146. })
  147. return it('should send a 404', function (done) {
  148. this.res.sendStatus = function (resCode) {
  149. resCode.should.equal(404)
  150. return done()
  151. }
  152. return this.StaticServerForbidSymlinks(this.req, this.res)
  153. })
  154. })
  155. describe('with a file outside the compiledir', function () {
  156. beforeEach(function () {
  157. return (this.req.url = '/../bar/output.pdf')
  158. })
  159. return it('should send a 404', function (done) {
  160. this.res.sendStatus = function (resCode) {
  161. resCode.should.equal(404)
  162. return done()
  163. }
  164. return this.StaticServerForbidSymlinks(this.req, this.res)
  165. })
  166. })
  167. describe('with a file with no leading /', function () {
  168. beforeEach(function () {
  169. return (this.req.url = './../bar/output.pdf')
  170. })
  171. return it('should send a 404', function (done) {
  172. this.res.sendStatus = function (resCode) {
  173. resCode.should.equal(404)
  174. return done()
  175. }
  176. return this.StaticServerForbidSymlinks(this.req, this.res)
  177. })
  178. })
  179. describe('with a github style path', function () {
  180. beforeEach(function () {
  181. this.req.url = '/henryoswald-latex_example/output/output.log'
  182. return (this.fs.realpath = sinon
  183. .stub()
  184. .callsArgWith(
  185. 1,
  186. null,
  187. `${this.settings.path.compilesDir}/henryoswald-latex_example/output/output.log`
  188. ))
  189. })
  190. return it('should call next', function (done) {
  191. this.res.sendStatus = function (resCode) {
  192. resCode.should.equal(200)
  193. return done()
  194. }
  195. return this.StaticServerForbidSymlinks(this.req, this.res, done)
  196. })
  197. })
  198. return describe('with an error from fs.realpath', function () {
  199. beforeEach(function () {
  200. return (this.fs.realpath = sinon.stub().callsArgWith(1, 'error'))
  201. })
  202. return it('should send a 500', function (done) {
  203. this.res.sendStatus = function (resCode) {
  204. resCode.should.equal(500)
  205. return done()
  206. }
  207. return this.StaticServerForbidSymlinks(this.req, this.res)
  208. })
  209. })
  210. })