From 5e6ec1f0ff132af2a539fc9a84551326dab162ee Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 16 Sep 2015 20:46:36 -0700 Subject: Don't detect static asset changes --- src/app.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/app.coffee b/src/app.coffee index 1ea1d2cf..3208ae49 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -89,7 +89,7 @@ app.get('/:user/report', authorize, transactions.index) app.get('/:user.json', users.json) app.get('/:user', cache, users.show) -app.use(require('connect-assets')(src: 'public')) +app.use(require('connect-assets')(src: 'public', detectChanges: false)) app.use((err, req, res, next) -> res.status(500) -- cgit v1.2.3 From 59528d7c0a301c805b03bf77492e489c0e723e79 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 6 Nov 2015 12:56:12 -0800 Subject: Bitcoin tips page --- app.js | 17 +++++++++++++++-- src/app.coffee | 10 ++++++++++ views/tips.html | 11 +++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 views/tips.html (limited to 'src') diff --git a/app.js b/app.js index c82f895e..dab0d431 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,5 @@ (function() { - var RedisStore, app, authorize, bodyParser, cache, calculator, config, cookieParser, express, fetchRates, fs, passport, path, request, session, sessionStore, sessions, transactions, users; + var RedisStore, app, authorize, bodyParser, cache, calculator, config, cookieParser, express, fetchRates, fs, passport, path, request, session, sessionStore, sessions, tips, transactions, users; request = require('request'); @@ -103,7 +103,7 @@ return setTimeout(fetchRates, 120000); })(); - app.get('/', cache, sessions["new"]); + tips = app.get('/', cache, sessions["new"]); app.get('/register', cache, users["new"]); @@ -113,6 +113,19 @@ app.get('/address', cache, calculator.address); + app.get('/tips', cache, function(req, res) { + return res.render('tips', { + notice: true, + layout: 'layout', + js: (function() { + return global.js; + }), + css: (function() { + return global.css; + }) + }); + }); + app.get('/login', cache, sessions["new"]); app.post('/login', sessions.create); diff --git a/src/app.coffee b/src/app.coffee index 3208ae49..f62b7696 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -62,11 +62,21 @@ do fetchRates = -> ) setTimeout(fetchRates, 120000) +tips = + app.get('/', cache, sessions.new) app.get('/register', cache, users.new) app.get('/ticker', cache, calculator.ticker) app.get('/sweep', calculator.sweep) app.get('/address', cache, calculator.address) +app.get('/tips', cache, (req, res) -> + res.render('tips', + notice: true, + layout: 'layout', + js: (-> global.js), + css: (-> global.css) + ) +) app.get('/login', cache, sessions.new) app.post('/login', sessions.create) diff --git a/views/tips.html b/views/tips.html new file mode 100644 index 00000000..a4ac19ba --- /dev/null +++ b/views/tips.html @@ -0,0 +1,11 @@ +

Congratulations

+ +

+If you're here, you've probably received a Bitcoin tip from me. I've created a short YouTube video to explain what to do next and show how you can create your own paper wallets. Enjoy, and if you have any questions, don't hesitate to contact me!

+ +

+-Adam Soltys
+asoltys@gmail.com +

