From 6b06f9e94313f13cd59a0cb70eca91d32f3ec5c0 Mon Sep 17 00:00:00 2001 From: ckosiegbu Date: Mon, 31 Jul 2017 00:02:53 +0100 Subject: [PATCH] Various fixes. Barcode email now sent only once instead of on each login. --- .../system_settings/system_settings.json | 128 +----------------- frappe/templates/includes/login/login.js | 58 +------- frappe/twofactor.py | 47 +++---- frappe/www/qrcode.html | 37 +++-- frappe/www/qrcode.py | 4 - 5 files changed, 59 insertions(+), 215 deletions(-) diff --git a/frappe/core/doctype/system_settings/system_settings.json b/frappe/core/doctype/system_settings/system_settings.json index 02e5eda0e5..338974cc47 100644 --- a/frappe/core/doctype/system_settings/system_settings.json +++ b/frappe/core/doctype/system_settings/system_settings.json @@ -1025,130 +1025,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"OTP App\" && doc.send_barcode_as_email==1", - "fieldname": "qr_code_email_subject", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "QR Code Email Subject", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"OTP App\" && doc.send_barcode_as_email==1", - "fieldname": "qr_code_email_body", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "QR Code Email Body", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"Email\"", - "fieldname": "two_factor_email_subject", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Two factor Email Subject", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"Email\"", - "fieldname": "two_factor_email_body", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Two factor Email Body", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1281,8 +1157,8 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2017-07-28 07:21:12.520227", - "modified_by": "Administrator", + "modified": "2017-07-29 13:33:49.201189", + "modified_by": "chude.osiegbu@manqala.com", "module": "Core", "name": "System Settings", "name_case": "", diff --git a/frappe/templates/includes/login/login.js b/frappe/templates/includes/login/login.js index 215dcfbc2e..cd65cdb250 100644 --- a/frappe/templates/includes/login/login.js +++ b/frappe/templates/includes/login/login.js @@ -269,18 +269,12 @@ var continue_otp_app = function(setup, qrcode){ request_otp(); var qrcode_div = $('
').attr({'id':'qrcode_div','style':'text-align:center;padding-bottom:15px;'}); - if (!setup){ - direction = $('
').attr('id','qr_info').text('Scan QR Code and enter the resulting code displayed. \ - You can use apps such as Google Authenticator, Lastpass Authenticator, Authy, Duo Mobile and others.'), - qrimg = $('').attr({ - 'src':'data:image/svg+xml;base64,' + qrcode, - 'style':'width:250px;height:250px;'}); - + if (setup){ + direction = $('
').attr('id','qr_info').text('Enter Code displayed in OTP App.'); qrcode_div.append(direction); - qrcode_div.append(qrimg); $('#otp_div').prepend(qrcode_div); } else { - direction = $('
').attr('id','qr_info').text('Enter Code displayed in OTP App'); + direction = $('
').attr('id','qr_info').text('OTP setup using OTP App was not completed. Please contact Administrator.'); qrcode_div.append(direction); $('#otp_div').prepend(qrcode_div); } @@ -291,36 +285,10 @@ var continue_sms = function(setup, prompt){ var sms_div = $('
').attr({'id':'sms_div','style':'padding-bottom:15px;text-align:center;'}); if (setup){ - direction = $('
').attr('id','sms_info').text('Enter phone number to send verification code'); - sms_div.append(direction); - sms_div.append($('
').attr({'id':'sms_code_div'}).html( - '
\ - \ - \ -

')); - + sms_div.append(prompt) $('#otp_div').prepend(sms_div); - - $('#submit_phone_no').on('click',function(){ - frappe.call({ - method: "frappe.core.doctype.user.user.send_token_via_sms", - args: {'phone_no': $('#phone_no').val(), 'tmp_id':data.tmp_id }, - freeze: true, - callback: function(r) { - if (r.message){ - $('#sms_div').empty().append( - '

SMS sent.
Enter verification code received


' - ); - } else { - $('#sms_div').empty().append( - '

SMS not sent


' - ); - } - } - }); - }) } else { - direction = $('
').attr('id','qr_info').text(prompt || 'SMS not sent'); + direction = $('
').attr('id','qr_info').text(prompt || 'SMS was not sent. Please contact Administrator.'); sms_div.append(direction); $('#otp_div').prepend(sms_div) } @@ -331,22 +299,10 @@ var continue_email = function(setup, prompt){ var email_div = $('
').attr({'id':'email_div','style':'padding-bottom:15px;text-align:center;'}); if (setup){ - email_div.append('

Verification code email will be sent to registered email address. Enter code received below

') + email_div.append(prompt) $('#otp_div').prepend(email_div); - frappe.call({ - method: "frappe.core.doctype.user.user.send_token_via_email", - args: {'tmp_id':data.tmp_id }, - callback: function(r) { - if (r.message){ - } else { - $('#email_div').empty().append( - '

Email not sent


' - ); - } - } - }); } else { - var direction = $('
').attr('id','qr_info').text(prompt || 'Verification code email not sent'); + var direction = $('
').attr('id','qr_info').text(prompt || 'Verification code email not sent. Please contact Administrator.'); email_div.append(direction); $('#otp_div').prepend(email_div); } diff --git a/frappe/twofactor.py b/frappe/twofactor.py index 3bcf8c5ce1..1c6b9c1053 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -130,12 +130,13 @@ def get_verification_obj(user,token,otp_secret): if verification_method == 'SMS': verification_obj = process_2fa_for_sms(user,token,otp_secret) elif verification_method == 'OTP App': - if should_send_barcode_as_email(): - verification_obj = process_2fa_for_email(user,token,otp_secret,otp_issuer,method='otp_app') + #check if this if the first time that the user is trying to login. If so, send an email + if not frappe.db.get_default(user + '_otplogin'): + verification_obj = process_2fa_for_email(user,token,otp_secret,otp_issuer,method='OTP App') else: verification_obj = process_2fa_for_otp_app(user,otp_secret,otp_issuer) elif verification_method == 'Email': - process_2fa_for_email(user,token,otp_secret,otp_issuer) + verification_obj = process_2fa_for_email(user,token,otp_secret,otp_issuer) return verification_obj @@ -146,7 +147,8 @@ def process_2fa_for_sms(user,token,otp_secret): status = send_token_via_sms(otp_secret,token=token, phone_no=phone) verification_obj = {'token_delivery': status, 'prompt': status and 'Enter verification code sent to {}'.format(phone[:4] + '******' + phone[-3:]), - 'method': 'SMS'} + 'method': 'SMS', + 'setup': status} return verification_obj def process_2fa_for_otp_app(user,otp_secret,otp_issuer): @@ -163,55 +165,50 @@ def process_2fa_for_otp_app(user,otp_secret,otp_issuer): 'setup': otp_setup_completed } return verification_obj -def process_2fa_for_email(user,token,otp_secret,otp_issuer,method='email'): +def process_2fa_for_email(user,token,otp_secret,otp_issuer,method='Email'): '''Process Email method for 2fa.''' + subject = None message = None status = True - if method == 'otp_app' and not frappe.db.get_default(user + '_otplogin'): + prompt = '' + if method == 'OTP App' and not frappe.db.get_default(user + '_otplogin'): + '''Sending one-time email for OTP App''' totp_uri = pyotp.TOTP(otp_secret).provisioning_uri(user, issuer_name=otp_issuer) qrcode_link = get_link_for_qrcode(user,totp_uri) message = get_email_body_for_qr_code({'qrcode_link':qrcode_link}) subject = get_email_subject_for_qr_code({'qrcode_link':qrcode_link}) - if method == 'email' or message: - status = send_token_via_email(user,token,otp_secret,otp_issuer,subject=subject,message=message) + prompt = 'Please check your registered email address for instructions on how to proceed. Do not close this window as you will have to return to it!!' + else: + '''Sending email verification''' + prompt = 'Verification code has been sent to your registered email address.' + status = send_token_via_email(user,token,otp_secret,otp_issuer,subject=subject,message=message) verification_obj = {'token_delivery': status, - 'prompt': status and 'Verification code has been sent to your registered email address', - 'method': 'Email'} + 'prompt': status and prompt, + 'method': 'Email', + 'setup': status} return verification_obj def get_email_subject_for_2fa(kwargs_dict): '''Get email subject for 2fa.''' - subject_template = 'Verifcation Code from Frappe Framework' - template = frappe.get_value('System Settings','System Settings','two_factor_email_subject') - if not template == '': - subject_template = template + subject_template = 'Verifcation Code from {}'.format(frappe.db.get_value('System Settings', 'System Settings', 'otp_issuer_name')) subject = render_string_template(subject_template,kwargs_dict) return subject def get_email_body_for_2fa(kwargs_dict): '''Get email body for 2fa.''' body_template = 'Use this token to login
{{otp}}' - template = frappe.get_value('System Settings','System Settings','two_factor_email_body') - if not template == '': - subject_template = template body = render_string_template(body_template,kwargs_dict) return body def get_email_subject_for_qr_code(kwargs_dict): '''Get QRCode email subject.''' - subject_template = 'Verification Code from Frappe Framework' - template = frappe.get_value('System Settings','System Settings','qr_code_email_subject') - if not template == '': - subject_template = template + subject_template = 'OTP Registration Code from {}'.format(frappe.db.get_value('System Settings', 'System Settings', 'otp_issuer_name')) subject = render_string_template(subject_template,kwargs_dict) return subject def get_email_body_for_qr_code(kwargs_dict): '''Get QRCode email body.''' - body_template = 'Scan the QRCode on this link to get token
{{qrcode_link}}' - template = frappe.get_value('System Settings','System Settings','qr_code_email_body') - if not template == '': - body_template = template + body_template = 'Please click on the following link and follow the instructions on the page.
{{qrcode_link}}' body = render_string_template(body_template,kwargs_dict) return body diff --git a/frappe/www/qrcode.html b/frappe/www/qrcode.html index 3edd1f7e18..3b9c81c531 100644 --- a/frappe/www/qrcode.html +++ b/frappe/www/qrcode.html @@ -1,12 +1,31 @@ +{% extends "templates/web.html" %} + +{% block title %}Register OTP Secret{% endblock %} + +{% block page_content %}
-
- Hi {{qr_code_user.first_name}}, Please scan QR Code and enter the resulting code displayed. - You can use apps such as Google Authenticator, Lastpass Authenticator, Authy, Duo Mobile and others. - -
-
- -
+ + + + + +
+
+

+ Hi {{qr_code_user.first_name}}, please perform the following actions: +

  • Open your authentication app on your mobile phone, +
  • Scan the QR Code and enter the resulting code displayed +
  • Return to the Verification screen and enter the code displayed by your authentication app +

    +

    Examples of Authentication Apps you can use are Google Authenticator, Lastpass Authenticator, Authy and Duo Mobile. +

    +
  • +
    +
    + +
    +
    -
    \ No newline at end of file +
    +{% endblock %} \ No newline at end of file diff --git a/frappe/www/qrcode.py b/frappe/www/qrcode.py index f87ede7597..636eabac35 100644 --- a/frappe/www/qrcode.py +++ b/frappe/www/qrcode.py @@ -14,10 +14,6 @@ no_cache = 1 def get_context(context): context.qr_code_user,context.qrcode_svg = get_user_svg_from_cache() - - - - def get_query_key(): '''Return query string arg.''' query_string = frappe.local.request.query_string