A simple file sharing site with an easy to use API and online panel.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

128 Zeilen
4.0KB

  1. const express = require('express');
  2. const router = express.Router();
  3. const config = require('config');
  4. const fs = require('fs').promises;
  5. const passport = require('passport');
  6. const canonicalize = require('../../util/auth/canonicalize');
  7. const ModelPath = '../../models/';
  8. const User = require(ModelPath + 'User.js');
  9. const Invite = require(ModelPath + 'Invite.js');
  10. const authenticate = require('../../util/auth/authenticateRequest');
  11. const verifyBody = require('../../util/verifyBody');
  12. const rateLimit = require('../../util/rateLimit');
  13. // Wraps passport.authenticate to return a promise
  14. const passportAuthenticate = (req, res, next) => {
  15. return new Promise((resolve) => {
  16. passport.authenticate('local', (err, user) => {
  17. resolve(user);
  18. })(req, res, next);
  19. });
  20. };
  21. // Wraps passport session creation to return a promise
  22. const passportLogin = (user, req) => {
  23. return new Promise((resolve) => {
  24. req.login(user, resolve);
  25. });
  26. };
  27. const registerParams = [
  28. {name: 'displayname', type: 'string', maxLength: config.get('User.Username.maxLength'), sanitize: true, restrict: new RegExp(config.get('User.Username.restrictedChars'))},
  29. {name: 'password', type: 'string'},
  30. {name: 'invite', type: 'string'}];
  31. router.post('/register',
  32. rateLimit(config.get('RateLimit.register.window'), config.get('RateLimit.register.max'), true),
  33. verifyBody(registerParams),
  34. async (req, res) => {
  35. const username = canonicalize(req.body.displayname);
  36. // Retrieve invite and username status
  37. const [invite, usernameCount] = await Promise.all([
  38. Invite.findOne({code: req.body.invite}),
  39. User.countDocuments({username: username})
  40. ]);
  41. // Validate the invite
  42. if (!invite)
  43. return res.status(422).json({message: 'Invalid invite code.'});
  44. if (invite.used)
  45. return res.status(422).json({message: 'Invite already used.'});
  46. if (invite.expires != null && invite.expires < Date.now())
  47. return res.status(422).json({message: 'Invite expired.'});
  48. // Validate the username
  49. if (usernameCount !== 0)
  50. return res.status(422).json({message: 'Username in use.'});
  51. // Create the user object
  52. await User.register({
  53. username: username,
  54. displayname: req.body.displayname,
  55. scope: invite.scope,
  56. date: Date.now()
  57. }, req.body.password);
  58. // Update the invite as used
  59. await Invite.updateOne({code: invite.code}, {recipient: username, used: Date.now()});
  60. res.status(200).json({'message': 'Registration successful.'});
  61. });
  62. const loginParams = [
  63. {name: 'displayname', type: 'string'},
  64. {name: 'password', type: 'string'}];
  65. router.post('/login',
  66. rateLimit(config.get('RateLimit.login.window'), config.get('RateLimit.login.max'), true),
  67. verifyBody(loginParams),
  68. async (req, res, next) => {
  69. req.body.username = canonicalize(req.body.displayname);
  70. // Authenticate
  71. const user = await passportAuthenticate(req, res, next);
  72. if (!user) {
  73. // Log failure
  74. await fs.appendFile('auth.log', `${new Date().toISOString()} login ${req.ip}\n`);
  75. return res.status(401).json({'message': 'Unauthorized.'});
  76. }
  77. // Create session
  78. await passportLogin(user, req);
  79. // Set session vars
  80. req.session.passport.displayname = user.displayname;
  81. req.session.passport.scope = user.scope;
  82. res.status(200).json({'message': 'Logged in.'});
  83. });
  84. router.post('/logout', (req, res) => {
  85. if (!req.isAuthenticated())
  86. return res.status(400).json({message: 'Not logged in.'});
  87. req.logout();
  88. res.status(200).json({'message': 'Logged out.'});
  89. });
  90. router.get('/whoami', authenticate(), (req, res) => {
  91. res.status(200).json({
  92. username: req.username,
  93. displayname: req.displayname,
  94. scope: req.scope,
  95. key: req.key
  96. });
  97. });
  98. module.exports = router;