diff --git a/public/javascripts/app.js b/public/javascripts/app.js index 0c2317d..2a0fa8c 100644 --- a/public/javascripts/app.js +++ b/public/javascripts/app.js @@ -18,6 +18,27 @@ jQuery(function($) { } } + $('#card-num').payment('formatCardNumber'); + + var validateDetails = function() { + // set variables for the expiry date validation, cvc validation and expiry date 'splitter' + var cardNum = $('#card-num'); + var validateNumber = $.payment.validateCardNumber(cardNum.val()); + if (validateNumber) { + // if the cvc is valid add the identified class + cardNum.closest('.form-group').addClass('has-success').removeClass('has-error'); + } else { + // remove again if the cvc becomes invalid + cardNum.closest('.form-group').addClass('has-error').removeClass('has-success'); + } + + } + // this runs the above function every time stuff is entered into the card inputs + $('.paymentInput').bind('change paste keyup', function() { + validateDetails(); + }); + + cardForm.submit(function(e) { e.preventDefault(); @@ -55,5 +76,4 @@ jQuery(function($) { return false; } }); - -}); \ No newline at end of file +}); diff --git a/public/javascripts/jquery.payment.min.js b/public/javascripts/jquery.payment.min.js new file mode 100644 index 0000000..5fdbb84 --- /dev/null +++ b/public/javascripts/jquery.payment.min.js @@ -0,0 +1,26 @@ +/* +Copyright (c) 2014 Stripe + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +jQuery payment by Stripe https://github.com/stripe/jquery.payment +*/ +(function(){var t,e,n,r,a,o,i,u,l,c,h,s,p,g,v,f,d,m,y,C,T,w=[].slice,D=[].indexOf||function(t){for(var e=0,n=this.length;n>e;e++)if(e in this&&this[e]===t)return e;return-1};$.payment={},$.payment.fn={},$.fn.payment=function(){var t,e;return e=arguments[0],t=2<=arguments.length?w.call(arguments,1):[],$.payment.fn[e].apply(this,t)},r=/(\d{1,4})/g,$.payment.cards=n=[{type:"visaelectron",pattern:/^4(026|17500|405|508|844|91[37])/,format:r,length:[16],cvcLength:[3],luhn:!0},{type:"maestro",pattern:/^(5(018|0[23]|[68])|6(39|7))/,format:r,length:[12,13,14,15,16,17,18,19],cvcLength:[3],luhn:!0},{type:"forbrugsforeningen",pattern:/^600/,format:r,length:[16],cvcLength:[3],luhn:!0},{type:"dankort",pattern:/^5019/,format:r,length:[16],cvcLength:[3],luhn:!0},{type:"visa",pattern:/^4/,format:r,length:[13,16],cvcLength:[3],luhn:!0},{type:"mastercard",pattern:/^5[0-5]/,format:r,length:[16],cvcLength:[3],luhn:!0},{type:"amex",pattern:/^3[47]/,format:/(\d{1,4})(\d{1,6})?(\d{1,5})?/,length:[15],cvcLength:[3,4],luhn:!0},{type:"dinersclub",pattern:/^3[0689]/,format:r,length:[14],cvcLength:[3],luhn:!0},{type:"discover",pattern:/^6([045]|22)/,format:r,length:[16],cvcLength:[3],luhn:!0},{type:"unionpay",pattern:/^(62|88)/,format:r,length:[16,17,18,19],cvcLength:[3],luhn:!1},{type:"jcb",pattern:/^35/,format:r,length:[16],cvcLength:[3],luhn:!0}],t=function(t){var e,r,a;for(t=(t+"").replace(/\D/g,""),r=0,a=n.length;a>r;r++)if(e=n[r],e.pattern.test(t))return e},e=function(t){var e,r,a;for(r=0,a=n.length;a>r;r++)if(e=n[r],e.type===t)return e},s=function(t){var e,n,r,a,o,i;for(r=!0,a=0,n=(t+"").split("").reverse(),o=0,i=n.length;i>o;o++)e=n[o],e=parseInt(e,10),(r=!r)&&(e*=2),e>9&&(e-=9),a+=e;return a%10===0},h=function(t){var e;return null!=t.prop("selectionStart")&&t.prop("selectionStart")!==t.prop("selectionEnd")?!0:null!=("undefined"!=typeof document&&null!==document&&null!=(e=document.selection)?e.createRange:void 0)&&document.selection.createRange().text?!0:!1},f=function(t){return setTimeout(function(){var e,n;return e=$(t.currentTarget),n=e.val(),n=n.replace(/\D/g,""),e.val(n)})},g=function(t){return setTimeout(function(){var e,n;return e=$(t.currentTarget),n=e.val(),n=$.payment.formatCardNumber(n),e.val(n)})},i=function(e){var n,r,a,o,i,u,l;return a=String.fromCharCode(e.which),!/^\d+$/.test(a)||(n=$(e.currentTarget),l=n.val(),r=t(l+a),o=(l.replace(/\D/g,"")+a).length,u=16,r&&(u=r.length[r.length.length-1]),o>=u||null!=n.prop("selectionStart")&&n.prop("selectionStart")!==l.length)?void 0:(i=r&&"amex"===r.type?/^(\d{4}|\d{4}\s\d{6})$/:/(?:^|\s)(\d{4})$/,i.test(l)?(e.preventDefault(),setTimeout(function(){return n.val(l+" "+a)})):i.test(l+a)?(e.preventDefault(),setTimeout(function(){return n.val(l+a+" ")})):void 0)},a=function(t){var e,n;return e=$(t.currentTarget),n=e.val(),8!==t.which||null!=e.prop("selectionStart")&&e.prop("selectionStart")!==n.length?void 0:/\d\s$/.test(n)?(t.preventDefault(),setTimeout(function(){return e.val(n.replace(/\d\s$/,""))})):/\s\d?$/.test(n)?(t.preventDefault(),setTimeout(function(){return e.val(n.replace(/\d$/,""))})):void 0},v=function(t){return setTimeout(function(){var e,n;return e=$(t.currentTarget),n=e.val(),n=$.payment.formatExpiry(n),e.val(n)})},u=function(t){var e,n,r;return n=String.fromCharCode(t.which),/^\d+$/.test(n)?(e=$(t.currentTarget),r=e.val()+n,/^\d$/.test(r)&&"0"!==r&&"1"!==r?(t.preventDefault(),setTimeout(function(){return e.val("0"+r+" / ")})):/^\d\d$/.test(r)?(t.preventDefault(),setTimeout(function(){return e.val(""+r+" / ")})):void 0):void 0},l=function(t){var e,n,r;return n=String.fromCharCode(t.which),/^\d+$/.test(n)?(e=$(t.currentTarget),r=e.val(),/^\d\d$/.test(r)?e.val(""+r+" / "):void 0):void 0},c=function(t){var e,n,r;return r=String.fromCharCode(t.which),"/"===r||" "===r?(e=$(t.currentTarget),n=e.val(),/^\d$/.test(n)&&"0"!==n?e.val("0"+n+" / "):void 0):void 0},o=function(t){var e,n;return e=$(t.currentTarget),n=e.val(),8!==t.which||null!=e.prop("selectionStart")&&e.prop("selectionStart")!==n.length?void 0:/\d\s\/\s$/.test(n)?(t.preventDefault(),setTimeout(function(){return e.val(n.replace(/\d\s\/\s$/,""))})):void 0},p=function(t){return setTimeout(function(){var e,n;return e=$(t.currentTarget),n=e.val(),n=n.replace(/\D/g,"").slice(0,4),e.val(n)})},C=function(t){var e;return t.metaKey||t.ctrlKey?!0:32===t.which?!1:0===t.which?!0:t.which<33?!0:(e=String.fromCharCode(t.which),!!/[\d\s]/.test(e))},m=function(e){var n,r,a,o;return n=$(e.currentTarget),a=String.fromCharCode(e.which),/^\d+$/.test(a)&&!h(n)?(o=(n.val()+a).replace(/\D/g,""),r=t(o),r?o.length<=r.length[r.length.length-1]:o.length<=16):void 0},y=function(t){var e,n,r;return e=$(t.currentTarget),n=String.fromCharCode(t.which),/^\d+$/.test(n)&&!h(e)?(r=e.val()+n,r=r.replace(/\D/g,""),r.length>6?!1:void 0):void 0},d=function(t){var e,n,r;return e=$(t.currentTarget),n=String.fromCharCode(t.which),/^\d+$/.test(n)&&!h(e)?(r=e.val()+n,r.length<=4):void 0},T=function(t){var e,r,a,o,i;return e=$(t.currentTarget),i=e.val(),o=$.payment.cardType(i)||"unknown",e.hasClass(o)?void 0:(r=function(){var t,e,r;for(r=[],t=0,e=n.length;e>t;t++)a=n[t],r.push(a.type);return r}(),e.removeClass("unknown"),e.removeClass(r.join(" ")),e.addClass(o),e.toggleClass("identified","unknown"!==o),e.trigger("payment.cardType",o))},$.payment.fn.formatCardCVC=function(){return this.on("keypress",C),this.on("keypress",d),this.on("paste",p),this.on("change",p),this.on("input",p),this},$.payment.fn.formatCardExpiry=function(){return this.on("keypress",C),this.on("keypress",y),this.on("keypress",u),this.on("keypress",c),this.on("keypress",l),this.on("keydown",o),this.on("change",v),this.on("input",v),this},$.payment.fn.formatCardNumber=function(){return this.on("keypress",C),this.on("keypress",m),this.on("keypress",i),this.on("keydown",a),this.on("keyup",T),this.on("paste",g),this.on("change",g),this.on("input",g),this.on("input",T),this},$.payment.fn.restrictNumeric=function(){return this.on("keypress",C),this.on("paste",f),this.on("change",f),this.on("input",f),this},$.payment.fn.cardExpiryVal=function(){return $.payment.cardExpiryVal($(this).val())},$.payment.cardExpiryVal=function(t){var e,n,r,a;return t=t.replace(/\s/g,""),a=t.split("/",2),e=a[0],r=a[1],2===(null!=r?r.length:void 0)&&/^\d+$/.test(r)&&(n=(new Date).getFullYear(),n=n.toString().slice(0,2),r=n+r),e=parseInt(e,10),r=parseInt(r,10),{month:e,year:r}},$.payment.validateCardNumber=function(e){var n,r;return e=(e+"").replace(/\s+|-/g,""),/^\d+$/.test(e)?(n=t(e),n?(r=e.length,D.call(n.length,r)>=0&&(n.luhn===!1||s(e))):!1):!1},$.payment.validateCardExpiry=function(t,e){var n,r,a;return"object"==typeof t&&"month"in t&&(a=t,t=a.month,e=a.year),t&&e?(t=$.trim(t),e=$.trim(e),/^\d+$/.test(t)&&/^\d+$/.test(e)&&t>=1&&12>=t?(2===e.length&&(e=70>e?"20"+e:"19"+e),4!==e.length?!1:(r=new Date(e,t),n=new Date,r.setMonth(r.getMonth()-1),r.setMonth(r.getMonth()+1,1),r>n)):!1):!1},$.payment.validateCardCVC=function(t,n){var r,a;return t=$.trim(t),/^\d+$/.test(t)?(r=e(n),null!=r?(a=t.length,D.call(r.cvcLength,a)>=0):t.length>=3&&t.length<=4):!1},$.payment.cardType=function(e){var n;return e?(null!=(n=t(e))?n.type:void 0)||null:null},$.payment.formatCardNumber=function(e){var n,r,a,o;return e=e.replace(/\D/g,""),(n=t(e))?(a=n.length[n.length.length-1],e=e.slice(0,a),n.format.global?null!=(o=e.match(n.format))?o.join(" "):void 0:(r=n.format.exec(e),null!=r?(r.shift(),r=$.grep(r,function(t){return t}),r.join(" ")):void 0)):e},$.payment.formatExpiry=function(t){var e,n,r,a;return(n=t.match(/^\D*(\d{1,2})(\D+)?(\d{1,4})?/))?(e=n[1]||"",r=n[2]||"",a=n[3]||"",a.length>0?r=" / ":" /"===r?(e=e.substring(0,1),r=""):2===e.length||r.length>0?r=" / ":1===e.length&&"0"!==e&&"1"!==e&&(e="0"+e,r=" / "),e+r+a):""}}).call(this); diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 146df28..eae3ee2 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -104,3 +104,38 @@ fieldset[disabled] .btn-primary.active { background-color: #9b59b6; border-color: #9b59b6; } + + +#card-num { + background-size:15%; + background-position-y: 49%; + background-position-x: 98%; + background-repeat: no-repeat; + transition: 1; + right: 0; + +} + +#card-num.maestro { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABACAYAAADoKgJJAAAT6klEQVR4Xu1cB1gUV9d+d1kWlqVXAQtRsCEgdlGjiSa2qDExauwmxm5i7yZo1GiMLZqi0XyWWGJMTPJFjIo9iBUUSyx0EASlCeyydf5zZ3SVCLJLW/P9vs/Dw87MndveOeeee86ZEeEROoXaSi0tp0gsMFAPzkcEkY3h2osfVTYDHDiFGKJErQ671RrNahwPLWCNifgWu37mK+O0h0Qi0Uv8STorsRBDzH68QJXNgFanh07PGernOC5BKZK8joNzYkXoFGotk0quEAe+jAhHO2vYWkshFr8gpcoYeaJitUaH3IIiKFQa/izHIVap1gaIrF7/dIoFsIqddHGwgZUlHb1Atc9ATr4SSpWWb1cHTBXJXvs0QgyESGlxsZNbVXuHXjQozICeVBojh/8NnBbZdFmYRGtLbSYpUkvJi3ky4wwUKFVMldEflyySd1mYQRaYO1tfLCUkOy9glhlghKjJNOPXGXCZInnnUJ4YduKFEWYWTgQyHhtnTxNTrd1iT4GtHLCzo/+2IDMQIpk1QE8NpyELRaUC8vOBvAcAO65kWOt08FHko7aiAB4qJazo2FarQa6lFGoLC6RZy5FoY4s7Mjk01LfqBC8xtq9+YpCYKm/cSgrUrgV4egLuboCUjo1Bbi5wNwNIvQNk3jPmjhLL1C/Iw+sZqWiZcw8N83Nh8eRjWkqtCgsJLju44IyzOw57eCPTSlbu9o29USDmFUYMeFVWZXBxBho3Amp685JRIRQUArduA7djSboE8/JZYJP/xt1kDEyNg18BSV8FoCcpP+vkhp21fBFJRFUVSKtVMTGODkDTIMDbq/LHoFYDV68DN24WV9BPtMQIGR9/He6qokpv/7qdI1bUD8QVe3roKhk8MXYvf5whEleyxJBUcIFNAP/GVW9R5OZBFHkWyMoyTE8tZSEW3IhGcN7jc5U8d3x1TIL2e9TCF34BYCqvssDpHxEjqkRi5HJwL7cDXF0qq59l16PXQxR9Gbh+A10zUzH31mXY6MpWc2VXbFyJFDIQZvm3wm25vXE3lFGKtG+myP7lBRlEfOUoTFpL9J1fAazM40H4YOsmjDkVXimTY2olTGLmNWqOCBcPU299qrxATIdKIoasLH0XIkVSeSJtygin/rgNgw6HmXJLpZfV0JqwqEEwDrqTkVMBCMS0n19xiaFFXt+zm9lI6Xn6JHqcOVVsKvxSkuCcXzErrDxzy8iZRmrtDFlv5QVPjENFibG2hq53D0BW9fa9KQNtnBiHzcs+gaURJrUp9RpTVklqbUTTDvwGtTwQiGk3r/wSQ4sTU19cVZjD5RnRP+4ZcORPzNi1pRJqMr2KRJkthgd3QJHY9DAKT4xzyLwMrpyLv75RA+jbtDS919V0h5hGuOHzhQi+faOaWizezA7veljnQxtrEyHiiWk7m4gRm26VkQrT9utjvFvFxM6VVbx9TBTeDT9QVjG4PMiDb2pymeWqooCONMqwoA6IsyF/oAkQcfpHxAjeZVOgb9saTGLMAWu1Cn/MnAjHAnJyPueIcHLHtEYtTOqliCNfGZMY2p6bRgwt9JoBbwHkhTUHekccx8Sfd5nUtCNZaEy1mQPDAtubuPnkiZllMjH64CDomjU1xxjL3eaXaz5DyFXyDpgBB9y8scg30ISWGTFtTCdGS9LCsTjKvwhdLpzBsm/XmKXHStIsPZp3NsFCI2JcWs80SWI48oFp+vYyywAr0ihbl459+L5Z9jWs33P9gnHc2Vh3TTmI0QX6Q9f62Sayn4MUNW0ti83juUwlCjWU/0FwsbZAoAtFK5/AXYUWf+dQ1LIMvHnqKOwUirKKlXid7WtqZN83XJO1a0r5pkI/lKeiwRWV3X65Gqab9pM6W1I3wMjbiRjXVjNMkhhNz67QP2NDaZF2F3v6NcJrjYo/HSH7EnA1WwXxg3ysau2K90L4pE8DFl24hy8uP9tN75KXi4PTxho5uGcXi7B3xbCMMFhQciNH4exYeRtw6soPYT/qRQqFqgeSEWAcGDEtTSNGPaQ/OHLtlwb5T78hassYeNZwLFakZ1gyTqUr4HnsOKI2joTcprgH+s0/U3D0DkUnCRLKAnW2soCVhQj3i3RQagVJa3X9Cr5etcRQr4hy4SQ+XhCR41QTm8xPcEmwcHGAhYsj9IVK6LLyoFWpMeG1Pjh6MJQvroq5jaSgd0odk0hqKdRN4QUG1q5l/ToQ28mhu5cDTXxqmfNNgQl0bt4FaqMiuDwx0zPAGWku0wSoRg17Zidq/7ALV48t5Muw3FyWA83Q60AyTt6+j+mqJCyY0bfYNXbdb2cs/J2k+KylK/ycZTw5j3A8rRAzIjNwM5eilgQpXZvTxAEj/V3gbCOozHxSk+uvZGP5pftg6cDs9sn+ThjT2BGedsUfglO+fbG9ew9sXPdBsbHEtxgErokv6m1ZxJ/PmLAU4m7t4dazPbIWf4fctTshXzYZLoO6wVL+2DeouhqL+9NXofDg6WfOzWD/EDBXTZkQETFuJhDDOThA9e7bpT9ZhQp0j/oLu7d8yJe5FJOIpoE+/G8mEef2HsPFxb15aYq6nIBmQYI6y1Bo0Hj+fnzT0RP9+7Qusf7kAg0C98TBoqgIe9s64ZXgOiWWYypx5fm7WFZTi3G9gp8qo3tQiE01+0C9YgYmjelquM6RNHzl1QfyL6Zh5JBO/PmsjFy4eAiSH9V5HGptWww371ICgHR/avcJUByKLHV+PmrQAhftjAhF88Q0m5ZBCWVGbTA5Zyeo2MayFEgSkzHFtgALZgllvt0cjrHvd+F/v3ckFeKwcGxaOYI/Xr/xICaOFiaGqbBBkzZjcENnPMhXUEJMHmUvaVCDJmXF4sHwcKfcAULAjlsYXJiM2aOFOs9eiMWc0N2U2muNrRvHwdFBjnQyIoKHfI24H8YY1OXyVb/jyImrkNjI8G1SNL6MfYAePy3Bqx39+Xq27TiB1yJPY9HeCxjx3+Vo3dLXMMLMe3nQx9xCsp0DWrWqz5/XaLRY/Pk+JKXc58fXpqUff55JTlJAv1LnZ169IJxwNGKq2c5fIMa4CKbewx3qt3qX2rDVuSh818sPb74hWG3Dx3yNrRvG878/2HoOYwJd0SK4Ls7ezkT0yRgDaWzRX7o3itYuGazsbRHkZQ9PCx3sLkZjdP+2CGhMKU+ELoO+xK4vR8DNVQjhfrFgJ9LTchAZl46Vnw9H21bCBNVpNBGxMWtg+TDl98fvj+DogShoaJ2Y/etuzKrpj/Xn1sHbU3h6//B9G/Xj4jCpdiB+urIB9vaCmjq89y/s+3AN1IENsenPxYZxR077Epp1O7HZtTYyWgfjz31zDNfiXDpCl51X4hyFvhSAcGNMZubEdA82gRgmMQNLV2U2vx/AqZUD4efribwiLbr1XITII4K+3rQnEqNokhlGrD6M91vXQoeQhvzxoPA7OEbryNIgBwxs5AqZ9GlXDzMAevVejPCwj0sc9KOTbFIatJmNtetGo2fXx6pMm34fWfPXI+/7XzEioD1Ox6znb9Hez0W8Wyf+96iOPXHy+GPjIr5ON8TcK8T52ROx5OMBfBldkRrxTh140/qupRU+avkKoiOWGfrEJIZJTkmYWzcIpxyNCKDxxDSdarTEcA72KBoidLAkuG7biVtHQ/kF/6/UfEwasMTQaSb+7AlOzStC63dW4/KuiZSvIXgP/Ldcw/omMrzSoi5/fDs2Heej4ikfUIJ+bwprzsX0AiyftQl7tk3mj5mqy6f3Sp4EOf9gHRmN+aPW4Df32pg/sy8G929HKQiP91Rxb0/HdKkn9u2axt+qOHoOqZ1HI93SGt+PHGaQcMWVWKQG9sOvTp5wXj0To4ZT2JygvpWExAbkVSfkWlgitPfbCPtltqEbsXYh0BeUvM/6yLcZouycSp0/wwVGjEeQ8cQwp6Vi3HslViyiiW93eD/Cfp7FX18XnYnVw5Yg/sraYuVnnclA+PxvcDE8lD+fr9ahz+gNOLpFUHnRN9PRbc1x/okc7CHG6mWCFbj7cjq2f7oN+/cK9f8VlYBBM3cU7wtJtLgteXKJIO76LeijYuAqk+DTBf3xRrdmfNmUn47gm+v3sPSTgfxxzpoduDdlBU7ZuSBr4UeYOUVQ1bnf7EHm+KX4xv0l1Jw/CtMm9eTP68l4iHN5mTefr8rsof1hOfq/JWiCIjK7k59hdg9p2AbJtJ8pEwIxU4yWGFahcti74Oyf9pOxjeVIRQpWfTaUb/f942k4NHYJUm58ZehHIb2Y03BTDDpdisT27yYIE5yUiw2LdxiOIzOU6L4/CfVTE7B3ZEvKqHXly809koA9U9ficuRyflFnJvH8c5n4LTEfKh0HRysx2rjbIOq+Eh42EsQ/UOMO/VlHnMHMlp74cBzlJBBidh7GFYmMJEnY7BX8HI6spZuxJV+MkG9n4bVXBWdj+uA5yN95AD86e+Nyjy7Yu32KYRy563cjb+vvuDZmKHqM6m44z4hkhJYEFpt5PbAjWE5AmeCJCTSNGFWvbtD51H6qbumlK1jbwdMw4FY/JyB9wSpcjvgMzk6C7b7xWjZm7ziH2W5qw5P51elkbJ27AaePfGrY8xQQgbZWxbNt+oQl4eKC9Rg7IIRXUaWh47JDCJvaGfIS1il2z7rBS2DbvZ3BJH5Uz8QOUzBz5zzDg5Do/xbU1+Nx29oWY+sE4Zed09CymaBqS0LK4XO0/s6AdaAfFMcvPFUkgSRleIOStwJPFRaImWxSzF8THAh1e0F0n4TsQDgOfvwGv28pooW6xrZbsF2/CefD5vP7Fj2pl2Z7E5C2/wR2DGtueDJHHUrEn9PXYNhbbfDJnLcN68Hps7dx49YdvDe0E99Mo92xyIy6AZv/HsDQAR0wkfYgXp7F9fW9+/l4453PERG+0EDyoz7GJ2YiefVO/LGLPA+tWpAETDY8MGxv06n9TJyKEaRbTwt8nF1bgydhqWd9nPWqhWUL30VPUomPNs2sbFZ2ASK+D4P7J2uRGuSPTt1aIHflVl7lPYlfXGtirbdgNZYFPubPE2NCUrmekvqUg592X8h/+hUW97LAkXcgf/Rwvm3bbT9CXMDejhYhf/hAModtYLP/ECRJKfx1RdfO0NbzgSQhCbIjJyFTFKKOnzdSbR2RTU+Y1flovlz+SNqRP8zCeXfLZtxNSuP1u7u3K5wc5RDT+uaano7xl85hPD3dReQqkTnY8tfkeh2cqL2esTcQoHyAbIkUc2o2Roq9I+rXqwFXioJOP3UEQ7wFFSal/NQd8Rcevs4tTCFTQ9tdaiHMwQNaZ7rPtwbk5GOzTLqDVlFReDU3E3ek1jhp64o3c9Mhozb/ibk+AWD+OWPA5y57BHxkEjGsYuWwgdA7FfeFGdNgZZSpT/li61cvFQijDBQpPV5WNJllwVapgPSJ92wU/L3kMjIxqpkjESw8G5p8q4e+s7LaLhRL0KdxiHHrC1XGE1OjHMSomzclddamrP48V9f3fDwdddPKdjZWRad/d/bCKm/Ba2AMBGKaMInhjPATPK6Ss7aC4v2h4CyLx1yMadQcZZrfvI4NK4SNbnWDyfIIv5ZItjL+QyMcRJkiT/+J5XqjTBXSCurWpmV/VPekPGrvP0sXICCeXnYyA07QuhJai15HMQH8G2WejctHDEcZ/YVsUSbHoDnQMCkBXc9FlNk0S3HqFXGizHJVUUBNe5b36jUnw8C0OXpIzIRySQwbiKZxAxR1Ezy95sBGUk/NSE09r9jmVhv/cSs5PPGsPvPEeDUgYsTGuf1LqkzZqys09R+7yatzkpzz8zBn+ybYUIymJDS79bfZki9uyuwwiUx3bTne0ef0PDHjK0QMR28eFw4dAD173/I5wkBKvJhupoTyfMr2/+ClYGSS97k84InxZsQYGSgrrRE9eZ0LWC4Ae0//OUD7mGisWve5WTIvVRTTn1GrCa7RBri8oE+WEDH1x1WYGNYBnZsLCgf0NezQy9upit7HSFnx9UqzqDBGyiKvhjgjN8K1/4yBVioxrB09ud0L3+kDfQne54pOuDH3v3rwABbv2wGpGV5WYuprnndjkpSKZ6hWOjFs8pj5rKDcM62PEA6uDrBYkHX4cUiv/o3mhbmYm34LjrqqyxH755hukgd6sVcDpFGwrTJQJcTwHSNLRNUiGGwTylFOVlVCkpoG2aFjEGdlG5px1qoxOSMO7Qoen6uKPjDn5l4nL3zvWqdc1ldpfao6Yh62qLezRVHHdtA0IHPaqEQ346dPTB//sY44C8trpb8t1qYwB6MzE1FHXb6U2mf1hq0jm9x8kGCCq8XY0VU5MY86wqw2Vatm/IaUmdcVgcXdTEgvxUB6jT5VYoR3l6UNtivIQt+cdAQp6CsaFWicLe4Rti68lDD1VVWoNmIMA6CcAY3vS7T+1Ia2Vk0KHRix96HYuuROGiQpd2B5Mxbi7Jxyz4ebVoWX87PQjNahIIrNlBQ3+WflWRS/uWTjgPNyR54UFi6oalQ/Mf8YEUefyWKWHNucsgAbR+91iui7YSL6VplIWQRxTg7EufSuvokxE2MnzkOjQk21Es46NeTULovPFJJ1VUQ+rgzaHKaSj4tlwlQ3zE5MdQ/439KeQEyDCUkUj3k6u+LfMor/wX5SPCaZiBkXQd/EDPkfHN+/dkjkXT4t8vQdO8XCQsx/EPsFno8Z0On0U0U+PiOstVLZNdoUlp409Xz09/9HLzguXqJW+vNmvZfP6IYiK8uDL9Ya83LP1hZOpemalrjxhmG/5ew82N7G3ZFlWvejjVtdkqDKcfyYd6zPf+scR/sCcTx1dK8iM3dldvYO/lte/wceVnXzIZnpOgAAAABJRU5ErkJggg=='); +} + +#card-num.amex { + background-image: url('data:image/png;base64,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'); +} + +#card-num.visa { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAgCAYAAAC/40AfAAAFoElEQVRYR+1ZC1BUVRj+dnn55uErKmSHXVikJRBQ8J2o44OHoyFmmk2WpU4zmiLjYwsy8wVGTZqZTtqUD2iKiIQpBcxQVPZhwCywywKijIPispIvXNjtnLNxcwXhMtMwLtM/w3D+8/jv953v/P+5cAUgVlpamuzs7BxvNpvdqG9PJhQKjW1tbccCAgK2CRQKxUaJRPKxq6ur0J5IPIq1sbHRUl9fv15QUlKikMlkofZKpB23RqMpFpSVlemIRJI+QKaKkRk9erTdkykvL++DZPz9/e1emYqKCqsyUqnU7slUVlb2QTJ+fn52r4xWq7Uq05tkzBYLrt26i/sP2zBiSD+4D3L5T24Fjoyvr28HZYRNORAaMiFsygUsJvZAi4sIrdIM8tubA7DluBKH8rXMXzZVAvmCIPit+YH5rgOcof3sZda+cfsBdvxUgqziK7jb0sqt9/UcgsKtUZxPSS5KK8DFqpusT+bljrwPZndLWKfTVQnIe5muMzLtqwWmBjRqtuJZUybpMqPVKwltI1exYVOrGUGJWTDcaWH+2Q/n4q/7JkTtPMX8UJ+hOLlxJm40P8Cc7b+h3nCvA6jAUe44JZ/F9R/M0+L9dBXnOwoF0H8eBxcnhy4J8SJDI+w/VYH6mlzsDtsLi+s0mMSHWOBs5VWsOHCOtSdIR+DH9ZE4fq4a731zifUtmSTGnmVjkZShxoHTlaxv2gue2LLgRfR3dkRd4x3cbG5B/HgRG2s1WxC+ObsD6azE6QiXDOdHhrxodlkAtNebMTU5F/MDDDg4/ShMskIWeGHaGRRWNLD24dWTMDvoOWw+rsLhMzrWl7I0DEsni23mLYwQ4ZPXx4Hu+OOWq76G5V9aN2de2ChkKepYOykuGCtnSrskU0WMHbPuyNAoIRuzcb3pHtLm6LA4eiXqbvdHxJaToAntPWwQzm+bC6FAgPmp+bigs573zIRIRPgOZ6okf3+ZAyN5ZggSY2WICfWyARi7Ow/F+kaimgMKkmaz+NRmkU06QjarK2NkyFszLzJrydHJKKolgC04Jw9GutKET3M0LP7W+DF4K9KXtWUJ/+ZQWeo8eJBqRQlvOqbCt3/obfBEjXkeB94ezzZBWXMLMbvy2PgicuzSiHrhhMxVUvlo1bu8O5YfGbFY3O09k6Oux4qvzrOA66ICcLSwBg2372OgiyOUO6MxuJ8TKwSBG35mc4YNdsGfjwFQEcDbM0tR9I9ydN7e5eGYP3YUVh66wHKQWtaGSISR4vHu1xeRWWw9aort0fB07/9EQnq93qoMHzLNpEoFkl2nSeo20BnGuw9Z4GVTxNixOIS1i7Q3EUfyiNpEUhAy1k7t9OGv7StEftl1NraCKPrODCki5CdZbGrDiRLU7jwwsfuI2hdvRpA8sj2WjwbnyPj4+HSrDF0Ym5IPVY3BBuDZ5FnwGTGY9R35XQ95upq133hJgo/ig7HnFw0cHQSY7D+S5QK9bxKPKbmKtZ+ALLtmxL5fKzol3t5Jj3FyXNAT51RXV1uV4UsmjeQIBddudPfT10zh/ITvFDhxvpb5qaSSvTJBhDk7TqP0qrFTEOPEw0gVnIjx8hxQ5WmF27Uk1KbSJZJcazG1IdDLDbmbZnRNRq1W8yoANEpJXROiduVzAQ+vmoAZMk/On5dawCmXvWEagkUeJM+KUKBpYIDazWvoQCyM8MbqmX7IuHAFm09Y1aSxaMxHLSalAJdrDXByFKI8NfaJlyerZpQMn5zp8gzwGGwiOUZ/hpLq5jrAiceKnk1hOdNbZHoGreezOTJ8c6bnj+i9FawAUGX6DBmVStV3yCiVyv/J9F428HsSyxlyzC6JRKKx/JY8vbNqa2uL6T/O13l4eKS6ubl1/APj6cVug8xoNFoMBkMCI0DUkTs4OLxKPg3Y3ScNgpt90ggJCdn2NwjGnJUGV81rAAAAAElFTkSuQmC'); +} + +#card-num.visaelectron { + background-image: url('data:image/png;base64,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'); +} + +#card-num.mastercard { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAgCAYAAAC/40AfAAAImklEQVRYR9WZeVBUVxaHv9c00nSDsitIRMVdcccNIooLOrhmrETU0SkdrRg33FMa45aURjE6OhlHB1HHLWommqARlWAyRmQ0iYoouACitkojiGADDd395jbGmWg3W9dUpTz/vG76nvPu9+655/zuQ6LfCpVTPcdNCokxSHjyuplMvlnmC0N5RbSkifh4k6ODYo5nAzXi+lqhyMjoyyooKCpFMksbJfXAlTn1NaomytcM5NdPXV9ajqHCeFfSDFyRq1QofBQiz15XM5rMmGVZJ7mEL8+VkHzqAtKtSEvk4ww6FT/C11BU6frMwYkMjTenPVuQ6NGCUgdHmyGVCjMhjR8wsMld2nvl464qqxz3pEzFtceenMoJ4PwDX4zmuqW8SDkB098CQ40wCllmjC6NZVlJBJQVVstuAfl742A2NAnliaNz5VgnBxNTO11lVpfLuKkM1frnl6rY/HMXdl5tj8HkUKvnLINOcu37Ya6kqB6mYfkz9qUdIrjofq0CvxhkAZneZiQP2rqzY+hp/F2f1ck/q7ABU04MIj3fo0Y/2Sxg6r+5LFeSqoZpp9dx5Oo+LED2mLG7ipL5Hjg6mu1xR1/hyHsJ4ZzKblKtv0gcndQg9IMqYXwEwPeXdtCovNiuicguCsxd6oEoLqY+KkzdnOyKU2pUMvrwMFJ1XlX6P4cJWWoTRiFqeMKV3QQXa+2awKtOskaBYaMXskfdNvaLOLl6NaG7xlSulC2rhPHo/X6uLCmsCsCox+nE3TxiN0jFGBdMQ9Qv+cvOotQ42d8CNqZ0Jia5q805SbL5OQw2SvNPl7bStIaqVSVpPQnjYFHFbPQuY4QauWHtKtSr8S2rErztbYoMInWtTJRmz16LrWA66h+RdHWX3atSnaNRrFjFWBe7Y88+3pcj6c2rgOmx0ApmsfYHFmqTQamEqCgoKIDjx2H8ePG0Rc7v2VPtZIxRIsVa2Hp6ws1Vwtxc5L17NyTPnij0tzE9PFUjnMInDAw64i+U8O5X4rOtlfEKXmAFs/P2Vwx7cpOtfaKYfm4/Jddv8Hn0J0w+FYf+/kM0vYKhVy/RpnRw9qxouWLLhYRQ8bSIa1OiaRfkheKjkUgevtCkHfKlRHB0QvJvBUX5JIVNYtDYuWTf0QkFUIgqdQqKBu2Rn2ViLkxD4d0bWS96WsVTpPqt+Cm9lIARB/B+uJrsKycI3TbaNox38Pxc5JflTHzGAXo+07Ju6hpmbpqL6U4O8cmZhA/vjXQtjTShYPxa+NOypR+6BUtRr/iAktIKShNO8TS4N+2a+XBl0Wo6xCznWUERHrevs++bK4xdPo1H3/6AW/8Q0s/upzjtM/TlTgSO2otK5STi+XM6dhaDp4q/FxXw87lEeg98i7LSEjSurpR/F4k+9yptNoy1hpHEnvHpImBeaZonM/bSuSSXv246SregN2jq506Z5EBeiZGm506jPXyM8oiheI4bw/2kc/SdPBrtso84/5cDRORcJCNuMQ5hc2msuEfChXzGTYhg7+EUIgd1ZH/MeqI3rKPsWBCy4THaJ2pK3CLIU/aha9gIvjv+BaMnTOZo3BqGT1rMuf0Lib/elvVr/kTZ160xiZ7XfM04G1kmSrNP53lWMPsyj9BV/5Dzx5Nxun2TsGm/J+3It/j27UF+3F6aRU9j12dfM3nmSFJnLeFEsx68Hz2cH7cdJGTeH0mcOISgmINcTr3Dnbt5dEDsi9ZhtC9MJubQDdbsFjAnuiOXaDlZMJ2QUbM5cOgMs2eMZveOA7w9dhgxK1exbN36SuitGXOZNnUEisQgcoud6bnZRppZ+kzDjnOtYNZqk2irz8Mr9SI5azcTHruWYxPmMWzvp2zf+E8mTQzn4t5jhM75A0WLlqBVe+A8eRI55y4RFjWYjJUx5PeLoIdDEWXx33C3XIHbgmj8lsxnacoDFiQfxll+xNMHqXx/qzHD+3lz8dI9wgaGExt3gtEDGvLxqi2s3x7L4+xkHD27IBdloL78DimZLkT9Y4DtlWnYMdpKNQ8ozmbok1vUW70ac2wsvlPGkxgXX7lCZ2KP0DJ6Kk8zc2jbyIVErYEe3VvilHWLK7GHCPhwISFZx1h3IY+OkWPxdHNGun4UKbAfI3TL0RbmsSoriv5DI2npW8r2nUkMHTGc7MxMQoOUHDxTwaKIVDIvn+bQ/Rn0Dwkk7dZT3un4bxoYU9l2UsH25DbWtcyimhsFzbGCcZJNXL/+N5zNRpsls0LIbEchUy1mFhvOJJTqi+8GsbecXGSM/Z0xyOKzZHophnGEBtlNQWFJPdzU5ZW/mcwSDgoh4mth4VsiySmw7lOVR4BG7S0wspWcWaQ7T3TexVqEr/0Qc4ASw4aqxWJNkU6m+/Pe531sDpORdJJvu5k2T5oacwUXbu3CzfT8JFhXs0iW8oXuQin9z1N2FfLVTqFpWb0hWyLIznetAkaUZr/WM8ThzPax+U39Pfbci0f5S0rVGchfiTnwuco19nPGHFSFKqhF4OXxXdh/IbDKkbJZwDRuPV0cAap+BzDxSRqrc89iORLYa6ZQFeVz3F5apbrE2pMSyOpjnap1kS0vNBq3qh7GEuF3xZl8+igJS+rV1b4UcuTGGH9mD00XIrpuD8QsS6w/2YEdZ1vWeNtaw1giBQidtCQvpRKsNna7njufePckweW5wu0akC9KblrltTb24x0v1iV04PK9ms//lnh1gnkxgfZCgkQKoCHFWTQTgL/eTzqlmrPqN0hwbUaipilGUcJftd6BOga1e0i/1o/wd9e/9PPdAg3/utmIU9f8SMnyrg3zf8fYBfPqHbyMJahEX8pVarD0n7qYpbf4uJaJF3iQV6wSV/tPoc9hWs/IEX2m+lcfdZnhbzRW9Jm7AubdTRKKOb/RHP5vt5Ux/1ny6zZNjV65SRSat8Qiv3b/0hAZmi+y80s0xuj/AELoeE0qzs1pAAAAAElFTkSuQmCC'); +} + +#card-num.discover { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAgCAYAAAC/40AfAAAFm0lEQVRYR+2ZeUxUVxTGvzfzKGFJEcEyQC2rsgmRpTFQC9ImIhIaGkuBhBATEiImxgUkTZCG3QaKIVASEyn9QwOC0Ii2YynFgoWydNgUEChYQUCWkY6EXTLTey+dqUAhqNQyCSeZvPdm7nvn/M757n3nZjgQ6+joCFAoFJ9xHKdPjhz9Th2MxKsgcY7Pzs5muLi4FHNtbW3eurq6P5iZmb2hDgD/FuPQ0NDc4OBgINfa2lrq5OT0kbqCKOO+e/eumCMS+83Ozs5N3WEIRyPX3t4usbe3d92C2UQZ2KrMJirGklC2KrNVmdeQgVVltmfPHkilUujr6+Pw4cOIi4vDtm3bIBKJUFxcjLm5OYSHh2NiYgKhoaHIysqCTCbDmTNnUFBQgIWFBcTGxiI+Ph5oLwNuZwMLs4CeMeD6CWRmXqA+8vLycPDgQYZ67tw51NXVITg4mJ0rrbKyEgcOHGCXxsbGOHv2LCwsLNi5ubm5atyqMEZGRjhx4gQcHR2RnJyM6elpNDc3Q1NTExUVFew3b29vREVFobOzEz4+PvD19WUJuHDhAnR0dNDU1ISI9y2B/EjAfB8gsgWEPDDSDTj64dMvCjEzM4ObN29ifn4eO3fuRGJiIktUdnY2SkpKWKC7d++GlpYW8vPz0d/fz0CfPn0KbW3t9S0AFCYjI4NlfXh4GKampigtLYW/vz+DSUhIAOmHWOaDgoIgkUjg7u6O3t5eWFoSAKV96UUqMgfYfkiiItnlNYHf7wADLah2OMUS0tfXh5qaGkRERID0V8jNzUV6ejpSU1PZUwIDAxkM9UuVcOTIEYyNjWH79u0vDkPv2LFjB5KSkhAZGckeunfvXpw/f57JhJY6OjoaYWFhLKsCgeAfJ7FWgA5xSkEs3QmMBvBHwyJQdBUcHBwQEhKC8vJyODs7IzMzk0mWSpQmh1pRURGTu56eHkiXjJSUFBw/fnzFLFxTZsrK1NbWwsPDg8mMOqQwpDGFoaEhenp6sGvXLty4cQMBAQEQi8VMctTkcjkEucFAzy+A2bvAW9YAJwSkDwAF6dwjv0VOTg6r7vj4OLq6umBtbc1gLl26hHv37qkCphB0XFpaGurr69l8W25rwri5uYHKrbCwkGWClp4+9Pr160wSVIKjo6MMhEqF/k4ze+zYMaZnGmDO5yeBtPcAAYF4U0RgSNVmJ4CIIuAdF0xOTrKJTJNVVkYWCmIUhqrg6NGj7JrOSzqGJpH6vnXrFkss2baslBlpnSWEdEmjSefE1NQUC8rLy4tpm1pMTAwDefToES5evAie53H69GlQcGp0Xl29epWtZjQYPz8/YFIKriwNGCSZFtlA8QEBNLRQBULnxv79++Hp6cm+q66uZglSGl0h6aJC/ZqYmLBF4tChQ6oVTjmO7MsaOQpDtKveXfP8NPpvX+liMOq8BeDaxBAUnoTMyHWEwdja2qpdZbiRLgiLo8Dd/5Ep7Yn9x4swNjY2agPDTQxD+F08BPWXyZK5oJpbKhjylt30MNyfAxBWZEBY+w3wjLRGy4zBtLS0SDYzjOBxB/iqryBsuLKkEsthpPYBizDkxbe5KqOQQ9j5E/g7Oey4HlPBkDfvpoCh84FvuAyNX78GJxtYD4NqDINpbGz8XyvDPZsB3/Y9+MYC8F0VpNWRvxCEcrDU7m+Y110ZBtBZDr6lBPz9MtDrVzUVjJWV1X8uMyohDRI430k+3T9vCMDzCRi1I6tZQ0ODmFTG91Uzs/x+lv0HNeB7KqHRUwXh4/aNdrHkeQ/3nWrlSIvvb2BgcI18yM7p5U0w8Rj8wzrw/RLwfeQ41LbmUvrynlbeuaArUrT7ZIWwvy/ITjFQKBRGkdO3yT7kud3V6i45sifRGu/ltcY6NLSk3Rr8nHRd920kBOScQq6tL3ti4x9n6xOa9xcZcbS/MtGpuQAAAABJRU5ErkJggg=='); +} diff --git a/server/controllers/users-controller.js b/server/controllers/users-controller.js index 0afb337..24619f4 100644 --- a/server/controllers/users-controller.js +++ b/server/controllers/users-controller.js @@ -123,6 +123,49 @@ exports.postBilling = function(req, res, next){ }); }); }; +exports.confirmEmail = function(req, res, next) { + var token = req.query.token; + + if (!token) { + req.flash('errors', { + msg: 'Please check the URL, you didn\' provide any token to confirm your email adress' + }); + return res.redirect(req.redirect.failure); + + } + + User.findOne({ + emailConfirmToken: req.query.token + }, function(err, user) { + + if (err || !user) { + req.flash('errors', { + msg: 'lease check the URL, you didn\' provide a valid token to confirm your email address' + }); + return res.redirect(req.redirect.failure); + } + + if (!user.emailConfirmed) { + user.emailConfirmed = true; + user.save(function(err) { + if (err) return next(err); + console.log(user.profile.website); + + req.flash('success', { + msg: 'Thank you, you sucessfully confirmed your email address.' + }); + res.redirect(req.redirect.success); + }); + + } else { + req.flash('errors', { + msg: 'Sorry, but the email address was already confirmed.' + }); + return res.redirect(req.redirect.failure); + } + + }) +}; exports.postPlan = function(req, res, next){ var plan = req.body.plan; diff --git a/server/middleware/email.js b/server/middleware/email.js new file mode 100644 index 0000000..23e863a --- /dev/null +++ b/server/middleware/email.js @@ -0,0 +1,38 @@ +var nodemailer = require('nodemailer'); +var mailgunApiTransport = require('nodemailer-mailgunapi-transport'); +var User = require('../models/user'); +var secrets = require('../config/secrets'); + + +var transporter = nodemailer.createTransport( + mailgunApiTransport({ + apiKey: secrets.mailgun.password, + domain: secrets.mailgun.user +})); + +var config = { + from: 'postmaster@sandboxdaaf0cb261364f07a6390025ab706114.mailgun.org', + siteName: 'node-stripe-membership' +} + + exports.sendSignup = function (req, user, cb) { + + + if(!user) { cb(false); return ; } + +var mailOptions = { + to: user.email, + from: config.from, + subject: 'Confirm signup on' + config.siteName, + text: 'You are receiving this email because you (or someone else) signed up at ' + config.siteName + '.\n\n' + + 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + + 'http://' + req.headers.host + '/user/verify_email?token=' + user.emailConfirmToken + '\n\n' + + 'If you did not request this, please ignore this email and your account won\'t be actived.\n' +}; +transporter.sendMail(mailOptions, function(err) { +console.log(err); + cb(err ? false : true); + +}) + +} diff --git a/server/middleware/passport.js b/server/middleware/passport.js index 8e9cf7b..45742dd 100644 --- a/server/middleware/passport.js +++ b/server/middleware/passport.js @@ -1,5 +1,7 @@ var LocalStrategy = require('passport-local').Strategy; var User = require('../models/user'); +var crypto = require('crypto'); +var Email = require('./email'); module.exports = function(passport){ @@ -58,16 +60,23 @@ module.exports = function(passport){ // edit this portion to accept other properties when creating a user. var user = new User({ email: req.body.email, - password: req.body.password // user schema pre save task hashes this password + password: req.body.password, // user schema pre save task hashes this password + emailConfirmToken: crypto.randomBytes(15).toString('hex') }); user.save(function(err) { - if (err) return done(err, false, req.flash('error', 'Error saving user.')); + if (err) return done(err, false, req.flash('error', 'Sorry, but an error occured while saving. Try again later')); var time = 14 * 24 * 3600000; req.session.cookie.maxAge = time; //2 weeks req.session.cookie.expires = new Date(Date.now() + time); req.session.touch(); - return done(null, user, req.flash('success', 'Thanks for signing up!!')); + Email.sendSignup(req, user, function (result) { + if(result) { + return done(null, user, req.flash('success', 'Thank you, your account was created. Check your emails to confirm the signup.')); + } else { + return done(null, false, req.flash('error', 'Sorry, but an error occured while creating the account. Try again later')); + } + }) }); }); }; diff --git a/server/models/user.js b/server/models/user.js index 5e502e4..eea50f6 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -17,6 +17,8 @@ var userSchema = new mongoose.Schema({ picture: { type: String, default: '' } }, + emailConfirmToken: String, + emailConfirmed: {type: Boolean, default: false}, resetPasswordToken: String, resetPasswordExpires: Date }); diff --git a/server/routes.js b/server/routes.js index ee94128..54d0bbc 100644 --- a/server/routes.js +++ b/server/routes.js @@ -111,9 +111,14 @@ module.exports = function (app, passport) { isAuthenticated, users.deleteAccount); + app.get('/user/verify_email', + setRedirect({success: '/', failure: '/'}), + users.confirmEmail); + + // use this url to receive stripe webhook events app.post('/stripe/events', stripeWebhook.middleware, stripeEvents ); -}; \ No newline at end of file +}; diff --git a/server/views/dashboard/billing.html b/server/views/dashboard/billing.html index 6a1b05b..369afa9 100644 --- a/server/views/dashboard/billing.html +++ b/server/views/dashboard/billing.html @@ -36,7 +36,7 @@