aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2014-09-06 19:40:55 -0700
committerAdam Soltys <[email protected]>2014-09-06 19:40:55 -0700
commite547723b23ccc58c832cac966b1b666a426afefb (patch)
tree757da6f03a771c612002300e60e2adf60c2f98d8
parent86d321130850e15b580c1d4705fc0bdd9473f7d8 (diff)
downloadcoinos-server-e547723b23ccc58c832cac966b1b666a426afefb.tar.gz
coinos-server-e547723b23ccc58c832cac966b1b666a426afefb.zip
Generate key on registration
-rw-r--r--public/css/calculator.less13
-rw-r--r--public/js/calculator.coffee4
-rw-r--r--public/js/check_password.js343
-rw-r--r--public/js/key.coffee28
-rw-r--r--public/js/register.coffee31
-rw-r--r--public/js/setup.coffee44
-rw-r--r--routes/sessions.js5
-rw-r--r--routes/users.js105
-rw-r--r--src/routes/sessions.coffee5
-rw-r--r--src/routes/users.coffee84
-rw-r--r--views/users/edit.html8
-rw-r--r--views/users/new.html11
12 files changed, 540 insertions, 141 deletions
diff --git a/public/css/calculator.less b/public/css/calculator.less
index 2764332b..10d4570d 100644
--- a/public/css/calculator.less
+++ b/public/css/calculator.less
@@ -71,3 +71,16 @@ td#total { font-weight: bold; text-align: right; }
@page {
margin: 0;
}
+
+div.pass-container {
+ height: 30px;
+}
+
+div.pass-bar {
+ height: 11px;
+ margin-top: 2px;
+}
+div.pass-hint {
+ font-family: arial;
+ font-size: 11px;
+}
diff --git a/public/js/calculator.coffee b/public/js/calculator.coffee
index edbd4fa9..b31d3ee8 100644
--- a/public/js/calculator.coffee
+++ b/public/js/calculator.coffee
@@ -60,7 +60,7 @@ setup = ->
if g.user.logo
$('#logo').attr('src', g.user.logo).show()
- getAddress() if g.user.bip32
+ getAddress() if g.user.pubkey
$('#symbol').html(g.user.currency)
$('#currency').html(g.user.currency)
@@ -196,7 +196,7 @@ logTransaction = (txid, amount) ->
getAddress = ->
i = g.user.index
- bip32 = new BIP32(g.user.bip32)
+ bip32 = new BIP32(g.user.pubkey)
result = bip32.derive("m/0/#{i}")
hash160 = result.eckey.pubKeyHash
g.user.address = (new Bitcoin.Address(hash160)).toString()
diff --git a/public/js/check_password.js b/public/js/check_password.js
new file mode 100644
index 00000000..f8fc40cc
--- /dev/null
+++ b/public/js/check_password.js
@@ -0,0 +1,343 @@
+/*
+ jQuery(document).ready(function () {
+ "use strict";
+ var $password = $(':password').pwstrength(),
+ common_words = ["password", "god", "123456"];
+
+ $password.pwstrength("addRule", "notEmail", function (options, word, score) {
+ return word.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i) && score;
+ }, -100, true);
+
+ $password.pwstrength("addRule", "commonWords", function (options, word, score) {
+ var result = false;
+ $.each(common_words, function (i, item) {
+ var re = new RegExp(item, "gi");
+ if (word.match(re)) {
+ result = score;
+ }
+ });
+ return result;
+ }, -500, true);
+ });
+
+ */
+
+
+
+
+/*jslint vars: false, browser: true, nomen: true, regexp: true */
+/*global jQuery */
+
+/*
+* jQuery Password Strength plugin for Twitter Bootstrap
+*
+* Copyright (c) 2008-2013 Tane Piper
+* Copyright (c) 2013 Alejandro Blanco
+* Dual licensed under the MIT and GPL licenses.
+*
+*/
+
+(function ($) {
+ "use strict";
+
+ var options = {
+ errors: [],
+ // Options
+ minChar: 8,
+ errorMessages: {
+ password_to_short: "The Password is too short",
+ same_as_username: "Your password cannot be the same as your username"
+ },
+ scores: [17, 26, 40, 50],
+ verdicts: ["Weak", "Normal", "Medium", "Strong", "Very Strong"],
+ showVerdicts: true,
+ raisePower: 1.4,
+ usernameField: "#username",
+ onLoad: undefined,
+ onKeyUp: undefined,
+ viewports: {
+ progress: undefined,
+ verdict: undefined,
+ errors: undefined
+ },
+ // Rules stuff
+ ruleScores: {
+ wordNotEmail: -100,
+ wordLength: -100,
+ wordSimilarToUsername: -100,
+ wordLowercase: 1,
+ wordUppercase: 3,
+ wordOneNumber: 3,
+ wordThreeNumbers: 5,
+ wordOneSpecialChar: 3,
+ wordTwoSpecialChar: 5,
+ wordUpperLowerCombo: 2,
+ wordLetterNumberCombo: 2,
+ wordLetterNumberCharCombo: 2
+ },
+ rules: {
+ wordNotEmail: true,
+ wordLength: true,
+ wordSimilarToUsername: true,
+ wordLowercase: true,
+ wordUppercase: true,
+ wordOneNumber: true,
+ wordThreeNumbers: true,
+ wordOneSpecialChar: true,
+ wordTwoSpecialChar: true,
+ wordUpperLowerCombo: true,
+ wordLetterNumberCombo: true,
+ wordLetterNumberCharCombo: true
+ },
+ validationRules: {
+ wordNotEmail: function (options, word, score) {
+ return word.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i) && score;
+ },
+ wordLength: function (options, word, score) {
+ var wordlen = word.length,
+ lenScore = Math.pow(wordlen, options.raisePower);
+ if (wordlen < options.minChar) {
+ lenScore = (lenScore + score);
+ options.errors.push(options.errorMessages.password_to_short);
+ }
+ return lenScore;
+ },
+ wordSimilarToUsername: function (options, word, score) {
+ var username = $(options.usernameField).val();
+ if (username && word.toLowerCase().match(username.toLowerCase())) {
+ options.errors.push(options.errorMessages.same_as_username);
+ return score;
+ }
+ return true;
+ },
+ wordLowercase: function (options, word, score) {
+ return word.match(/[a-z]/) && score;
+ },
+ wordUppercase: function (options, word, score) {
+ return word.match(/[A-Z]/) && score;
+ },
+ wordOneNumber : function (options, word, score) {
+ return word.match(/\d+/) && score;
+ },
+ wordThreeNumbers : function (options, word, score) {
+ return word.match(/(.*[0-9].*[0-9].*[0-9])/) && score;
+ },
+ wordOneSpecialChar : function (options, word, score) {
+ return word.match(/.[!,@,#,$,%,\^,&,*,?,_,~]/) && score;
+ },
+ wordTwoSpecialChar : function (options, word, score) {
+ return word.match(/(.*[!,@,#,$,%,\^,&,*,?,_,~].*[!,@,#,$,%,\^,&,*,?,_,~])/) && score;
+ },
+ wordUpperLowerCombo : function (options, word, score) {
+ return word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && score;
+ },
+ wordLetterNumberCombo : function (options, word, score) {
+ return word.match(/([a-zA-Z])/) && word.match(/([0-9])/) && score;
+ },
+ wordLetterNumberCharCombo : function (options, word, score) {
+ return word.match(/([a-zA-Z0-9].*[!,@,#,$,%,\^,&,*,?,_,~])|([!,@,#,$,%,\^,&,*,?,_,~].*[a-zA-Z0-9])/) && score;
+ }
+ }
+ },
+
+ setProgressBar = function ($el, score) {
+ var options = $el.data("pwstrength"),
+ progressbar = options.progressbar.find('.progress-bar'),
+ $verdict;
+
+ if (options.showVerdicts) {
+ if (options.viewports.verdict) {
+ $verdict = $(options.viewports.verdict).find(".password-verdict");
+ } else {
+ $verdict = $el.parent().find(".password-verdict");
+ if ($verdict.length === 0) {
+ $verdict = $('<span class="password-verdict"></span>');
+ $verdict.insertAfter($el);
+ }
+ }
+ }
+
+
+ if (score < options.scores[0]) {
+ progressbar.addClass("progress-bar-danger").removeClass("progress-bar-warning").removeClass("progress-bar-success");
+ progressbar.css("width", "5%");
+ if (options.showVerdicts) {
+ $verdict.text(options.verdicts[0]);
+ }
+ } else if (score >= options.scores[0] && score < options.scores[1]) {
+ progressbar.addClass("progress-bar-danger").removeClass("progress-bar-warning").removeClass("progress-bar-success");
+ progressbar.css("width", "25%");
+ if (options.showVerdicts) {
+ $verdict.text(options.verdicts[1]);
+ }
+ } else if (score >= options.scores[1] && score < options.scores[2]) {
+ progressbar.addClass("progress-bar-warning").removeClass("progress-bar-danger").removeClass("progress-bar-success");
+ progressbar.css("width", "50%");
+ if (options.showVerdicts) {
+ $verdict.text(options.verdicts[2]);
+ }
+ } else if (score >= options.scores[2] && score < options.scores[3]) {
+ progressbar.addClass("progress-bar-warning").removeClass("progress-bar-danger").removeClass("progress-bar-success");
+ progressbar.css("width", "75%");
+ if (options.showVerdicts) {
+ $verdict.text(options.verdicts[3]);
+ }
+ } else if (score >= options.scores[3]) {
+ progressbar.addClass("progress-bar-success").removeClass("progress-bar-warning").removeClass("progress-bar-danger");
+ progressbar.css("width", "100%");
+ if (options.showVerdicts) {
+ $verdict.text(options.verdicts[4]);
+ }
+ }
+ },
+
+ calculateScore = function ($el) {
+ var self = this,
+ word = $el.val(),
+ totalScore = 0,
+ options = $el.data("pwstrength");
+
+ $.each(options.rules, function (rule, active) {
+ if (active === true) {
+ var score = options.ruleScores[rule],
+ result = options.validationRules[rule](options, word, score);
+ if (result) {
+ totalScore += result;
+ }
+ }
+ });
+ setProgressBar($el, totalScore);
+ return totalScore;
+ },
+
+ progressWidget = function () {
+ return '<div class="progress"><div class="progress-bar progress-bar-striped"></div></div>';
+ },
+
+ methods = {
+ init: function (settings) {
+ var self = this,
+ allOptions = $.extend(options, settings);
+
+ return this.each(function (idx, el) {
+ var $el = $(el),
+ progressbar,
+ verdict;
+
+ $el.data("pwstrength", allOptions);
+
+ $el.on("keyup", function (event) {
+ var options = $el.data("pwstrength");
+ options.errors = [];
+ calculateScore.call(self, $el);
+ if ($.isFunction(options.onKeyUp)) {
+ options.onKeyUp(event);
+ }
+ });
+
+ progressbar = $(progressWidget());
+ if (allOptions.viewports.progress) {
+ $(allOptions.viewports.progress).append(progressbar);
+ } else {
+ progressbar.insertAfter($el);
+ }
+ progressbar.find(".bar").css("width", "0%");
+ $el.data("pwstrength").progressbar = progressbar;
+
+ if (allOptions.showVerdicts) {
+ verdict = $('<span class="password-verdict">' + allOptions.verdicts[0] + '</span>');
+ if (allOptions.viewports.verdict) {
+ $(allOptions.viewports.verdict).append(verdict);
+ } else {
+ verdict.insertAfter($el);
+ }
+ }
+
+ if ($.isFunction(allOptions.onLoad)) {
+ allOptions.onLoad();
+ }
+ });
+ },
+
+ destroy: function () {
+ this.each(function (idx, el) {
+ var $el = $(el);
+ $el.parent().find("span.password-verdict").remove();
+ $el.parent().find("div.progress").remove();
+ $el.parent().find("ul.error-list").remove();
+ $el.removeData("pwstrength");
+ });
+ },
+
+ forceUpdate: function () {
+ var self = this;
+ this.each(function (idx, el) {
+ var $el = $(el),
+ options = $el.data("pwstrength");
+ options.errors = [];
+ calculateScore.call(self, $el);
+ });
+ },
+
+ outputErrorList: function () {
+ this.each(function (idx, el) {
+ var output = '<ul class="error-list">',
+ $el = $(el),
+ errors = $el.data("pwstrength").errors,
+ viewports = $el.data("pwstrength").viewports,
+ verdict;
+ $el.parent().find("ul.error-list").remove();
+
+ if (errors.length > 0) {
+ $.each(errors, function (i, item) {
+ output += '<li>' + item + '</li>';
+ });
+ output += '</ul>';
+ if (viewports.errors) {
+ $(viewports.errors).html(output);
+ } else {
+ output = $(output);
+ verdict = $el.parent().find("span.password-verdict");
+ if (verdict.length > 0) {
+ el = verdict;
+ }
+ output.insertAfter(el);
+ }
+ }
+ });
+ },
+
+ addRule: function (name, method, score, active) {
+ this.each(function (idx, el) {
+ var options = $(el).data("pwstrength");
+ options.rules[name] = active;
+ options.ruleScores[name] = score;
+ options.validationRules[name] = method;
+ });
+ },
+
+ changeScore: function (rule, score) {
+ this.each(function (idx, el) {
+ $(el).data("pwstrength").ruleScores[rule] = score;
+ });
+ },
+
+ ruleActive: function (rule, active) {
+ this.each(function (idx, el) {
+ $(el).data("pwstrength").rules[rule] = active;
+ });
+ }
+ };
+
+ $.fn.pwstrength = function (method) {
+ var result;
+ if (methods[method]) {
+ result = methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+ } else if (typeof method === "object" || !method) {
+ result = methods.init.apply(this, arguments);
+ } else {
+ $.error("Method " + method + " does not exist on jQuery.pwstrength");
+ }
+ return result;
+ };
+}(jQuery));
diff --git a/public/js/key.coffee b/public/js/key.coffee
new file mode 100644
index 00000000..f964b0cf
--- /dev/null
+++ b/public/js/key.coffee
@@ -0,0 +1,28 @@
+Key = ->
+ rng = new SecureRandom()
+ bytes = new Array(256)
+ rng.nextBytes(bytes)
+
+ hasher = new jsSHA(bytes.toString(), 'TEXT')
+ rng.nextBytes(bytes)
+
+ I = hasher.getHMAC(bytes.toString(), "TEXT", "SHA-512", "HEX")
+ il = Crypto.util.hexToBytes(I.slice(0, 64))
+ ir = Crypto.util.hexToBytes(I.slice(64, 128))
+
+ key = new BIP32()
+ key.eckey = new Bitcoin.ECKey(il)
+ key.eckey.pub = key.eckey.getPubPoint()
+ key.eckey.setCompressed(true)
+ key.eckey.pubKeyHash = Bitcoin.Util.sha256ripe160(key.eckey.pub.getEncoded(true))
+ key.has_private_key = true
+
+ key.chain_code = ir
+ key.child_index = 0
+ key.parent_fingerprint = Bitcoin.Util.hexToBytes("00000000")
+ key.version = BITCOIN_MAINNET_PRIVATE
+ key.depth = 0
+
+ key.build_extended_public_key()
+ key.build_extended_private_key()
+ return key
diff --git a/public/js/register.coffee b/public/js/register.coffee
index 342cbea3..0e47a794 100644
--- a/public/js/register.coffee
+++ b/public/js/register.coffee
@@ -1,10 +1,35 @@
#= require js/jquery-1.8.2.min.js
#= require js/jquery-ui.min.js
-#= require js/score_password.js
#= require js/check_email.js
+#= require js/check_password.js
+#= require js/jsbn.js
+#= require js/jsbn2.js
+#= require js/crypto-min.js
+#= require js/2.5.3-crypto-sha256.js
+#= require js/sha512.js
+#= require js/rfc1751.js
+#= require js/bitcoinjs-min.js
+#= require js/modsqrt.js
+#= require js/bip32.js
+#= require js/secure_random.js
+#= require js/key.js
+#= require js/aes.js
+g = this
$(->
$('#username').focus()
+ $('#password').pwstrength(showVerdicts: false)
+
+ key = new Key()
+ $('#pubkey').val(key.extended_public_key_string())
+ privkey = key.extended_private_key_string()
+
+ $('#password').keyup((e) ->
+ return if e.keyCode is 9 or e.keyCode is 16
+ enc_privkey = CryptoJS.AES.encrypt(privkey, $(this).val()).toString()
+ enc_privkey = privkey if $(this).val() == ''
+ $('#privkey').val(enc_privkey)
+ )
$('#username').blur(->
$(this).parent().next('.alert').remove()
@@ -19,13 +44,11 @@ $(->
$('#password').blur(->
$('#confirm').blur()
$(this).parent().next('.alert').remove()
- score = scorePassword($(this).val())
- if score > 40
+ if $('.progress-bar-success').length > 0
$(this).parent().removeClass('has-error')
else
$(this).parent().addClass('has-error')
- $(this).parent().after('<div class="alert alert-danger">Weak password</div>')
)
$('#confirm').blur(->
diff --git a/public/js/setup.coffee b/public/js/setup.coffee
index 272e2159..8348aaf4 100644
--- a/public/js/setup.coffee
+++ b/public/js/setup.coffee
@@ -2,19 +2,19 @@
#= require ../js/jquery-ui.min.js
#= require ../js/jquery.printElement.min.js
#= require ../js/bootstrap.min.js
-#= require ../js/crypto-min.js
-#= require ../js/2.5.3-crypto-sha256.js
#= require ../js/jsbn.js
#= require ../js/jsbn2.js
-#= require ../js/check_address.js
-#= require ../js/bitcoinjs-min.js
+#= require ../js/crypto-min.js
+#= require ../js/2.5.3-crypto-sha256.js
#= require ../js/sha512.js
-#= require ../js/modsqrt.js
#= require ../js/rfc1751.js
+#= require ../js/bitcoinjs-min.js
+#= require ../js/modsqrt.js
#= require ../js/bip32.js
#= require ../js/secure_random.js
#= require ../js/qrcode.js
#= require ../js/aes.js
+#= require ../js/key.js
g = exports ? this
g.proceed = false
@@ -51,7 +51,7 @@ $(->
$.getJSON("/#{user}.json", (data) ->
$('#title').val(data.title)
$('#logo').val(data.logo)
- $('#bip32').val(data.bip32)
+ $('#pubkey').val(data.pubkey)
$('#address').val(data.address)
$("#symbol option[value='#{data.symbol}']").attr('selected', 'selected')
$('#commission').val(data.commission)
@@ -74,7 +74,7 @@ $(->
$(this).parent().removeClass('has-error')
)
- $('#bip32').blur(->
+ $('#pubkey').blur(->
try
new BIP32($(this).val())
$(this).parent().removeClass('has-error')
@@ -83,33 +83,7 @@ $(->
)
$('#generate').click(->
- rng = new SecureRandom()
- bytes = new Array(256)
- rng.nextBytes(bytes)
-
- hasher = new jsSHA(bytes.toString(), 'TEXT')
- rng.nextBytes(bytes)
-
- I = hasher.getHMAC(bytes.toString(), "TEXT", "SHA-512", "HEX")
- il = Crypto.util.hexToBytes(I.slice(0, 64))
- ir = Crypto.util.hexToBytes(I.slice(64, 128))
-
- key = new BIP32()
- key.eckey = new Bitcoin.ECKey(il)
- key.eckey.pub = key.eckey.getPubPoint()
- key.eckey.setCompressed(true)
- key.eckey.pubKeyHash = Bitcoin.Util.sha256ripe160(key.eckey.pub.getEncoded(true))
- key.has_private_key = true
-
- key.chain_code = ir
- key.child_index = 0
- key.parent_fingerprint = Bitcoin.Util.hexToBytes("00000000")
- key.version = BITCOIN_MAINNET_PRIVATE
- key.depth = 0
-
- key.build_extended_public_key()
- key.build_extended_private_key()
-
+ key = new Key()
g.pubkey = key.extended_public_key_string()
g.privkey = key.extended_private_key_string()
@@ -186,7 +160,7 @@ $(->
if $('.tab-pane:eq(2)').hasClass('active')
$('a[data-toggle="tab"]:eq(1)').click()
).on('hidden.bs.modal', ->
- $('#bip32').val(g.pubkey) if g.update_pub_key
+ $('#pubkey').val(g.pubkey) if g.update_pub_key
)
$('#setup').submit(->
diff --git a/routes/sessions.js b/routes/sessions.js
index 38ae74b1..d01dc4f1 100644
--- a/routes/sessions.js
+++ b/routes/sessions.js
@@ -30,11 +30,12 @@
});
}
return req.login(user, function(err) {
- var url;
+ var re, url;
if (err) {
return next(err);
}
- if (req.session.redirect != null) {
+ re = new RegExp(user.username, 'g');
+ if ((req.session.redirect != null) && re.test(req.session.redirect)) {
url = req.session.redirect;
}
if (url == null) {
diff --git a/routes/users.js b/routes/users.js
index 1bffc7fb..47562df4 100644
--- a/routes/users.js
+++ b/routes/users.js
@@ -83,60 +83,63 @@
userkey = "user:" + req.body.username;
return db.hgetall(userkey, function(err, obj) {
if (obj) {
- return res.redirect(req.body.username);
- } else {
- if (req.body.confirm !== req.body.password) {
- errormsg += "Passwords must match";
- return res.render('users/new', {
- layout: 'layout',
- js: (function() {
- return global.js;
- }),
- css: (function() {
- return global.css;
- }),
- error: errormsg
- });
- }
- bcrypt.hash(req.body.password, 12, function(err, hash) {
- db.sadd("users", userkey);
- return db.hmset(userkey, {
- username: req.body.username,
- password: hash,
- email: req.body.email
- }, function() {
- req.session.redirect = "/" + req.body.username + "/edit";
- return sessions.create(req, res);
- });
+ errormsg += "Username exists";
+ }
+ if (req.body.confirm !== req.body.password) {
+ errormsg += "Passwords must match";
+ }
+ if (errormsg) {
+ return res.render('users/new', {
+ layout: 'layout',
+ js: (function() {
+ return global.js;
+ }),
+ css: (function() {
+ return global.css;
+ }),
+ error: errormsg
+ });
+ }
+ bcrypt.hash(req.body.password, 12, function(err, hash) {
+ db.sadd("users", userkey);
+ return db.hmset(userkey, {
+ username: req.body.username,
+ password: hash,
+ email: req.body.email,
+ pubkey: req.body.pubkey,
+ privkey: req.body.privkey
+ }, function() {
+ req.session.redirect = "/" + req.body.username + "/edit";
+ return sessions.create(req, res);
});
- return require('crypto').randomBytes(48, function(ex, buf) {
- var token, url;
- token = buf.toString('base64').replace(/\//g, '').replace(/\+/g, '');
- db.set(token, req.body.username);
- url = "" + req.protocol + "://" + req.hostname + ":3000/verify/" + token;
- return res.render('users/welcome', {
- user: req.params.user,
- layout: 'mail',
- url: url,
- js: (function() {
- return global.js;
- }),
- css: (function() {
- return global.css;
- })
- }, function(err, html) {
- var email, sendgrid;
- sendgrid = require('sendgrid')(config.sendgrid_user, config.sendgrid_password);
- email = new sendgrid.Email({
- to: req.body.email,
- subject: 'Welcome to CoinOS',
- html: html
- });
- return sendgrid.send(email);
+ });
+ return require('crypto').randomBytes(48, function(ex, buf) {
+ var token, url;
+ token = buf.toString('base64').replace(/\//g, '').replace(/\+/g, '');
+ db.set(token, req.body.username);
+ url = "" + req.protocol + "://" + req.hostname + ":3000/verify/" + token;
+ return res.render('users/welcome', {
+ user: req.params.user,
+ layout: 'mail',
+ url: url,
+ js: (function() {
+ return global.js;
+ }),
+ css: (function() {
+ return global.css;
+ })
+ }, function(err, html) {
+ var email, sendgrid;
+ sendgrid = require('sendgrid')(config.sendgrid_user, config.sendgrid_password);
+ email = new sendgrid.Email({
+ to: req.body.email,
+ subject: 'Welcome to CoinOS',
+ html: html
});
+ return sendgrid.send(email);
});
- }
+ });
});
},
edit: function(req, res) {
diff --git a/src/routes/sessions.coffee b/src/routes/sessions.coffee
index 30d3cdef..5b1d9f06 100644
--- a/src/routes/sessions.coffee
+++ b/src/routes/sessions.coffee
@@ -21,7 +21,10 @@ module.exports = (passport) ->
if (err)
return next(err)
- url = req.session.redirect if req.session.redirect?
+ re = new RegExp(user.username, 'g')
+ if req.session.redirect? and re.test(req.session.redirect)
+ url = req.session.redirect
+
url ?= "/#{user.username}"
delete req.session.redirect
return res.redirect(url)
diff --git a/src/routes/users.coffee b/src/routes/users.coffee
index 91654391..dc22303d 100644
--- a/src/routes/users.coffee
+++ b/src/routes/users.coffee
@@ -56,53 +56,57 @@ module.exports = (sessions) ->
userkey = "user:"+req.body.username
db.hgetall(userkey, (err, obj) ->
if obj
- res.redirect(req.body.username)
- else
- if req.body.confirm != req.body.password
- errormsg += "Passwords must match"
- return res.render('users/new',
- layout: 'layout',
- js: (-> global.js),
- css: (-> global.css),
- error: errormsg
- )
+ errormsg += "Username exists"
- bcrypt.hash(req.body.password, 12, (err, hash) ->
- db.sadd("users",userkey)
- db.hmset(userkey,
- username: req.body.username,
- password: hash,
- email: req.body.email
- , ->
- req.session.redirect = "/#{req.body.username}/edit"
- sessions.create(req, res)
- )
+ if req.body.confirm != req.body.password
+ errormsg += "Passwords must match"
+
+ if errormsg
+ return res.render('users/new',
+ layout: 'layout',
+ js: (-> global.js),
+ css: (-> global.css),
+ error: errormsg
)
- require('crypto').randomBytes(48, (ex, buf) ->
- token = buf.toString('base64').replace(/\//g,'').replace(/\+/g,'')
- db.set(token, req.body.username)
- url = "#{req.protocol}://#{req.hostname}:3000/verify/#{token}"
+ bcrypt.hash(req.body.password, 12, (err, hash) ->
+ db.sadd("users",userkey)
+ db.hmset(userkey,
+ username: req.body.username,
+ password: hash,
+ email: req.body.email,
+ pubkey: req.body.pubkey,
+ privkey: req.body.privkey
+ , ->
+ req.session.redirect = "/#{req.body.username}/edit"
+ sessions.create(req, res)
+ )
+ )
+
+ require('crypto').randomBytes(48, (ex, buf) ->
+ token = buf.toString('base64').replace(/\//g,'').replace(/\+/g,'')
+ db.set(token, req.body.username)
+ url = "#{req.protocol}://#{req.hostname}:3000/verify/#{token}"
- res.render('users/welcome',
- user: req.params.user,
- layout: 'mail',
- url: url,
- js: (-> global.js),
- css: (-> global.css),
- (err, html) ->
- sendgrid = require('sendgrid')(config.sendgrid_user, config.sendgrid_password)
+ res.render('users/welcome',
+ user: req.params.user,
+ layout: 'mail',
+ url: url,
+ js: (-> global.js),
+ css: (-> global.css),
+ (err, html) ->
+ sendgrid = require('sendgrid')(config.sendgrid_user, config.sendgrid_password)
- email = new sendgrid.Email(
- to: req.body.email
- subject: 'Welcome to CoinOS'
- html: html
- )
+ email = new sendgrid.Email(
+ to: req.body.email
+ subject: 'Welcome to CoinOS'
+ html: html
+ )
- sendgrid.send(email)
- )
+ sendgrid.send(email)
)
+ )
)
edit: (req, res) ->
diff --git a/views/users/edit.html b/views/users/edit.html
index a4ba131d..9307e52c 100644
--- a/views/users/edit.html
+++ b/views/users/edit.html
@@ -18,11 +18,11 @@
</div>
<div class="form-group">
- <label for="bip32">Extended key:</label>
+ <label for="pubkey">Public Key:</label>
<div class="input-group">
- <input type="text" id="bip32" name="bip32" class="form-control" placeholder="xpub..." />
+ <input type="text" id="pubkey" name="pubkey" class="form-control" placeholder="xpub..." />
<span class="input-group-btn">
- <button id="generate" type="button" class="btn">Generate</button>
+ <button id="generate" type="button" class="btn">New</button>
</span>
</div>
</div>
@@ -40,7 +40,7 @@
</div>
<div class="form-group">
- <label for="commission">Commission / Discount:</label>
+ <label for="commission">Commission (+) / Discount (-) %:</label>
<input type="text" id="commission" name="commission" class="form-control" />
</div>
diff --git a/views/users/new.html b/views/users/new.html
index bf8b3b7d..ab3a9edd 100644
--- a/views/users/new.html
+++ b/views/users/new.html
@@ -20,14 +20,21 @@
</div>
<div class="form-group">
- <label for="password">Password:</label>
+ <label for="password">Passphrase:</label>
<input type="password" id="password" name="password" class="form-control" />
+ <div id="messages"></div>
</div>
<div class="form-group">
- <label for="confirm">Confirm Password:</label>
+ <label for="confirm">Confirm Passphrase:</label>
<input type="password" id="confirm" name="confirm" class="form-control" />
</div>
+ <input id="pubkey" name="pubkey" type="hidden" />
+ <input id="privkey" name="privkey" type="hidden" />
+
<input class="btn btn-primary" type="submit" value="Register" />
</form>
+
+<div id="qr"></div>
+