From 9c144312eb6a88eaf81294af59a5160f094138b0 Mon Sep 17 00:00:00 2001 From: crossxcell99 Date: Thu, 29 Jun 2017 16:34:01 +0100 Subject: [PATCH] show qr code for first otp login --- frappe/auth.py | 1 - frappe/hooks.py | 3 ++- frappe/public/build.json | 3 +++ frappe/public/js/frappe/qrious.min.js | 6 +++++ frappe/templates/includes/login/login.js | 28 ++++++++++++++++++++++-- 5 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 frappe/public/js/frappe/qrious.min.js diff --git a/frappe/auth.py b/frappe/auth.py index 0a9a7ade5f..94241a8e34 100644 --- a/frappe/auth.py +++ b/frappe/auth.py @@ -127,7 +127,6 @@ class LoginManager: if user_info.two_factor_setup: frappe.local.response['verification'] = {'setup_completed':True} - raise frappe.RequestToken otp_secret = frappe.db.get_default(self.user + '_otpsecret') else: import os diff --git a/frappe/hooks.py b/frappe/hooks.py index 2d28b74d91..1ceab9f7ca 100755 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -40,7 +40,8 @@ app_include_css = [ ] web_include_js = [ - "website_script.js" + "website_script.js", + "assets/js/qrious.min.js" ] bootstrap = "assets/frappe/css/bootstrap.css" diff --git a/frappe/public/build.json b/frappe/public/build.json index 13bc48b8b5..546b90a82a 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -22,6 +22,9 @@ "website/js/website.js", "public/js/frappe/misc/rating_icons.html" ], + "js/qrious.min.js": [ + "public/js/frappe/qrious.min.js" + ], "js/dialog.min.js": [ "public/js/frappe/dom.js", "public/js/frappe/ui/modal.html", diff --git a/frappe/public/js/frappe/qrious.min.js b/frappe/public/js/frappe/qrious.min.js new file mode 100644 index 0000000000..5735ea62de --- /dev/null +++ b/frappe/public/js/frappe/qrious.min.js @@ -0,0 +1,6 @@ +/*! QRious v4.0.2 | (C) 2017 Alasdair Mercer | GPL v3 License +Based on jsqrencode | (C) 2010 tz@execpc.com | GPL v3 License +*/ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.QRious=e()}(this,function(){"use strict";function t(t,e){var n;return"function"==typeof Object.create?n=Object.create(t):(s.prototype=t,n=new s,s.prototype=null),e&&i(!0,n,e),n}function e(e,n,s,r){var o=this;return"string"!=typeof e&&(r=s,s=n,n=e,e=null),"function"!=typeof n&&(r=s,s=n,n=function(){return o.apply(this,arguments)}),i(!1,n,o,r),n.prototype=t(o.prototype,s),n.prototype.constructor=n,n.class_=e||o.class_,n.super_=o,n}function i(t,e,i){for(var n,s,a=0,h=(i=o.call(arguments,2)).length;a>1&1,n=0;n0;e--)n[e]=n[e]?n[e-1]^_.EXPONENT[v._modN(_.LOG[n[e]]+t)]:n[e-1];n[0]=_.EXPONENT[v._modN(_.LOG[n[0]]+t)]}for(t=0;t<=i;t++)n[t]=_.LOG[n[t]]},_checkBadness:function(){var t,e,i,n,s,r=0,o=this._badness,a=this.buffer,h=this.width;for(s=0;sh*h;)u-=h*h,c++;for(r+=c*v.N4,n=0;n=o-2&&(t=o-2,s>9&&t--);var a=t;if(s>9){for(r[a+2]=0,r[a+3]=0;a--;)e=r[a],r[a+3]|=255&e<<4,r[a+2]=e>>4;r[2]|=255&t<<4,r[1]=t>>4,r[0]=64|t>>12}else{for(r[a+1]=0,r[a+2]=0;a--;)e=r[a],r[a+2]|=255&e<<4,r[a+1]=e>>4;r[1]|=255&t<<4,r[0]=64|t>>4}for(a=t+3-(s<10);a=5&&(i+=v.N1+n[e]-5);for(e=3;et||3*n[e-3]>=4*n[e]||3*n[e+3]>=4*n[e])&&(i+=v.N3);return i},_finish:function(){this._stringBuffer=this.buffer.slice();var t,e,i=0,n=3e4;for(e=0;e<8&&(this._applyMask(e),(t=this._checkBadness())>=1)1&n&&(s[r-1-e+8*r]=1,e<6?s[8+r*e]=1:s[8+r*(e+1)]=1);for(e=0;e<7;e++,n>>=1)1&n&&(s[8+r*(r-7+e)]=1,e?s[6-e+8*r]=1:s[7+8*r]=1)},_interleaveBlocks:function(){var t,e,i=this._dataBlock,n=this._ecc,s=this._eccBlock,r=0,o=this._calculateMaxLength(),a=this._neccBlock1,h=this._neccBlock2,f=this._stringBuffer;for(t=0;t1)for(t=u.BLOCK[n],i=s-7;;){for(e=s-7;e>t-3&&(this._addAlignment(e,i),!(e6)for(t=d.BLOCK[r-7],e=17,i=0;i<6;i++)for(n=0;n<3;n++,e--)1&(e>11?r>>e-12:t>>e)?(s[5-i+o*(2-n+o-11)]=1,s[2-n+o-11+o*(5-i)]=1):(this._setMask(5-i,2-n+o-11),this._setMask(2-n+o-11,5-i))},_isMasked:function(t,e){var i=v._getMaskBit(t,e);return 1===this._mask[i]},_pack:function(){var t,e,i,n=1,s=1,r=this.width,o=r-1,a=r-1,h=(this._dataBlock+this._eccBlock)*(this._neccBlock1+this._neccBlock2)+this._neccBlock2;for(e=0;ee&&(i=t,t=e,e=i),i=e,i+=e*e,i>>=1,i+=t},_modN:function(t){for(;t>=255;)t=((t-=255)>>8)+(255&t);return t},N1:3,N2:3,N3:40,N4:10}),p=v,m=f.extend({draw:function(){this.element.src=this.qrious.toDataURL()},reset:function(){this.element.src=""},resize:function(){var t=this.element;t.width=t.height=this.qrious.size}}),g=h.extend(function(t,e,i,n){this.name=t,this.modifiable=Boolean(e),this.defaultValue=i,this._valueTransformer=n},{transform:function(t){var e=this._valueTransformer;return"function"==typeof e?e(t,this):t}}),k=h.extend(null,{abs:function(t){return null!=t?Math.abs(t):null},hasOwn:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},noop:function(){},toUpperCase:function(t){return null!=t?t.toUpperCase():null}}),w=h.extend(function(t){this.options={},t.forEach(function(t){this.options[t.name]=t},this)},{exists:function(t){return null!=this.options[t]},get:function(t,e){return w._get(this.options[t],e)},getAll:function(t){var e,i=this.options,n={};for(e in i)k.hasOwn(i,e)&&(n[e]=w._get(i[e],t));return n},init:function(t,e,i){"function"!=typeof i&&(i=k.noop);var n,s;for(n in this.options)k.hasOwn(this.options,n)&&(s=this.options[n],w._set(s,s.defaultValue,e),w._createAccessor(s,e,i));this._setAll(t,e,!0)},set:function(t,e,i){return this._set(t,e,i)},setAll:function(t,e){return this._setAll(t,e)},_set:function(t,e,i,n){var s=this.options[t];if(!s)throw new Error("Invalid option: "+t);if(!s.modifiable&&!n)throw new Error("Option cannot be modified: "+t);return w._set(s,e,i)},_setAll:function(t,e,i){if(!t)return!1;var n,s=!1;for(n in t)k.hasOwn(t,n)&&this._set(n,t[n],e,i)&&(s=!0);return s}},{_createAccessor:function(t,e,i){var n={get:function(){return w._get(t,e)}};t.modifiable&&(n.set=function(n){w._set(t,n,e)&&i(n,t)}),Object.defineProperty(e,t.name,n)},_get:function(t,e){return e["_"+t.name]},_set:function(t,e,i){var n="_"+t.name,s=i[n],r=t.transform(null!=e?e:t.defaultValue);return i[n]=r,r!==s}}),M=w,b=h.extend(function(){this._services={}},{getService:function(t){var e=this._services[t];if(!e)throw new Error("Service is not being managed with name: "+t);return e},setService:function(t,e){if(this._services[t])throw new Error("Service is already managed with name: "+t);e&&(this._services[t]=e)}}),B=new M([new g("background",!0,"white"),new g("backgroundAlpha",!0,1,k.abs),new g("element"),new g("foreground",!0,"black"),new g("foregroundAlpha",!0,1,k.abs),new g("level",!0,"L",k.toUpperCase),new g("mime",!0,"image/png"),new g("padding",!0,null,k.abs),new g("size",!0,100,k.abs),new g("value",!0,"")]),y=new b,O=h.extend(function(t){B.init(t,this,this.update.bind(this));var e=B.get("element",this),i=y.getService("element"),n=e&&i.isCanvas(e)?e:i.createCanvas(),s=e&&i.isImage(e)?e:i.createImage();this._canvasRenderer=new c(this,n,!0),this._imageRenderer=new m(this,s,s===e),this.update()},{get:function(){return B.getAll(this)},set:function(t){B.setAll(t,this)&&this.update()},toDataURL:function(t){return this.canvas.toDataURL(t||this.mime)},update:function(){var t=new p({level:this.level,value:this.value});this._canvasRenderer.render(t),this._imageRenderer.render(t)}},{use:function(t){y.setService(t.getName(),t)}});Object.defineProperties(O.prototype,{canvas:{get:function(){return this._canvasRenderer.getElement()}},image:{get:function(){return this._imageRenderer.getElement()}}});var A=O,L=h.extend({getName:function(){}}).extend({createCanvas:function(){},createImage:function(){},getName:function(){return"element"},isCanvas:function(t){},isImage:function(t){}}).extend({createCanvas:function(){return document.createElement("canvas")},createImage:function(){return document.createElement("img")},isCanvas:function(t){return t instanceof HTMLCanvasElement},isImage:function(t){return t instanceof HTMLImageElement}});return A.use(new L),A}); + +//# sourceMappingURL=qrious.min.js.map \ No newline at end of file diff --git a/frappe/templates/includes/login/login.js b/frappe/templates/includes/login/login.js index afbfc8656f..85b12b980d 100644 --- a/frappe/templates/includes/login/login.js +++ b/frappe/templates/includes/login/login.js @@ -157,12 +157,36 @@ login.login_handlers = (function() { var login_handlers = { 200: function(data) { console.log(data); - if(data.token) { + if(data.verification) { login.set_indicator("{{ _("Success") }}", 'green'); - $('.login-content').empty().append($('
').html('
\ + $('.login-content').empty().append($('
').attr({'id':'otp_div'}).html('
\ Verification
\ \ ')); + if (!data.verification.setup_completed){ + var qrcode = $('
').attr('id','qrcode_div'); + var direction = $('
').attr('id','qr_info').text('Scan QR Code and enter the resulting code displayed'); + var qrcanvas = $(''); + qrcanvas.attr('id','qrcanvass'); + qrcode.append(direction); + qrcode.append(qrcanvas); + $('#otp_div').prepend(qrcode) + qr = new QRious({ + element: document.getElementById('qrcanvass'), + value: data.verification.totp_uri, + background: 'white', // background color + foreground: 'black', // foreground color + level: 'L', // Error correction level of the QR code + mime: 'image/png', // MIME type used to render + size: 200 + }); + } else { + var qrcode = $('
').attr('id','qrcode_div'); + var direction = $('
').attr('id','qr_info').text('Enter the code displayed in otp app under the appropriate account'); + direction.attr('style','padding-bottom:10px;'); + qrcode.append(direction); + $('#otp_div').prepend(qrcode) + } document.cookie = "tmp_id="+data.tmp_id; verify_token(); return false;