Guest User

Untitled

a guest
Sep 23rd, 2017
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const session = require('koa-generic-session');
  2. const mongooseStore = require('koa-session-mongoose');
  3. const convert = require('koa-convert');
  4.  
  5. exports.init = app => app.use(convert(session({
  6.   key:     'sid',
  7.   cookie:  {
  8.     httpOnly:  true,
  9.     path:      '/',
  10.     overwrite: true,
  11.     signed:    false, // by default true (not needed here)
  12.     maxAge:    3600 * 4 * 1e3 // session expires in 4 hours, remember me lives longer
  13.   },
  14.  
  15.   // touch session.updatedAt in DB & reset cookie on every visit to prolong the session
  16.   // koa-session-mongoose resaves the session as a whole, not just a single field
  17.   rolling: true,
  18.  
  19.   store: mongooseStore.create({
  20.     model:   'Session',
  21.     expires: 3600 * 4
  22.   })
  23. })));
  24.  
  25. const passport = require('../libs/passport');
  26.  
  27. exports.init = app => app.use(passport.initialize());
  28.  
  29. exports.init = app => app.use(require('koa-passport').session());
  30.  
  31.  
  32. exports.init = app => app.use(async function(ctx, next) {
  33.  
  34.   // keep previous flash
  35.   let messages = ctx.session.messages || {};
  36.  
  37.   // clear all flash
  38.   delete ctx.session.messages;
  39.  
  40.   ctx.flash = function(type, html) {
  41.  
  42.     if (type === undefined) {
  43.       return messages || {};
  44.     }
  45.     if (html === undefined) {
  46.       return messages[type] || [];
  47.     }
  48.  
  49.     if (!ctx.session.messages) {
  50.       ctx.session.messages = {};
  51.     }
  52.  
  53.     if (!ctx.session.messages[type]) {
  54.       ctx.session.messages[type] = [];
  55.     }
  56.  
  57.     ctx.session.messages[type].push(html);
  58.   };
  59.  
  60.   await next();
  61.  
  62.   // note that ctx.session can be null after other middlewares,
  63.   // e.g. logout does session.destroy()
  64.   if (!ctx.session) return;
  65.  
  66.   if (ctx.status == 302 && !ctx.session.messages) {
  67.     // pass on the flash over a redirect
  68.     ctx.session.messages = messages;
  69.   }
  70.  
  71. });
  72.  
  73. const CSRF = require('koa-csrf').default;
  74.  
  75. exports.init = app => app.use(new CSRF({
  76.   invalidSessionSecretMessage: 'Invalid session secret',
  77.   invalidSessionSecretStatusCode: 403,
  78.   invalidTokenMessage: 'Invalid CSRF token',
  79.   invalidTokenStatusCode: 403,
  80.   excludedMethods: [ 'GET', 'HEAD', 'OPTIONS' ],
  81.   disableQuery: false
  82. }));
  83.  
  84. const mongoose = require('mongoose');
  85. const crypto = require('crypto');
  86. const _ = require('lodash');
  87. const config = require('config');
  88.  
  89. const userSchema = new mongoose.Schema({
  90.   displayName:   {
  91.     type:     String,
  92.     required: "Имя пользователя отсутствует."
  93.   },
  94.   email:         {
  95.     type:     String,
  96.     unique:   true,
  97.     required: "E-mail пользователя не должен быть пустым.",
  98.     validate: [
  99.       {
  100.         validator: function checkEmail(value) {
  101.           return this.deleted ? true : /^[-.\w]+@([\w-]+\.)+[\w-]{2,12}$/.test(value);
  102.         },
  103.         msg:       'Укажите, пожалуйста, корректный email.'
  104.       }
  105.     ]
  106.   },
  107.   deleted: Boolean,
  108.   // ('asdfjasdfahsdf' + 'password') => 'sdfashfkjaw76f48afasdf'
  109.   passwordHash:  {
  110.     type: String,
  111.     required: true
  112.   },
  113.   salt:          {
  114.     required: true,
  115.     type: String
  116.   }
  117. }, {
  118.   timestamps: true
  119. });
  120.  
  121. userSchema.virtual('password')
  122.   .set(function(password) {
  123.  
  124.     if (password !== undefined) {
  125.       if (password.length < 4) {
  126.         this.invalidate('password', 'Пароль должен быть минимум 4 символа.');
  127.       }
  128.     }
  129.  
  130.     this._plainPassword = password;
  131.  
  132.     if (password) {
  133.       this.salt = crypto.randomBytes(config.crypto.hash.length).toString('base64');
  134.       this.passwordHash = crypto.pbkdf2Sync(
  135.         password,
  136.         this.salt,
  137.         config.crypto.hash.iterations,
  138.         config.crypto.hash.length,
  139.         'sha1'
  140.       ).toString('base64');
  141.     } else {
  142.       // remove password (unable to login w/ password any more, but can use providers)
  143.       this.salt = undefined;
  144.       this.passwordHash = undefined;
  145.     }
  146.   })
  147.   .get(function() {
  148.     return this._plainPassword;
  149.   });
  150.  
  151. userSchema.methods.checkPassword = function(password) {
  152.   if (!password) return false; // empty password means no login by password
  153.   if (!this.passwordHash) return false; // this user does not have password (the line below would hang!)
  154.  
  155.   return crypto.pbkdf2Sync(
  156.     password,
  157.     this.salt,
  158.     config.crypto.hash.iterations,
  159.     config.crypto.hash.length,
  160.     'sha1'
  161.   ).toString('base64') == this.passwordHash;
  162. };
  163.  
  164. module.exports = mongoose.model('User', userSchema);
  165.  
  166. const passport = require('koa-passport');
  167.  
  168.  
  169. exports.post = async function(ctx, next) {
  170.   // запускает стратегию, станадартные опции что делать с результатом
  171.   // опции @https://github.com/jaredhanson/passport/blob/master/lib/middleware/authenticate.js
  172.   // можно передать и функцию
  173.   await passport.authenticate('local', {
  174.     successRedirect: '/',
  175.     failureRedirect: '/',
  176.     //failureMessage: true // запишет сообщение об ошибке в session.messages[]
  177.     failureFlash: true // req.flash, better
  178.   })(ctx, next);
  179.  
  180. };
  181.  
  182. exports.get = async function(ctx, next) {
  183.   if (ctx.isAuthenticated()) {
  184.     ctx.body = ctx.render('welcome');
  185.   } else {
  186.     ctx.body = ctx.render('login');
  187.   }
  188.  
  189. };
  190.  
  191. exports.post = async function(ctx, next) {
  192.   ctx.logout();
  193.  
  194.   ctx.session = null; // destroy session (!!!)
  195.  
  196.   ctx.redirect('/');
  197. };
  198.  
  199. const passport = require('koa-passport');
  200. const User = require('../models/user');
  201. const pick = require('lodash/pick');
  202.  
  203. exports.get = async function(ctx, next) {
  204.   ctx.body = ctx.render('registration');
  205. };
  206.  
  207. exports.post = async function(ctx, next) {
  208.   const user = await User.create(pick(ctx.request.body, User.publicFields));
  209.   // ctx.flash('error', 'message');
  210.   // ctx.redirect('/registration');
  211.   await ctx.login(user);
  212.   ctx.redirect('/');
  213. };
  214.  
  215. const Koa = require('koa');
  216. const app = new Koa();
  217.  
  218. const config = require('config');
  219. const mongoose = require('./libs/mongoose');
  220.  
  221. const path = require('path');
  222. const fs = require('fs');
  223.  
  224. app.keys = [config.get('secret')];
  225.  
  226. const handlers = fs.readdirSync(path.join(__dirname, 'middlewares')).sort();
  227.  
  228. handlers.forEach(handler => require('./middlewares/' + handler).init(app));
  229.  
  230. // ---------------------------------------
  231.  
  232. // can be split into files too
  233. const Router = require('koa-router');
  234.  
  235. const router = new Router();
  236.  
  237. router.get('/', require('./routes/frontpage').get);
  238. router.post('/login', require('./routes/login').post);
  239. router.post('/logout', require('./routes/logout').post);
  240. // router.get('/', require('./routes/login').post);
  241.  
  242. app.use(router.routes());
  243.  
  244. app.listen(3000);
  245.  
  246. const passport = require('koa-passport');
  247. const User = require('../../models/user');
  248.  
  249. require('./serialize');
  250.  
  251. require('./localStrategy');
  252.  
  253. module.exports = passport;
  254.  
  255. let passport = require('koa-passport');
  256. let LocalStrategy = require('passport-local');
  257. let User = require('../../models/user');
  258.  
  259. passport.use(new LocalStrategy({
  260.     usernameField: 'email', // 'username' by default
  261.     passwordField: 'password',
  262.     passReqToCallback: true // req for more complex cases
  263.   },
  264.   // TODO: rewrite this, use async/await
  265.   function(req, email, password, done) {
  266.     User.findOne({ email }, (err, user) => {
  267.       if (err) {
  268.         return done(err);
  269.       }
  270.  
  271.       if (!user || !user.checkPassword(password)) {
  272.         // don't say whether the user exists
  273.         return done(null, false, { message: 'Нет такого пользователя или пароль неверен.' });
  274.       }
  275.       return done(null, user);
  276.     });
  277.   }
  278. ));
  279.  
  280. const User = require('../../models/user');
  281. const passport = require('koa-passport');
  282.  
  283. // паспорт напрямую с базой не работает
  284. passport.serializeUser(function(user, done) {
  285.   done(null, user.email); // uses _id as idField
  286. });
  287.  
  288. passport.deserializeUser(function(email, done) {
  289.   User.findOne({email:email}, done); // callback version checks id validity automatically
  290. });
  291.  
  292. const promisify = require('es6-promisify');
  293. const assert = require('assert');
  294. const mongoose = require('./mongoose');
  295.  
  296. module.exports = async function clearDatabase() {
  297.  
  298.   if (mongoose.connection.readyState == 2) { // connecting
  299.     await promisify(cb => mongoose.connection.on('open', cb))();
  300.   }
  301.   assert(mongoose.connection.readyState == 1);
  302.  
  303.   const db = mongoose.connection.db;
  304.  
  305.   let collections = await promisify(cb => db.listCollections().toArray(cb))();
  306.  
  307.   collections = collections
  308.     .filter(coll => !coll.name.startsWith('system.'))
  309.     .map(coll => db.collection(coll.name)); // plain object with info => collection object
  310.  
  311.   await Promise.all(
  312.     // collections.map(coll => promisify(cb => coll.drop(cb))())
  313.     collections.map(coll => promisify(coll.drop, coll)())
  314.   );
  315.  
  316.   await Promise.all(mongoose.modelNames().map(async function(modelName) {
  317.     const model = mongoose.model(modelName);
  318.     return promisify(cb => model.ensureIndexes(cb))();
  319.   }));
  320. };
  321.  
  322. const mongoose = require('./mongoose');
  323.  
  324. module.exports = async function (models) {
  325.  
  326.   let promises = [];
  327.   for (let name in models) {
  328.     let modelObjects = models[name];
  329.  
  330.     for (let modelObject of modelObjects) {
  331.       promises.push(mongoose.model(name).create(modelObject));
  332.     }
  333.   }
  334.  
  335.   await Promise.all(promises);
  336.  
  337. };
  338.  
  339. const mongoose = require('mongoose');
  340. const config = require('config');
  341. mongoose.Promise = Promise;
  342.  
  343. if (process.env.MONGOOSE_DEBUG) {
  344.   mongoose.set('debug', true);
  345. }
  346.  
  347. mongoose.connect(config.mongoose.uri, config.mongoose.options);
  348.  
  349. module.exports = mongoose;
  350.  
  351. // generate a valid object id from an arbitrary string
  352.  
  353. const crypto = require('crypto');
  354.  
  355. // oid('course1') => generates always same id
  356. module.exports = function oid(str) {
  357.   return crypto.createHash('md5').update(str).digest('hex').substring(0, 24);
  358. };
  359.  
  360. exports.withTime = oidWithTime;
  361.  
  362. function oidWithTime(str) {
  363.   const time = Math.floor(Date.now() / 1000).toString(16);
  364.   while (time.length < 8) { // never happens in real-life though
  365.     time = '0' + time;
  366.   }
  367.   return time + crypto.createHash('md5').update(str).digest('hex').substring(0, 16);
  368. }
Add Comment
Please, Sign In to add comment