Bläddra i källkod

fix website user login bug refactor JS

version-14
crossxcell99 8 år sedan
förälder
incheckning
aa45ffcac6
5 ändrade filer med 144 tillägg och 239 borttagningar
  1. +21
    -15
      frappe/auth.py
  2. +15
    -18
      frappe/core/doctype/user/user.py
  3. +1
    -2
      frappe/hooks.py
  4. +0
    -6
      frappe/public/js/frappe/qrious.min.js
  5. +107
    -198
      frappe/templates/includes/login/login.js

+ 21
- 15
frappe/auth.py Visa fil

@@ -124,7 +124,7 @@ class LoginManager:
query = """select name from `tabRole` where two_factor_auth=1
and name in ("All",{0}) limit 1""".format(', '.join('\"{}\"'.format(i.role) for \
i in user_obj.roles))
two_factor_user_role = len(frappe.db.sql(query))
two_factor_user_role = len(frappe.db.sql(query))

self.otp_secret = frappe.db.get_default(self.user + '_otpsecret')
if not self.otp_secret:
@@ -152,12 +152,10 @@ class LoginManager:
else:
otp_setup_completed = False

verification_obj = {'token_delivery': True,
'prompt': False,
'totp_uri': totp_uri,
verification_obj = {'totp_uri': totp_uri,
'method': 'OTP App',
'qrcode': get_qr_svg_code(totp_uri),
'otp_setup_completed': otp_setup_completed}
'setup': otp_setup_completed }
elif self.verification_method == 'Email':
status = self.send_token_via_email(token=token,otpsecret=self.otp_secret)
verification_obj = {'token_delivery': status,
@@ -174,9 +172,13 @@ class LoginManager:
usr = frappe.form_dict.get('usr')
pwd = frappe.form_dict.get('pwd')

# set increased expiry time for SMS and Email
if self.verification_method in ['SMS', 'Email']:
frappe.cache().set(tmp_id + '_token',token)
frappe.cache().expire(tmp_id + '_token',300)
expiry_time = 300
frappe.cache().set(tmp_id + '_token', token)
frappe.cache().expire(tmp_id + '_token', expiry_time)
else:
expiry_time = 180

frappe.cache().set(tmp_id + '_usr', usr)
frappe.cache().set(tmp_id + '_pwd', pwd)
@@ -184,7 +186,7 @@ class LoginManager:
frappe.cache().set(tmp_id + '_user', self.user)

for field in [tmp_id + nm for nm in ['_usr', '_pwd', '_otp_secret', '_user']]:
frappe.cache().expire(field,180)
frappe.cache().expire(field, expiry_time)

frappe.local.response['verification'] = verification_obj
frappe.local.response['tmp_id'] = tmp_id
@@ -232,7 +234,7 @@ class LoginManager:
try:
otp_secret = frappe.cache().get(tmp_id + '_otp_secret')
if not otp_secret:
frappe.throw('Login session expired, please refresh page to try again')
frappe.throw('Login session expired. Refresh page to try again')
except AttributeError:
return False

@@ -395,21 +397,24 @@ class LoginManager:
def clear_cookies(self):
clear_cookies()

def send_token_via_sms(self,otpsecret,token=None,phone_no=None):
def send_token_via_sms(self, otpsecret, token=None, phone_no=None):
try:
from erpnext.setup.doctype.sms_settings.sms_settings import send_request
except:
return False

if not phone_no:
return False

ss = frappe.get_doc('SMS Settings', 'SMS Settings')
if not ss.sms_gateway_url:
return False
hotp = pyotp.HOTP(otpsecret)
args = {ss.message_parameter: 'verification code is {}'.format(hotp.at(int(token)))}
for d in ss.get("parameters"):
args[d.parameter] = d.value

if not phone_no:
return False
args[ss.receiver_parameter] = phone_no

status = send_request(ss.sms_gateway_url, args)
@@ -419,13 +424,14 @@ class LoginManager:
else:
return False

def send_token_via_email(self,token,otpsecret):
user_email = frappe.db.get_value('User',self.user, 'email')
def send_token_via_email(self, token, otpsecret):
user_email = frappe.db.get_value('User', self.user, 'email')
if not user_email:
return False
hotp = pyotp.HOTP(otpsecret)
frappe.sendmail(recipients=user_email, sender=None, subject='Verification Code',
message='<p>Your verification code is {}</p>'.format(hotp.at(int(token))),delayed=False, retry=3)
message='<p>Your verification code is {}</p>'.format(hotp.at(int(token))),
delayed=False, retry=3)
return True

