server.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import './configToEnv';
  2. import dotenv from 'dotenv';
  3. dotenv.config();
  4. import nextApp from 'next';
  5. import express, { Request, Response } from 'express';
  6. import mongoose from 'mongoose';
  7. import helmet from 'helmet';
  8. import morgan from 'morgan';
  9. import Raven from 'raven';
  10. import cookieParser from 'cookie-parser';
  11. import passport from 'passport';
  12. import cors from 'cors';
  13. import {
  14. validateBody,
  15. validationCriterias,
  16. validateUrl,
  17. ipCooldownCheck,
  18. } from './controllers/validateBodyController';
  19. import * as auth from './controllers/authController';
  20. import * as link from './controllers/linkController';
  21. import './cron';
  22. import './passport';
  23. mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true });
  24. if (process.env.RAVEN_DSN) {
  25. Raven.config(process.env.RAVEN_DSN).install();
  26. }
  27. const catchErrors = fn => (req, res, next) =>
  28. fn(req, res, next).catch(err => {
  29. res
  30. .status(500)
  31. .json({ error: 'Sorry an error ocurred. Please try again later.' });
  32. if (process.env.RAVEN_DSN) {
  33. Raven.captureException(err, {
  34. user: { email: req.user && req.user.email },
  35. });
  36. throw new Error(err);
  37. } else {
  38. throw new Error(err);
  39. }
  40. });
  41. const port = Number(process.env.PORT) || 3000;
  42. const dev = process.env.NODE_ENV !== 'production';
  43. const app = nextApp({ dir: './client', dev });
  44. const handle = app.getRequestHandler();
  45. app.prepare().then(() => {
  46. const server = express();
  47. server.set('trust proxy', true);
  48. if (process.env.NODE_ENV !== 'production') {
  49. server.use(morgan('dev'));
  50. }
  51. server.use(helmet());
  52. server.use(cookieParser());
  53. server.use(express.json());
  54. server.use(express.urlencoded({ extended: true }));
  55. server.use(passport.initialize());
  56. server.use(express.static('static'));
  57. server.use((req, _res, next) => {
  58. req.realIP =
  59. (req.headers['x-real-ip'] as string) ||
  60. req.connection.remoteAddress ||
  61. '';
  62. return next();
  63. });
  64. server.use(link.customDomainRedirection);
  65. /* View routes */
  66. server.get(
  67. '/reset-password/:resetPasswordToken?',
  68. catchErrors(auth.resetUserPassword),
  69. (req, res) => app.render(req, res, '/reset-password', req.user)
  70. );
  71. server.get(
  72. '/verify/:verificationToken?',
  73. catchErrors(auth.verify),
  74. (req, res) => app.render(req, res, '/verify', req.user)
  75. );
  76. /* User and authentication */
  77. server.post(
  78. '/api/auth/signup',
  79. validationCriterias,
  80. validateBody,
  81. catchErrors(auth.signup)
  82. );
  83. server.post(
  84. '/api/auth/login',
  85. validationCriterias,
  86. validateBody,
  87. auth.authLocal,
  88. auth.login
  89. );
  90. server.post('/api/auth/renew', auth.authJwt, auth.renew);
  91. server.post(
  92. '/api/auth/changepassword',
  93. auth.authJwt,
  94. catchErrors(auth.changeUserPassword)
  95. );
  96. server.post(
  97. '/api/auth/generateapikey',
  98. auth.authJwt,
  99. catchErrors(auth.generateUserApiKey)
  100. );
  101. server.post(
  102. '/api/auth/resetpassword',
  103. catchErrors(auth.requestUserPasswordReset)
  104. );
  105. server.get('/api/auth/usersettings', auth.authJwt, auth.userSettings);
  106. /* URL shortener */
  107. server.post(
  108. '/api/url/submit',
  109. cors(),
  110. auth.authApikey,
  111. auth.authJwtLoose,
  112. catchErrors(auth.recaptcha),
  113. catchErrors(validateUrl),
  114. catchErrors(ipCooldownCheck),
  115. catchErrors(link.shortener)
  116. );
  117. server.post(
  118. '/api/url/deleteurl',
  119. auth.authApikey,
  120. auth.authJwt,
  121. catchErrors(link.deleteUserLink)
  122. );
  123. server.get(
  124. '/api/url/geturls',
  125. auth.authApikey,
  126. auth.authJwt,
  127. catchErrors(link.getUserLinks)
  128. );
  129. server.post(
  130. '/api/url/customdomain',
  131. auth.authJwt,
  132. catchErrors(link.setCustomDomain)
  133. );
  134. server.delete(
  135. '/api/url/customdomain',
  136. auth.authJwt,
  137. catchErrors(link.deleteCustomDomain)
  138. );
  139. server.get(
  140. '/api/url/stats',
  141. auth.authApikey,
  142. auth.authJwt,
  143. catchErrors(link.getLinkStats)
  144. );
  145. server.post('/api/url/requesturl', catchErrors(link.goToLink));
  146. server.post('/api/url/report', catchErrors(link.reportLink));
  147. server.post(
  148. '/api/url/admin/ban',
  149. auth.authApikey,
  150. auth.authJwt,
  151. auth.authAdmin,
  152. catchErrors(link.ban)
  153. );
  154. server.get(
  155. '/:id',
  156. catchErrors(link.goToLink),
  157. (req: Request, res: Response) => {
  158. switch (req.pageType) {
  159. case 'password':
  160. return app.render(req, res, '/url-password', {
  161. protectedLink: req.protectedLink,
  162. });
  163. case 'info':
  164. default:
  165. return app.render(req, res, '/url-info', {
  166. linkTarget: req.linkTarget,
  167. });
  168. }
  169. }
  170. );
  171. server.get('*', (req, res) => handle(req, res));
  172. server.listen(port, err => {
  173. if (err) throw err;
  174. console.log(`> Ready on http://localhost:${port}`);
  175. });
  176. });