index.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. const crypto = require('crypto');
  2. const express = require('express');
  3. const helmet = require('helmet');
  4. const storage = require('../storage');
  5. const config = require('../config');
  6. const auth = require('../middleware/auth');
  7. const language = require('../middleware/language');
  8. const pages = require('./pages');
  9. const filelist = require('./filelist');
  10. const IS_DEV = config.env === 'development';
  11. const ID_REGEX = '([0-9a-fA-F]{10})';
  12. module.exports = function(app) {
  13. app.use(helmet());
  14. app.use(
  15. helmet.hsts({
  16. maxAge: 31536000,
  17. force: !IS_DEV
  18. })
  19. );
  20. app.use(function(req, res, next) {
  21. req.cspNonce = crypto.randomBytes(16).toString('hex');
  22. next();
  23. });
  24. if (!IS_DEV) {
  25. app.use(
  26. helmet.contentSecurityPolicy({
  27. directives: {
  28. defaultSrc: ["'self'"],
  29. connectSrc: [
  30. "'self'",
  31. 'wss://*.dev.lcip.org',
  32. 'wss://*.mozaws.net',
  33. 'wss://send.firefox.com',
  34. 'https://*.dev.lcip.org',
  35. 'https://*.accounts.firefox.com',
  36. 'https://sentry.prod.mozaws.net',
  37. 'https://www.google-analytics.com'
  38. ],
  39. imgSrc: [
  40. "'self'",
  41. 'https://www.google-analytics.com',
  42. 'https://*.dev.lcip.org',
  43. 'https://firefoxusercontent.com'
  44. ],
  45. scriptSrc: [
  46. "'self'",
  47. function(req) {
  48. return `'nonce-${req.cspNonce}'`;
  49. }
  50. ],
  51. styleSrc: ["'self'", 'https://code.cdn.mozilla.net'],
  52. fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
  53. formAction: ["'none'"],
  54. frameAncestors: ["'none'"],
  55. objectSrc: ["'none'"],
  56. reportUri: '/__cspreport__'
  57. }
  58. })
  59. );
  60. }
  61. app.use(function(req, res, next) {
  62. res.set('Pragma', 'no-cache');
  63. res.set('Cache-Control', 'no-cache');
  64. next();
  65. });
  66. app.use(express.json());
  67. app.get('/', language, pages.index);
  68. app.get('/signin', pages.blank);
  69. app.get('/oauth', pages.blank);
  70. app.get('/legal', language, pages.legal);
  71. app.get('/jsconfig.js', require('./jsconfig'));
  72. app.get(`/share/:id${ID_REGEX}`, language, pages.blank);
  73. app.get(`/download/:id${ID_REGEX}`, language, pages.download);
  74. app.get('/completed', language, pages.blank);
  75. app.get('/unsupported/:reason', language, pages.unsupported);
  76. app.get(`/api/download/:id${ID_REGEX}`, auth.hmac, require('./download'));
  77. app.get(
  78. `/api/download/blob/:id${ID_REGEX}`,
  79. auth.hmac,
  80. require('./download')
  81. );
  82. app.get(`/api/exists/:id${ID_REGEX}`, require('./exists'));
  83. app.get(`/api/metadata/:id${ID_REGEX}`, auth.hmac, require('./metadata'));
  84. app.get('/api/filelist', auth.fxa, filelist.get);
  85. app.post('/api/filelist', auth.fxa, filelist.post);
  86. app.post('/api/upload', auth.fxa, require('./upload'));
  87. app.post(`/api/delete/:id${ID_REGEX}`, auth.owner, require('./delete'));
  88. app.post(`/api/password/:id${ID_REGEX}`, auth.owner, require('./password'));
  89. app.post(
  90. `/api/params/:id${ID_REGEX}`,
  91. auth.owner,
  92. auth.fxa,
  93. require('./params')
  94. );
  95. app.post(`/api/info/:id${ID_REGEX}`, auth.owner, require('./info'));
  96. app.get('/__version__', function(req, res) {
  97. res.sendFile(require.resolve('../../dist/version.json'));
  98. });
  99. app.get('/__lbheartbeat__', function(req, res) {
  100. res.sendStatus(200);
  101. });
  102. app.get('/__heartbeat__', async (req, res) => {
  103. try {
  104. await storage.ping();
  105. res.sendStatus(200);
  106. } catch (e) {
  107. res.sendStatus(500);
  108. }
  109. });
  110. };