class CookieManager:


+ 15
- 18
frappe/core/doctype/user/user.py Visa fil

@@ -928,17 +928,18 @@ def update_gravatar(name):

@frappe.whitelist(allow_guest=True)
def send_token_via_sms(tmp_id,phone_no=None,user=None):
from erpnext.setup.doctype.sms_settings.sms_settings import send_request
try:
from erpnext.setup.doctype.sms_settings.sms_settings import send_request
except:
return False

if not frappe.cache().ttl(tmp_id + '_token'):
return False

token = frappe.cache().get(tmp_id + '_token')

ss = frappe.get_doc('SMS Settings', 'SMS Settings')
if not ss.sms_gateway_url:
return False

token = frappe.cache().get(tmp_id + '_token')
args = {ss.message_parameter: 'verification code is {}'.format(token)}

for d in ss.get("parameters"):
@@ -956,7 +957,6 @@ def send_token_via_sms(tmp_id,phone_no=None,user=None):
return False

args[ss.receiver_parameter] = usr_phone

status = send_request(ss.sms_gateway_url, args)

if 200 <= status < 300:
@@ -971,22 +971,19 @@ def send_token_via_email(tmp_id,token=None):

user = frappe.cache().get(tmp_id + '_user')
count = token or frappe.cache().get(tmp_id + '_token')

if ((not user) or (user == 'None') or (not count)):
return False

otpsecret = frappe.cache().get(tmp_id + '_otp_secret')
hotp = pyotp.HOTP(otpsecret)
user_email = frappe.db.get_value('User',user, 'email')
if not user_email:
return False
frappe.sendmail(recipients=user_email, sender=None, subject='Verification Code',
message='<p>Your verification code is {0}</p>'.format(hotp.at(int(count))),delayed=False, retry=3)
return True

#@frappe.whitelist(allow_guest=True)
#def set_verification_method(tmp_id,method=None):
# user = frappe.cache().get(tmp_id + '_user')
# if ((not user) or (user == 'None') or (not method)):
# return False
# frappe.db.set_value('User', user, 'two_factor_method', method)
# frappe.db.commit()
otpsecret = frappe.cache().get(tmp_id + '_otp_secret')
hotp = pyotp.HOTP(otpsecret)

frappe.sendmail(
recipients=user_email, sender=None, subject='Verification Code',
message='<p>Your verification code is {0}</p>'.format(hotp.at(int(count))),
delayed=False, retry=3)

return True

+ 1
- 2
frappe/hooks.py Visa fil

@@ -40,8 +40,7 @@ app_include_css = [
]

web_include_js = [
"website_script.js",
"assets/js/qrious.min.js"
"website_script.js"
]

bootstrap = "assets/frappe/css/bootstrap.css"


+ 0
- 6
frappe/public/js/frappe/qrious.min.js
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 107
- 198
frappe/templates/includes/login/login.js Visa fil

