Advertisement
Guest User

JS Example

a guest
Jan 20th, 2017
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const jwt = require('jsonwebtoken')
  2. const express = require('express')
  3. const bodyParser = require('body-parser')
  4. const models = require('./models.js')
  5. const passport = require('passport')
  6. const crypto = require('crypto')
  7. const session = require('express-session')
  8. const FileStore = require('session-file-store')(session)
  9. const RedditStrategy = require('passport-reddit').Strategy
  10. const cors = require('cors')
  11.  
  12. const settings = {
  13.   'mode': 'development',
  14.   'secret': '',
  15.   'admins': ['strideynet'],
  16.   'responses': {
  17.     'noPermissions' : {"error":{"name": "noPermissions", "message": "You don't have the permissions to do that!"}},
  18.     '404' : {"error":{"name": "notFound", "message": "That resource can't be found!"}},
  19.     'invalidFormat': {"error":{"name": "invalidFormat", "message": "A required field may be of the wrong type or null!"}}
  20.   },
  21.   'modifiableFields': ['description', 'public'],
  22.   'changing': {
  23.     'development': {
  24.       'key': 'Re92nrdP8kmd2g',
  25.       'secret': '',
  26.       'redirect': 'http://localhost/auth/reddit/callback',
  27.       'siteURL': 'test'
  28.     }
  29.   }
  30. }
  31.  
  32. passport.serializeUser(function(user, done) {
  33.   done(null, user);
  34. });
  35.  
  36. passport.deserializeUser(function(obj, done) {
  37.   done(null, obj);
  38. });
  39.  
  40. passport.use(new RedditStrategy({
  41.     clientID: settings.changing[settings.mode].key,
  42.     clientSecret: settings.changing[settings.mode].secret,
  43.     callbackURL: settings.changing[settings.mode].redirect
  44.   },
  45.   function(accessToken, refreshToken, profile, done) {
  46.     // asynchronous verification, for effect...
  47.     process.nextTick(function () {
  48.  
  49.       // To keep the example simple, the user's Reddit profile is returned to
  50.       // represent the logged-in user.  In a typical application, you would want
  51.       // to associate the Reddit account with a user record in your database,
  52.       // and return that user instead.
  53.       return done(null, profile);
  54.     });
  55.   }
  56. ));
  57.  
  58. let app = express()
  59.  
  60. let api = express.Router()
  61. let auth = express.Router()
  62.  
  63. app.use(session({
  64.    store: new FileStore(),
  65.   secret: '',
  66.   resave: false,
  67.   saveUninitialized: true
  68. }))
  69.  
  70. auth.use(passport.initialize());
  71. auth.use(passport.session());
  72.  
  73. auth.get('/key', function(req, res) {
  74.   if (req.isAuthenticated()) {
  75.     let data = {
  76.       'user': req.user.name,
  77.       'admin': false
  78.     }
  79.     if (settings.admins.indexOf(req.user.name) >= 0) {
  80.       data.admin = true
  81.     }
  82.  
  83.     data.JWT = jwt.sign(data, settings.secret)
  84.  
  85.     res.status(200).json(data)
  86.   } else {
  87.     res.status(401).json({"error": {"name": "loginRequired", "redirect": "/auth/login/"}})
  88.   }
  89. })
  90.  
  91. auth.get('/login', function(req, res) {
  92.   if (req.isAuthenticated()) {
  93.     res.redirect('http://localhost/')
  94.   } else {
  95.     res.send('<a href="/auth/reddit"> Click here to proceed with logging in</a>')
  96.   }
  97. })
  98.  
  99. auth.get('/reddit', function(req, res, next){
  100.   req.session.state = crypto.randomBytes(32).toString('hex');
  101.   passport.authenticate('reddit', {
  102.     state: req.session.state,
  103.   })(req, res, next);
  104. });
  105.  
  106. // GET /auth/reddit/callback
  107. //   Use passport.authenticate() as route middleware to authenticate the
  108. //   request.  If authentication fails, the user will be redirected back to the
  109. //   login page.  Otherwise, the primary route function function will be called,
  110. //   which, in this example, will redirect the user to the home page.
  111. auth.get('/reddit/callback', function(req, res, next){
  112.   // Check for origin via state token
  113.   console.log(req.query.state)
  114.   console.log('session')
  115.   console.log(req.session.state)
  116.   if (req.query.state == req.session.state){
  117.     passport.authenticate('reddit', {
  118.       successRedirect: 'http://panama.mhoc.co.uk/',
  119.       failureRedirect: '/login'
  120.     })(req, res, next);
  121.   }
  122.   else {
  123.     next( new Error(403) );
  124.   }
  125. });
  126.  
  127. auth.get('/logout', function(req, res){
  128.   req.logout();
  129.   res.redirect('/auth/login');
  130. });
  131.  
  132. //api
  133. //API Bodyparser
  134. api.use(bodyParser.json())
  135.  
  136. //ensure authed
  137. api.use(function( req, res, next) {
  138.   if (req.get('JWT')) {
  139.     return jwt.verify(req.get('JWT'), settings.secret, function(err, decoded) {
  140.       if (err) {
  141.         return res.status(401).json({"error": err})
  142.       }
  143.  
  144.       if (decoded.user) {
  145.         req.decodedJWT = decoded
  146.         req.decodedJWT.admin = false
  147.         if (settings.admins.indexOf(req.decodedJWT.user) >= 0) {
  148.           req.decodedJWT.admin = true
  149.         }
  150.         return next()
  151.       } else {
  152.         return res.status(401).json({"error":{"name": "JWTMissingInfo", "message": "The JWT is invalid!"}})
  153.       }
  154.     })
  155.   } else {
  156.     return res.status(401).json({"error":{"name": "noJWTHeader", "message": "You must include a JWT."}})
  157.   }
  158. })
  159.  
  160. // Simple endpoint. Sends what they sent.
  161. api.post('/test', function(req, res) {
  162.   res.json(req.body)
  163. })
  164.  
  165. //Autocomplete option :P
  166. api.get('/suggest', function(req, res){
  167.   models['accountModel'].find({}).distinct('_id', function(err, documents){
  168.     if (err) {
  169.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  170.     }
  171.     return res.status(200).json(documents)
  172.   })
  173. })
  174.  
  175. //All accounts -> Admin Only
  176. api.get('/account/@all', function(req, res) {
  177.   if (settings.admins.indexOf(req.decodedJWT.user) >= 0) {
  178.     models['accountModel'].find({}, function(err, documents){
  179.       if (err) {
  180.         return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  181.       }
  182.       return res.status(200).json(documents)
  183.     })
  184.   } else {
  185.     return res.status(403).json(settings.responses.noPermissions)
  186.   }
  187. })
  188.  
  189. //All accounts that are public
  190. api.get('/account/@public', function(req, res) {
  191.   models['accountModel'].find({"public": true}, function(err, documents){
  192.     if (err) {
  193.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  194.     }
  195.     return res.status(200).json(documents)
  196.   })
  197. })
  198.  
  199. //All accounts you own TODO: Optimise this!
  200. api.get('/account/@mine', function(req, res) {
  201.   models['accountModel'].find({}, function(err, documents){
  202.     if (err) {
  203.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  204.     }
  205.     let ownedAccounts = []
  206.     documents.forEach(function(document, index){
  207.       if (document.users[req.decodedJWT.user] >= 0) {
  208.         ownedAccounts.push(document)
  209.       }
  210.     })
  211.  
  212.     return res.status(200).json(ownedAccounts)
  213.   })
  214. })
  215.  
  216. //Create account -> Admin Only TODO: More validation and add logging
  217. api.post('/account/', function(req, res) {
  218.   if (req.decodedJWT.admin) {
  219.     let newAccount = new models['accountModel']({
  220.       "_id": req.body['_id'],
  221.       public: req.body.public,
  222.       description: req.body.description,
  223.       accountType: req.body.accountType,
  224.       users: req.body.users,
  225.       wages: req.body.wages
  226.     })
  227.  
  228.     newAccount.save(function(err, newAccount){
  229.       if (err) {
  230.         console.log(err)
  231.         return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  232.       }
  233.       return res.status(201).json(newAccount)
  234.     })
  235.   } else {
  236.     return res.status(403).json(settings.responses.noPermissions)
  237.   }
  238. })
  239.  
  240. //Get account info -> Users only
  241. api.get('/account/:accountID', function(req, res) {
  242.   models['accountModel'].findOne({"_id": req.params.accountID}, function(err, document){
  243.     if (err) {
  244.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  245.     }
  246.     if (document) {
  247.       if ((document.users[req.decodedJWT.user] > 2) || (req.decodedJWT.admin)) {
  248.         return res.status(200).json(document)
  249.       } else {
  250.         return res.status(403).json(settings.responses.noPermissions)
  251.       }
  252.     } else {
  253.       return res.status(404).json(settings.responses['404'])
  254.     }
  255.   })
  256. })
  257.  
  258. //Modify account details -> Owners, Users and Staff? TODO:Logging!
  259. api.put('/account/:accountID', function(req, res) {
  260.   models['accountModel'].findOne({"_id": req.params.accountID}, function(err, document){
  261.     if (err) {
  262.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  263.     }
  264.     if (document) {
  265.       if ((document.users[req.decodedJWT.user] >= 3) || (req.decodedJWT.admin)) {
  266.         if (req.body.changedFields) {
  267.           let failedFields = []
  268.  
  269.           for (let key in req.body.changedFields) {
  270.             if (settings.modifiableFields.indexOf(key) >= 0) {
  271.               document[key] = req.body.changedFields[key]
  272.             } else {
  273.               failedFields.push(key)
  274.             }
  275.           }
  276.  
  277.           document.save(function (err, updatedDocument) {
  278.           if (err) {
  279.             return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  280.           }
  281.             res.status(200).json(updatedDocument)
  282.           })
  283.  
  284.         } else {
  285.           return res.status(400).json(settings.responses.invalidFormat)
  286.         }
  287.       } else {
  288.         return res.status(403).json(settings.responses.noPermissions)
  289.       }
  290.     } else {
  291.       return res.status(404).json(settings.responses['404'])
  292.     }
  293.   })
  294. })
  295.  
  296. //Add new user or modify existing! -> account owners only
  297. api.post('/account/:accountID/users', function(req, res) {
  298.   models['accountModel'].findOne({"_id": req.params.accountID}, function(err, document){
  299.     if (err) {
  300.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  301.     }
  302.     if (document) {
  303.       if ((document.users[req.decodedJWT.user] >= 3) || (req.decodedJWT.admin)) {
  304.         if (req.body.users) {
  305.           let failedUsers = []
  306.           for (let key in req.body.users) {
  307.             if (((Number(req.body.users[key]) >= 3) && ((document.users[req.params.userID]) == 4)) || (Number(req.body.users[key]) < 3)) {
  308.               document.users[key] = Number(req.body.users[key])
  309.             } else {
  310.               failedUsers.push(req.body.users[key])
  311.             }
  312.           }
  313.  
  314.           document.markModified('users')
  315.  
  316.           document.save(function (err, updatedDocument) {
  317.           if (err) {
  318.             return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  319.           }
  320.             res.status(200).json(updatedDocument)
  321.           })
  322.         } else {
  323.           return res.status(400).json(settings.responses.invalidFormat)
  324.         }
  325.       } else {
  326.         return res.status(403).json(settings.responses.noPermissions)
  327.       }
  328.     } else {
  329.       return res.status(404).json(settings.responses['404'])
  330.     }
  331.   })
  332. })
  333.  
  334. //Remove user -> account owners only
  335. api.delete('/account/:accountID/users/:userID', function(req, res) {
  336.   models['accountModel'].findOne({"_id": req.params.accountID}, function(err, document){
  337.     if (err) {
  338.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  339.     }
  340.     if (document) {
  341.       if (document.users[req.params.userID]) {
  342.         if ((document.users[req.decodedJWT.user] > document.users[req.params.userID]) || (req.decodedJWT.admin)) {
  343.           if (Object.keys(document.users).length > 1) {
  344.             delete document.users[req.params.userID]
  345.  
  346.             document.markModified('users')
  347.  
  348.             document.save(function (err, updatedDocument) {
  349.               if (err) {
  350.                 return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  351.               }
  352.               return res.status(200).json(updatedDocument)
  353.             })
  354.           } else {
  355.             return res.status(400).json({"error":{"name": "lastElement", "message": "I won't let you remove the final person!"}})
  356.           }
  357.         } else {
  358.           return res.status(403).json(settings.responses.noPermissions)
  359.         }
  360.       } else {
  361.         return res.status(404).json(settings.responses['404'])
  362.       }
  363.     } else {
  364.       return res.status(404).json(settings.responses['404'])
  365.     }
  366.   })
  367. })
  368.  
  369. //Remove wage -> admin
  370. api.delete('/account/:accountID/wages/:wageID', function(req, res) {
  371.   models['accountModel'].findOne({"_id": req.params.accountID}, function(err, document){
  372.     if (err) {
  373.       return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  374.     }
  375.     if (document) {
  376.       if (document.wages.indexOf(req.params.wageID) != -1) {
  377.         if (req.decodedJWT.admin) {
  378.           document.wages.splice(document.wages.indexOf(req.params.wageID), 1)
  379.  
  380.           document.markModified('wages')
  381.           document.save(function (err, updatedDocument) {
  382.             if (err) {
  383.               return res.status(500).json({"error":{"name": "databaseError", "message": "Somethings gone horribly wrong!", "detail": err}})
  384.             }
  385.             return res.status(200).json(updatedDocument)
  386.           })
  387.         } else {
  388.           return res.status(403).json(settings.responses.noPermissions)
  389.         }
  390.       } else {
  391.         return res.status(404).json(settings.responses['404'])
  392.       }
  393.     } else {
  394.       return res.status(404).json(settings.responses['404'])
  395.     }
  396.   })
  397. })
  398.  
  399. //Get all transactions -> Staff only
  400. api.get('/wages', function(req, res) {
  401.  
  402. })
  403.  
  404. //Get all transactions -> Staff only
  405. api.get('/wages/@suggest', function(req, res) {
  406.  
  407. })
  408.  
  409.  
  410. //Get all transactions -> Staff only
  411. api.get('/transactions', function(req, res) {
  412.  
  413. })
  414.  
  415. //New transaction. Users can create transactions but only for their accounts!
  416. api.post('/transaction', function(req, res) {
  417.  
  418. })
  419.  
  420. //Info on that trans -> Staff
  421. api.get('/transaction/:transactionID', function(req, res) {
  422.  
  423. })
  424.  
  425. //Modify info on that trans -> Staff
  426. api.put('/transaction/:transactionID', function(req, res) {
  427.  
  428. })
  429.  
  430. //Delete transaction -> Staff Only
  431. api.delete('/transaction/:transactionID', function(req, res) {
  432.  
  433. })
  434.  
  435. //Staff audit log :O
  436. api.get('/logs', function(req, res) {
  437. })
  438.  
  439. app.use('/api', api)
  440. app.use('/auth', auth)
  441.  
  442. app.listen(8081, function () {
  443.   console.log('Listening on 80')
  444. })
  445.  
  446. var proxy = require('redbird')({port: 80});
  447.  
  448. proxy.register('localhost/','http://127.0.0.1:8080')
  449.  
  450. proxy.register('localhost/api', 'http://127.0.0.1:8081/api')
  451. proxy.register('localhost/auth','http://127.0.0.1:8081/auth')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement