From 9a1ad879137d292e8d9f421a07c11bffcb97eabf Mon Sep 17 00:00:00 2001 From: oribicic Date: Wed, 18 Jan 2017 22:01:10 +0100 Subject: [PATCH] passcode poc --- controllers/index.js | 7 +- controllers/passcode/index.js | 179 +++++++++++++++++++++++----------- 2 files changed, 125 insertions(+), 61 deletions(-) diff --git a/controllers/index.js b/controllers/index.js index d891ce5..92d1e32 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -1,7 +1,8 @@ 'use strict'; module.exports = { - authentication: require('./authentication'), - resources: require('./resources'), - users: require('./users') + authentication: require('./authentication'), + resources: require('./resources'), + users: require('./users'), + passcode: require('./passcode') }; diff --git a/controllers/passcode/index.js b/controllers/passcode/index.js index 6a3f294..5d4531d 100644 --- a/controllers/passcode/index.js +++ b/controllers/passcode/index.js @@ -1,76 +1,139 @@ 'use strict'; -const Promise = require('bluebird'); const _ = require('lodash'); -const services = require('../../models/services'); +const Promise = require("bluebird"); -const defaultSufixType = 'alpha'; +const validator = require('../../middleware/validator'); +const services = require('../../models/services'); const validate = { - create: validator.validation('body', { - rules: { - count: { type: 'positive'}}, - prefix: { type: 'norule'}, - sufixLength: { type: 'positive', length: { min: 4 }}, - sufixType: { type: ['alpha', 'alpha-num']} - }, - required: ['email', 'password'] - }) + create: validator.validation( + 'body', { + rules : { + count : { type: 'positive' }, + prefix : { type: 'norule' }, + suffixLength: { + type : 'positive', + length: { min: 4 } + }, + suffixType : { type: ['alpha', 'alpha-num'] } + }, + required: ['count', 'suffixType'] + } + ) +}; + +function create(req, res, next) { + + services.user.getById(req.params.userId) + .then( + user => _generate(user, [], req.body) + .timeout(30000) + .then( + (passcodes) => services.passcode.bulkCreate(_mapPasscodes(user, passcodes)) + .then( + (passcodes) => { + res.status(201); + res.locals = passcodes; + next(); + } + ) + .catch(err => next(err)) + ) + .catch(err => next(err)) + ) + .catch(err => next(err)); +} + +//TODO: ovo treba u servis prebacit +const optionsDefault = { + count : 1, + prefix : '', + suffixLength: 4, + suffixType : 'alpha' }; -function _hasPasscode(userId, passcode){ - //create passcode +function _generate(user, passcodes, options = optionsDefault) { + const deferred = Promise.defer(); + + const neededCount = options.count - passcodes.length; + if (neededCount <= 0) { + deferred.resolve(passcodes); + } + + options.count = neededCount; + const testPasscodes = _createPasscodes(options); + const validCandidatePasscodes = _.difference(testPasscodes, passcodes); + + services.passcode.listWithFilter( + undefined, + { + code : { $in: validCandidatePasscodes }, + userId: user.id + ''//TODO ask about this hack + } + ) + .then( + (existing) => { + if (existing.count > 0) { + const existingPasscodes = _.map(existing.rows, (row) => row.code); + const validPasscodes = _.difference(validCandidatePasscodes, existingPasscodes); + + _generate(user, _.concat(passcodes, validPasscodes), options) + .then((newPasscodes) => deferred.resolve(newPasscodes)) + .catch(err => deferred.reject(err)); + } else { + deferred.resolve(_.concat(passcodes, validCandidatePasscodes)); + } + } + ) + .catch(err => deferred.reject(err)); + + return deferred.promise; +} + +function _createPasscodes(options) { + + const passcodes = []; + + while (passcodes.length < options.count) { + const passcode = _createPasscode(options); + if (!_.includes(passcodes, passcode)) { + passcodes.push(passcode); + } + } + + return passcodes; } -function createPasscodes( - userId, - options = { - count: 1, - prefix: '', - sufixLength: 4, - sufixType: defaultSufixType - } -) { - - var passcodes = []; - - do { - var passcode = createPasscode(userId, options) - if(!_.includes(passcodes, passcode)){ - passcodes.push(passcode); - } - } while(passcodes.length <= options.count); - - return passcodes; +const alphaDictionary = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; +const alphaNumericDictionary = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + +function _createPasscode(options) { + switch (options.suffixType) { + case 'alpha-num': + return options.prefix + _generateRandom(options.suffixLength, alphaNumericDictionary); + default: + return options.prefix + _generateRandom(options.suffixLength, alphaDictionary); + } } -function createPasscode(userId, options){ - services.passcodes. +function _generateRandom(length, dictionary) { + const sample = _.times(length, () => _.sample(dictionary)); + return sample.join(''); } -function create(req, res, next) { - services.user.getById( - req.params.userId - ).then(user => { - const passcodes.... - services.passcode.getExistingPasscodes({where : {code: ['....']}}) - .then(existing => REKURZIJA) - services.passcode.doesNotExist({ where: { userId: user.id, code: 'nesto' }}) - .then( () => services.user.create(req.body)) - .then( user => services.emailConfirmation.createToken(user) - .then( emailConfirmation => services.emailConfirmation.sendMail({ - email: user.email, token: emailConfirmation.token - })) - .then( () => { - res.status(201); - res.locals = user; - next(); - }) - ) - ) - .catch(err => next(err)); +function _mapPasscodes(user, passcodes) { + return _.map( + passcodes, (passcode) => { + return { + userId: user.id, + code : passcode + }; + } + ); } module.exports = { - create: create + create : create, + validate: validate };