@@ -160,204 +160,16 @@ login.login_handlers = (function() {
if(data.verification) {
login.set_indicator("{{ _("Success") }}", 'green');

var continue_otp = function(setup_completed,method_prompt){

$('.login-content').empty().append($('<div>').attr({'id':'otp_div'}).html(
'<form class="form-verify">\
<div class="page-card-head">\
<span class="indicator blue" data-text="Verification">Verification</span>\
</div>\
<input type="text" id="login_token" class="form-control" placeholder="Verification Code" required autocomplete="off" autofocus="">\
<button type="submit" class="btn btn-sm btn-primary btn-block" id="verify_token">Verify</button>\
</form>'));

verify_token();

if (!setup_completed){
var qrcode = $('<div>')
qrcode.attr('id','qrcode_div');
qrcode.css('text-align','center');

var direction = $('<div>').attr('id','qr_info').text(method_prompt || 'Scan QR Code and enter the resulting code displayed');

var qrimg = $('<img>');
qrimg.attr('src','data:image/svg+xml;base64,' + data.verification.qrcode);
qrcode.append(direction);
qrcode.append(qrimg);
$('#otp_div').prepend(qrcode);
} else {
var qrcode = $('<div>').attr('id','qrcode_div');
var direction = $('<div>').attr('id','qr_info').text(method_prompt || 'Enter Code displayed in OTP App');
direction.attr('style','padding-bottom:10px;');
qrcode.append(direction);
$('#otp_div').prepend(qrcode)
}
}

var continue_sms = function(setup_completed,method_prompt){

$('.login-content').empty().append($('<div>').attr({'id':'otp_div'}).html(
'<form class="form-verify">\
<div class="page-card-head">\
<span class="indicator blue" data-text="Verification">Verification</span>\
</div>\
<input type="text" id="login_token" class="form-control" placeholder="Verification Code" required="" autofocus="">\
<button class="btn btn-sm btn-primary btn-block" id="verify_token">Verify</button>\
</form>'));

verify_token();

if (!setup_completed){
var sms_div = $('<div>').attr({'id':'sms_div','style':'margin-bottom: 20px;'});
var direction = $('<div>').attr({'id':'sms_info','style':'margin-bottom: 15px;'}).text('Enter phone number to send verification code');
sms_div.append(direction);
sms_div.append($('<div>').attr({'id':'sms_code_div'}).html(
'<div class="form-group text-center">\
<input type="text" id="phone_no" class="form-control" placeholder="2347001234567" required="" autofocus="">\
<button class="btn btn-sm btn-primary" id="submit_phone_no" >Send SMS</button>\
</div><hr>'));

$('#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(
'<p class="lead">SMS sent.<br><small><small>Enter verification code received</small></small></p><hr>'
);
} else {
$('#sms_div').empty().append(
'<p class="lead">SMS not sent</p><hr>'
);
}
}
});
})
} else {
var smscode = $('<div>').attr('id','smscode_div');
var direction = $('<div>').attr('id','qr_info').text(method_prompt || 'Enter verification code sent to registered phone number');
direction.attr('style','padding-bottom:10px;');
smscode.append(direction);
$('#otp_div').prepend(smscode)
}
}

var continue_email = function(setup_completed,method_prompt){

$('.login-content').empty().append($('<div>').attr({'id':'otp_div'}).html(
'<form class="form-verify">\
<div class="page-card-head">\
<span class="indicator blue" data-text="Verification">Verification</span>\
</div>\
<input type="text" id="login_token" class="form-control" placeholder="Verification Code" required="" autofocus="">\
<button class="btn btn-sm btn-primary btn-block" id="verify_token">Verify</button>\
</form>'));

verify_token();

if (!setup_completed){
var email_div = $('<div>').attr({'id':'email_div','style':'margin-bottom: 20px;'});
email_div.append('<p>Verification code email will be sent to registered email address. Enter code received below</p>')

$('#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(
'<p>Email not sent</p><hr>'
);
}
}
});
} else {
if (method_prompt){
var emailcode = $('<div>').attr('id','emailcode_div');
var direction = $('<div>').attr('id','qr_info').text(method_prompt || 'Verification code email will be sent to registered email address. Enter code received below');
direction.attr('style','padding-bottom:10px;');
emailcode.append(direction);
$('#otp_div').prepend(emailcode);
} else {
var emailcode = $('<div>').attr('id','emailcode_div');
var direction = $('<div>').attr('id','qr_info').text('Verification code email not sent');
direction.attr('style','padding-bottom:10px;');
emailcode.append(direction);
$('#otp_div').prepend(emailcode)
}

}
}

