A simple file sharing site with an easy to use API and online panel.
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

86 wiersze
2.8KB

  1. const fs = require('fs').promises;
  2. const config = require('config');
  3. const ModelPath = '../models/';
  4. const Key = require(ModelPath + 'Key.js');
  5. const User = require(ModelPath + 'User.js');
  6. const verifyScope = require('./verifyScope.js');
  7. const rateLimit = require('express-rate-limit');
  8. const checkSession = (req, scope, status) => {
  9. if (req.isAuthenticated()) {
  10. status.authenticated = true;
  11. if (!scope || verifyScope(req.session.passport.scope, scope)) {
  12. req.username = req.session.passport.user;
  13. req.displayname = req.session.passport.displayname;
  14. req.scope = req.session.passport.scope;
  15. req.key = null;
  16. status.permission = true;
  17. }
  18. }
  19. };
  20. const checkKey = async (req, scope, status) => {
  21. if (req.body.key) {
  22. const key = await Key.findOne({key: req.body.key});
  23. if (key) {
  24. status.authenticated = true;
  25. if (!scope || verifyScope(key.scope, scope)) {
  26. req.username = key.issuer;
  27. req.displayname = key.issuer;
  28. req.scope = key.scope;
  29. req.key = key.key;
  30. status.permission = true;
  31. }
  32. } else {
  33. // Log failure
  34. await fs.appendFile('auth.log', `${new Date().toISOString()} key ${req.ip}\n`);
  35. }
  36. }
  37. };
  38. const apiLimiter = config.get('RateLimit.enable')
  39. ? rateLimit({
  40. windowMs: config.get('RateLimit.api.window') * 1000,
  41. max: config.get('RateLimit.api.max'),
  42. skip: (req, res) => res.statusCode !== 401 && res.statusCode !== 403
  43. })
  44. : (req, res, next) => { next(); };
  45. // Middleware that checks for authentication by either API key or session
  46. // sets req.username, req.displayname, req.scope, and req.key if authenticated properly,
  47. // otherwise throws an error code.
  48. // If the user is banned, also throw an error.
  49. const requireAuth = scope => (req, res, next) => {
  50. apiLimiter(req, res, async () => {
  51. const status = {
  52. authenticated: false,
  53. permission: false
  54. };
  55. // First, check the session
  56. checkSession(req, scope, status);
  57. // If not authenticated yet, check for a key
  58. if (!status.authenticated)
  59. await checkKey(req, scope, status);
  60. if (!status.authenticated)
  61. return res.status(401).json({message: 'Unauthorized.'});
  62. else if (!status.permission)
  63. return res.status(403).json({message: 'Forbidden.'});
  64. // Check if the user is banned
  65. const user = await User.findOne({username: req.username});
  66. if (user && user.banned)
  67. return res.status(403).json({message: 'Forbidden.'});
  68. next();
  69. });
  70. };
  71. module.exports.checkSession = checkSession;
  72. module.exports.checkKey = checkKey;
  73. module.exports.requireAuth = requireAuth;