+ + -- cgit v1.2.3 From c1cd55151fdea2bd80e27a6a9dfc905a243dd379 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 11 Nov 2015 13:25:35 -0800 Subject: Fetch remote image files and store locally --- .gitignore | 2 +- public/assets/img/logos/yummyyards.png | Bin 0 -> 22968 bytes public/js/calculator.coffee | 4 +++- routes/users.js | 17 +++++++++++++++-- src/routes/users.coffee | 10 ++++++++++ 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 public/assets/img/logos/yummyyards.png (limited to 'src') diff --git a/.gitignore b/.gitignore index 2391f700..ca800b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -public/bitcoins.pdf node_modules builtAssets database.json @@ -9,3 +8,4 @@ src/config.coffee config.js passenger* tmp +public/img/assets/logos diff --git a/public/assets/img/logos/yummyyards.png b/public/assets/img/logos/yummyyards.png new file mode 100644 index 00000000..e8f59c9f Binary files /dev/null and b/public/assets/img/logos/yummyyards.png differ diff --git a/public/js/calculator.coffee b/public/js/calculator.coffee index cc2dcece..cc45cae5 100644 --- a/public/js/calculator.coffee +++ b/public/js/calculator.coffee @@ -59,7 +59,9 @@ setup = -> $('#title').html("#{g.user.title}").show() if g.user.logo - $('#logo').attr('src', g.user.logo).show() + ext = g.user.logo.substr(g.user.logo.length - 3) + src = "/assets/img/logos/#{g.user.username}.#{ext}" + $('#logo').attr('src', src).show() getAddress() diff --git a/routes/users.js b/routes/users.js index c5e0f0ee..28b89797 100644 --- a/routes/users.js +++ b/routes/users.js @@ -1,5 +1,5 @@ (function() { - var bcrypt, config, db; + var bcrypt, config, db, fs, request; db = require("../redis"); @@ -7,6 +7,10 @@ bcrypt = require('bcrypt'); + fs = require('fs'); + + request = require('request'); + module.exports = function(sessions) { return { exists: function(req, res) { @@ -34,7 +38,7 @@ }, show: function(req, res) { return db.hgetall("user:" + req.params.user, function(err, obj) { - var options; + var ext, options, path; if (obj) { options = { user: req.params.user, @@ -50,6 +54,15 @@ if (req.query.verified != null) { options.verified = true; } + if (obj.logo.length > 3) { + ext = obj.logo.substr(obj.logo.length - 3); + path = "public/assets/img/logos/" + obj.username + "." + ext; + fs.lstat(path, function(err, stats) { + if ((ext === 'jpg' || ext === 'png' || ext === 'gif') && (err || !stats.isFile())) { + return request("" + obj.logo).pipe(fs.createWriteStream(path)); + } + }); + } res.render('users/show', options); return delete req.session.verified; } else { diff --git a/src/routes/users.coffee b/src/routes/users.coffee index d3ecabaf..b1e4fd9a 100644 --- a/src/routes/users.coffee +++ b/src/routes/users.coffee @@ -1,6 +1,8 @@ db = require("../redis") config = require("../config") bcrypt = require('bcrypt') +fs = require('fs') +request = require('request') module.exports = (sessions) -> exists: (req, res) -> @@ -33,6 +35,14 @@ module.exports = (sessions) -> if req.query.verified? options.verified = true + if obj.logo.length > 3 + ext = obj.logo.substr(obj.logo.length - 3) + path = "public/assets/img/logos/#{obj.username}.#{ext}" + fs.lstat(path, (err, stats) -> + if ext in ['jpg', 'png', 'gif'] and (err or not stats.isFile()) + request("#{obj.logo}").pipe(fs.createWriteStream(path)) + ) + res.render('users/show', options) delete req.session.verified else -- cgit v1.2.3 From a50564c1e992bb17af3d06af4e7ea44da5bc5595 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 11 Nov 2015 20:19:19 -0800 Subject: Move address management to separate wallet page --- app.js | 16 +++--- public/js/setup.coffee | 104 ---------------------------------- public/js/wallet.coffee | 144 +++++++++++++++++++++++++++++++++++++++++++++++ routes/users.js | 15 ++++- src/app.coffee | 11 ++-- src/routes/users.coffee | 11 +++- views/layout.html | 5 +- views/users/edit.html | 70 +---------------------- views/users/profile.html | 2 +- views/users/wallet.html | 78 +++++++++++++++++++++++++ 10 files changed, 266 insertions(+), 190 deletions(-) create mode 100644 public/js/wallet.coffee create mode 100644 views/users/wallet.html (limited to 'src') diff --git a/app.js b/app.js index dab0d431..5f381065 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,5 @@ (function() { - var RedisStore, app, authorize, bodyParser, cache, calculator, config, cookieParser, express, fetchRates, fs, passport, path, request, session, sessionStore, sessions, tips, transactions, users; + var RedisStore, app, authorize, bodyParser, cache, calculator, config, cookieParser, express, fetchRates, fs, passport, path, request, session, sessionStore, sessions, transactions, users; request = require('request'); @@ -103,15 +103,15 @@ return setTimeout(fetchRates, 120000); })(); - tips = app.get('/', cache, sessions["new"]); + app.get('/', cache, sessions["new"]); - app.get('/register', cache, users["new"]); + app.get('/address', cache, calculator.address); - app.get('/ticker', cache, calculator.ticker); + app.get('/register', cache, users["new"]); app.get('/sweep', calculator.sweep); - app.get('/address', cache, calculator.address); + app.get('/ticker', cache, calculator.ticker); app.get('/tips', cache, function(req, res) { return res.render('tips', { @@ -138,11 +138,13 @@ app.get('/verify/:token', users.verify); - app.get('/:user/profile', authorize, users.profile); + app.post('/:user', authorize, users.update); app.get('/:user/edit', authorize, users.edit); - app.post('/:user', authorize, users.update); + app.get('/:user/profile', authorize, users.profile); + + app.get('/:user/wallet', authorize, users.wallet); app.get('/:user/transactions.json', authorize, transactions.json); diff --git a/public/js/setup.coffee b/public/js/setup.coffee index 465cfb39..01705cdd 100644 --- a/public/js/setup.coffee +++ b/public/js/setup.coffee @@ -56,7 +56,6 @@ $(-> $('#email').val(data.email) $('#title').val(data.title) $('#logo').val(data.logo) - $('#pubkey').val(data.pubkey) $('#address').val(data.address) $("#symbol option[value='#{data.symbol}']").attr('selected', 'selected') $('#commission').val(data.commission) @@ -72,96 +71,6 @@ $(-> $('#unit').append("") ) - $('#pubkey').blur(-> - if check_address($(this).val()) - $(this).parent().removeClass('has-error') - else - $(this).parent().addClass('has-error') - ) - - $('#generate').click(-> - key = new Key() - g.pubkey = key.extended_public_key_string() - g.privkey = key.extended_private_key_string() - - $('#modal').modal() - $('#privkey_text').html(g.privkey) - $('#qr').html('') - new QRCode('qr', text: g.privkey, width: 260, height: 260) - ) - - $('#encryption-password').keyup((e) -> - return if e.keyCode is 9 or e.keyCode is 16 - g.enc_privkey = CryptoJS.AES.encrypt(g.privkey, $(this).val()).toString() - g.enc_privkey = g.privkey if $(this).val() == '' - $('#privkey_text').html(g.enc_privkey) - $('#qr').html('') - new QRCode('qr', text: g.enc_privkey, width: 260, height: 260) - - if $(this).val() - $('#status').html('(Encrypted)') - else - $('#status').html('(Unencrypted)') - ) - - $('#confirm').blur(-> - $('#confirm_error').remove() - if $('#password').val() != $('#confirm').val() - $('#password, #confirm').parent().addClass('has-error') - $('#confirm').parent().after('
Passwords don\'t match
') - else - $('#password, #confirm').parent().removeClass('has-error') - ) - - $('#encryption-password, #encryption-confirm').keyup((e) -> check_passwords(e) unless e.keyCode is 9) - $('#encryption-password, #encryption-confirm').blur((e) -> check_passwords(e)) - - check_passwords = (e) -> - if $('#encryption-password').val() != $('#encryption-confirm').val() or $('#encryption-password').val() is '' - $('#encryption-password, #encryption-confirm').parent().addClass('has-error') - $('#modal .alert').removeClass('alert-success').addClass('alert-danger') - else - $('#encryption-password, #encryption-confirm').parent().removeClass('has-error') - $('#modal .alert').removeClass('alert-danger').addClass('alert-success') - - if $('.progress-bar-success').length > 0 - $('#encryption-password').parent().removeClass('has-error') - else - $('#encryption-password').parent().addClass('has-error') - - $('#print').click(-> - $('#key-dialog').printElement(printMode: 'popup') - ) - - $('a[data-toggle="tab"]').on('shown.bs.tab', (e) -> - $('#print').toggle(e.target.attributes.href.value == '#step1') - ) - - $('#close').click(-> - $('#modal .form-control').blur() - if $('#modal .has-error').length > 0 - $('#step1_link').click() - $('#modal .has-error').effect('shake', 500) - else - g.update_key = true - $('#modal').modal('hide') - ) - $('#encrypt').submit(-> $('#close').click(); return false) - - $('#modal').on('show.bs.modal', -> - $('#encryption-password, #encryption-confirm').val('').keyup().parent().removeClass('has-error') - $('#modal .alert').removeClass('alert-success').addClass('alert-danger') - ) - - $('#modal').on('shown.bs.modal', -> - g.update_key = false - $('#encryption-password').focus() - ).on('hidden.bs.modal', -> - if g.update_key - $('#pubkey').val(g.pubkey) - $('#privkey').val(g.enc_privkey) - ) - $('#setup').submit(-> $('#setup .form-control').blur() if $('#setup .has-error').length > 0 @@ -170,16 +79,3 @@ $(-> ) ) -check_address = (address) -> - try - bitcoin.Address.fromBase58Check(address) - return true - catch - return isBip32(address) - -isBip32 = (address) -> - try - new BIP32(address) - return true - catch - return false diff --git a/public/js/wallet.coffee b/public/js/wallet.coffee new file mode 100644 index 00000000..8ced085f --- /dev/null +++ b/public/js/wallet.coffee @@ -0,0 +1,144 @@ +#= require ../js/jquery-1.8.2.min.js +#= require ../js/jquery-ui.min.js +#= require ../js/jquery.printElement.min.js +#= require ../js/check_password.js +#= require ../js/bootstrap.min.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-1.0.2.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 + +$(-> + $('#encryption-password').pwstrength(showVerdicts: false) + + user = $('#username').val() + $.getJSON("/#{user}.json", (data) -> + $('#pubkey').val(data.pubkey) + $('#address').val(data.address) + $('#setup').fadeIn() + ) + + $('#pubkey').blur(-> + if check_address($(this).val()) + $(this).parent().removeClass('has-error') + else + $(this).parent().addClass('has-error') + ) + + $('#generate').click(-> + key = new Key() + g.pubkey = key.extended_public_key_string() + g.privkey = key.extended_private_key_string() + + $('#modal').modal() + $('#privkey_text').html(g.privkey) + $('#qr').html('') + new QRCode('qr', text: g.privkey, width: 260, height: 260) + ) + + $('#encryption-password').keyup((e) -> + return if e.keyCode is 9 or e.keyCode is 16 + g.enc_privkey = CryptoJS.AES.encrypt(g.privkey, $(this).val()).toString() + g.enc_privkey = g.privkey if $(this).val() == '' + $('#privkey_text').html(g.enc_privkey) + $('#qr').html('') + new QRCode('qr', text: g.enc_privkey, width: 260, height: 260) + + if $(this).val() + $('#status').html('(Encrypted)') + else + $('#status').html('(Unencrypted)') + ) + + $('#confirm').blur(-> + $('#confirm_error').remove() + if $('#password').val() != $('#confirm').val() + $('#password, #confirm').parent().addClass('has-error') + $('#confirm').parent().after('
Passwords don\'t match
') + else + $('#password, #confirm').parent().removeClass('has-error') + ) + + $('#encryption-password, #encryption-confirm').keyup((e) -> check_passwords(e) unless e.keyCode is 9) + $('#encryption-password, #encryption-confirm').blur((e) -> check_passwords(e)) + + check_passwords = (e) -> + if $('#encryption-password').val() != $('#encryption-confirm').val() or $('#encryption-password').val() is '' + $('#encryption-password, #encryption-confirm').parent().addClass('has-error') + $('#modal .alert').removeClass('alert-success').addClass('alert-danger') + else + $('#encryption-password, #encryption-confirm').parent().removeClass('has-error') + $('#modal .alert').removeClass('alert-danger').addClass('alert-success') + + if $('.progress-bar-success').length > 0 + $('#encryption-password').parent().removeClass('has-error') + else + $('#encryption-password').parent().addClass('has-error') + + $('#print').click(-> + $('#key-dialog').printElement(printMode: 'popup') + ) + + $('a[data-toggle="tab"]').on('shown.bs.tab', (e) -> + $('#print').toggle(e.target.attributes.href.value == '#step1') + ) + + $('#close').click(-> + $('#modal .form-control').blur() + if $('#modal .has-error').length > 0 + $('#step1_link').click() + $('#modal .has-error').effect('shake', 500) + else + g.update_key = true + $('#modal').modal('hide') + ) + $('#encrypt').submit(-> $('#close').click(); return false) + + $('#modal').on('show.bs.modal', -> + $('#encryption-password, #encryption-confirm').val('').keyup().parent().removeClass('has-error') + $('#modal .alert').removeClass('alert-success').addClass('alert-danger') + ) + + $('#modal').on('shown.bs.modal', -> + g.update_key = false + $('#encryption-password').focus() + ).on('hidden.bs.modal', -> + if g.update_key + $('#pubkey').val(g.pubkey) + $('#privkey').val(g.enc_privkey) + ) + + $('#setup').submit(-> + $('#setup .form-control').blur() + if $('#setup .has-error').length > 0 + $('#setup .has-error').effect('shake', 500) + return false + ) +) + +check_address = (address) -> + try + bitcoin.Address.fromBase58Check(address) + return true + catch + return isBip32(address) + +isBip32 = (address) -> + try + new BIP32(address) + return true + catch + return false diff --git a/routes/users.js b/routes/users.js index 28b89797..36914152 100644 --- a/routes/users.js +++ b/routes/users.js @@ -54,7 +54,7 @@ if (req.query.verified != null) { options.verified = true; } - if (obj.logo.length > 3) { + if (obj.logo && obj.logo.length > 3) { ext = obj.logo.substr(obj.logo.length - 3); path = "public/assets/img/logos/" + obj.username + "." + ext; fs.lstat(path, function(err, stats) { @@ -243,6 +243,19 @@ }); } }); + }, + wallet: function(req, res) { + return res.render('users/wallet', { + user: req.params.user, + layout: 'layout', + navigation: true, + js: (function() { + return global.js; + }), + css: (function() { + return global.css; + }) + }); } }; }; diff --git a/src/app.coffee b/src/app.coffee index f62b7696..554ef303 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -62,13 +62,11 @@ do fetchRates = -> ) setTimeout(fetchRates, 120000) -tips = - app.get('/', cache, sessions.new) +app.get('/address', cache, calculator.address) app.get('/register', cache, users.new) -app.get('/ticker', cache, calculator.ticker) app.get('/sweep', calculator.sweep) -app.get('/address', cache, calculator.address) +app.get('/ticker', cache, calculator.ticker) app.get('/tips', cache, (req, res) -> res.render('tips', notice: true, @@ -86,9 +84,10 @@ app.get('/users/new', cache, users.new) app.post('/users', users.create) app.get('/verify/:token', users.verify) -app.get('/:user/profile', authorize, users.profile) -app.get('/:user/edit', authorize, users.edit) app.post('/:user', authorize, users.update) +app.get('/:user/edit', authorize, users.edit) +app.get('/:user/profile', authorize, users.profile) +app.get('/:user/wallet', authorize, users.wallet) app.get('/:user/transactions.json', authorize, transactions.json) app.post('/:user/transactions', transactions.create) diff --git a/src/routes/users.coffee b/src/routes/users.coffee index b1e4fd9a..014b74b3 100644 --- a/src/routes/users.coffee +++ b/src/routes/users.coffee @@ -35,7 +35,7 @@ module.exports = (sessions) -> if req.query.verified? options.verified = true - if obj.logo.length > 3 + if obj.logo and obj.logo.length > 3 ext = obj.logo.substr(obj.logo.length - 3) path = "public/assets/img/logos/#{obj.username}.#{ext}" fs.lstat(path, (err, stats) -> @@ -192,3 +192,12 @@ module.exports = (sessions) -> res.redirect("/#{reply.toString()}?verified") ) ) + + wallet: (req, res) -> + res.render('users/wallet', + user: req.params.user, + layout: 'layout', + navigation: true, + js: (-> global.js), + css: (-> global.css) + ) diff --git a/views/layout.html b/views/layout.html index 5be45ded..e63e3c47 100644 --- a/views/layout.html +++ b/views/layout.html @@ -20,8 +20,9 @@