if (data.verification.method_first_time){
// $('.login-content').empty().append('<div id="verification_method">\
// <div>\
// <p class="lead">Select verification Method <br>\
// <small><small><small class="text-muted">method may be changed later in settings</small></small></small></p>\
// </div>\
// <div class="form-check">\
// <label class="form-check-label">\
// <input class="form-check-input" type="radio" name="method" value="OTP App" checked>\
// OTP App\
// </label>\
// </div>\
// <div class="form-check">\
// <label class="form-check-label">\
// <input class="form-check-input" type="radio" name="method" value="SMS">\
// SMS\
// </label>\
// </div>\
// <div class="form-check disabled">\
// <label class="form-check-label">\
// <input class="form-check-input" type="radio" name="method" value="Email">\
// Email\
// </label>\
// </div>\
// <button id="submit_method" class="btn btn-sm btn-primary">Continue</button>\
// </div>')

// if (data.verification.restrict_method){
// $('input[name=method]').each(function(){
// if ($(this).val() != data.verification.restrict_method){
// $(this).attr('disabled',true)
// }
// })
// }
// $('#submit_method').on('click',function(event){
if (data.verification.method == 'OTP App'){
continue_otp(setup_completed=false);
} else if (data.verification.method == 'SMS'){
continue_sms(setup_completed=false);
} else if (data.verification.method == 'Email'){
continue_email(setup_completed=false);
}
document.cookie = "tmp_id="+data.tmp_id;

// frappe.call({
// method: "frappe.core.doctype.user.user.set_verification_method",
// args: {'tmp_id':data.tmp_id, 'method': $('input[name=method]:checked').val()},
// callback: function(r) { }
// });
// });
} else {
if (data.verification.method == 'OTP App'){
console.log(data.verification.totp_uri)
continue_otp(setup_completed = data.verification.otp_setup_completed);
} else if (data.verification.method == 'SMS'){
continue_sms(setup_completed=true, method_prompt=data.verification.prompt);
console.log('SMS');
} else if (data.verification.method == 'Email'){
continue_sms(setup_completed=true, method_prompt=data.verification.prompt);
}
if (data.verification.method == 'OTP App'){
continue_otp_app(data.verification.setup, data.verification.qrcode);
} else if (data.verification.method == 'SMS'){
continue_sms(data.verification.setup, data.verification.prompt);
} else if (data.verification.method == 'Email'){
continue_sms(data.verification.setup, data.verification.prompt);
}

document.cookie = "tmp_id="+data.tmp_id;
//verify_token();
return false;

} else if(data.message == 'Logged In'){
@@ -410,10 +222,7 @@ login.login_handlers = (function() {

frappe.ready(function() {

login.bind_events();
console.log("Why");


if (!window.location.hash) {
window.location.hash = "#login";
@@ -440,3 +249,103 @@ var verify_token = function(event) {
return false;
});
}

var request_otp = function(r){
$('.login-content').empty().append($('<div>').attr({'id':'twofactor_div'}).html(
'<form class="form-verify">\
<div class="page-card-head">\
<span class="indicator blue" data-text="Verification">Verification</span>\
</div>\
<div id="otp_div"></div>\
<input type="text" id="login_token" autocomplete="off" class="form-control" placeholder="Verification Code" required="" autofocus="">\
<button class="btn btn-sm btn-primary btn-block" id="verify_token">Verify</button>\
</form>'));
// add event handler for submit button
verify_token();
}

var continue_otp_app = function(setup, qrcode){
request_otp();
var qrcode_div = $('<div>').attr({'id':'qrcode_div','style':'text-align:center;padding-bottom:15px;'});

if (!setup){
direction = $('<div>').attr('id','qr_info').text('Scan QR Code and enter the resulting code displayed' ),
qrimg = $('<img>').attr({
'src':'data:image/svg+xml;base64,' + qrcode,
'style':'width:250px;height:250px;'});

qrcode_div.append(direction);
qrcode_div.append(qrimg);
$('#otp_div').prepend(qrcode_div);
} else {
direction = $('<div>').attr('id','qr_info').text('Enter Code displayed in OTP App');
qrcode_div.append(direction);
$('#otp_div').prepend(qrcode_div);
}
}

var continue_sms = function(setup, prompt){
request_otp();
var sms_div = $('<div>').attr({'id':'sms_div','style':'padding-bottom:15px;text-align:center;'});

if (!setup){
direction = $('<div>').attr('id','sms_info').text('Enter phone number to send verification code');
sms_div.append(direction);
sms_div.append($('<div>').attr({'id':'sms_code_div'}).html(
'<div class="form-group text-center">\
<input type="text" id="phone_no" class="form-control" placeholder="2347001234567" required="" autofocus="">\
<button class="btn btn-sm btn-primary" id="submit_phone_no" >Send SMS</button>\
</div><hr>'));

$('#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(
'<p class="lead">SMS sent.<br><small><small>Enter verification code received</small></small></p><hr>'
);
} else {
$('#sms_div').empty().append(
'<p class="lead">SMS not sent</p><hr>'
);
}
}
});
})
} else {
direction = $('<div>').attr('id','qr_info').text(prompt || 'SMS not sent');
sms_div.append(direction);
$('#otp_div').prepend(sms_div)
}
}

var continue_email = function(setup, prompt){
request_otp();
var email_div = $('<div>').attr({'id':'email_div','style':'padding-bottom:15px;text-align:center;'});

if (!setup){
email_div.append('<p>Verification code email will be sent to registered email address. Enter code received below</p>')
$('#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(
'<p>Email not sent</p><hr>'
);
}
}
});
} else {
var direction = $('<div>').attr('id','qr_info').text(prompt || 'Verification code email not sent');
email_div.append(direction);
$('#otp_div').prepend(email_div);
}
}

Laddar…
Avbryt
Spara