Browse Source

[password] reset via link, added update page for portal user

version-14
Rushabh Mehta 12 years ago
parent
commit
3eab31b9a9
8 changed files with 179 additions and 55 deletions
  1. +74
    -17
      core/doctype/profile/profile.py
  2. +10
    -1
      core/doctype/profile/profile.txt
  3. +1
    -1
      webnotes/auth.py
  4. +0
    -23
      webnotes/handler.py
  5. +2
    -1
      webnotes/webutils.py
  6. +22
    -11
      website/js/website.js
  7. +1
    -1
      website/templates/includes/login.js
  8. +69
    -0
      website/templates/pages/update-password.html

+ 74
- 17
core/doctype/profile/profile.py View File

@@ -85,8 +85,8 @@ class DocType:
def update_new_password(self):
"""update new password if set"""
if self.doc.new_password:
from webnotes.auth import update_password
update_password(self.doc.name, self.doc.new_password)
from webnotes.auth import _update_password
_update_password(self.doc.name, self.doc.new_password)
if self.in_insert:
webnotes.msgprint("New user created. - %s" % self.doc.name)
@@ -94,11 +94,18 @@ class DocType:
self.send_welcome_mail(self.doc.new_password)
webnotes.msgprint("Sent welcome mail.")
else:
self.password_reset_mail(self.doc.new_password)
webnotes.msgprint("Password updated.")
self.password_update_mail(self.doc.new_password)
webnotes.msgprint("New Password Emailed.")
webnotes.conn.set(self.doc, 'new_password', '')
def reset_password(self):
from webnotes.utils import random_string, get_request_site_address

key = random_string(32)
webnotes.conn.set_value("Profile", self.doc.name, "reset_password_key", key)
self.password_reset_mail(get_request_site_address() + "/update-password?key=" + key)
def get_other_system_managers(self):
return webnotes.conn.sql("""select distinct parent from tabUserRole user_role
where role='System Manager' and docstatus<2
@@ -111,25 +118,37 @@ class DocType:
return (self.doc.first_name or '') + \
(self.doc.first_name and " " or '') + (self.doc.last_name or '')

def password_reset_mail(self, password):
def password_reset_mail(self, link):
"""reset password"""
txt = """
## Password Reset

Dear %(first_name)s,

Your password has been reset. Your new password is:
Please click on the following link to update your new password:

password: %(password)s
<a href="%(link)s">%(link)s</a>

To login to %(product)s, please go to:
Thank you,<br>
%(user_fullname)s
"""
self.send_login_mail("Your " + webnotes.get_config().get("app_name") + " password has been reset",
txt, {"link": link})
def password_update_mail(self, password):
txt = """
## Password Update Notification

%(login_url)s
Dear %(first_name)s,

Your password has been updated. Here is your new password: %(new_password)s

Thank you,<br>
%(user_fullname)s
"""
self.send_login_mail("Your " + webnotes.get_config().get("app_name") + " password has been reset", txt, password)
self.send_login_mail("Your " + webnotes.get_config().get("app_name") + " password has been reset",
txt, {"password": "password"})
def send_welcome_mail(self, password):
"""send welcome mail to user with password and login url"""
@@ -151,9 +170,10 @@ To login to your new %(product)s account, please go to:
Thank you,<br>
%(user_fullname)s
"""
self.send_login_mail("Welcome to " + webnotes.get_config().get("app_name"), txt, password)
self.send_login_mail("Welcome to " + webnotes.get_config().get("app_name"), txt,
{ "password": password })

def send_login_mail(self, subject, txt, password):
def send_login_mail(self, subject, txt, add_args):
"""send mail with login details"""
import os
@@ -168,13 +188,14 @@ Thank you,<br>
args = {
'first_name': self.doc.first_name or self.doc.last_name or "user",
'user': self.doc.name,
'password': password,
'company': webnotes.conn.get_default('company') or webnotes.get_config().get("app_name"),
'login_url': get_request_site_address(),
'product': webnotes.get_config().get("app_name"),
'user_fullname': full_name
}
args.update(add_args)
sender = webnotes.session.user not in ("Administrator", "Guest") and webnotes.session.user or None
sendmail_md(recipients=self.doc.email, sender=sender, subject=subject, msg=txt % args)
@@ -301,10 +322,31 @@ def update_profile(fullname, password=None):
webnotes.add_cookies["full_name"] = fullname
if password:
from webnotes.auth import update_password
update_password(webnotes.session.user, password)
from webnotes.auth import _update_password
_update_password(webnotes.session.user, password)

return _("Updated")

@webnotes.whitelist(allow_guest=True)
def update_password(new_password, key=None, old_password=None):
# verify old password
if old_password:
user = webnotes.session.user
if not webnotes.conn.sql("""select user from __Auth where password=password(%s)
and user=%s""", (old_password, user)):
return _("Cannot Update: Incorrect Password")
else:
if key:
user = webnotes.conn.get_value("Profile", {"reset_password_key":key})
if not user:
return _("Cannot Update: Incorrect / Expired Link.")
from webnotes.auth import _update_password
_update_password(user, new_password)
webnotes.conn.set_value("Profile", user, "reset_password_key", "")
return _("Password Updated")
@webnotes.whitelist(allow_guest=True)
def sign_up(email, full_name):
@@ -331,7 +373,22 @@ def sign_up(email, full_name):
profile.ignore_permissions = True
profile.insert()
return _("Registration Details Emailed.")

@webnotes.whitelist(allow_guest=True)
def reset_password(user):
user = webnotes.form_dict.get('user', '')
if user in ["demo@erpnext.com", "Administrator"]:
return "Not allowed"
if webnotes.conn.sql("""select name from tabProfile where name=%s""", user):
# Hack!
webnotes.session["user"] = "Administrator"
profile = webnotes.bean("Profile", user)
profile.get_controller().reset_password()
return "Password reset details sent to your email."
else:
return "No such user (%s)" % user

def profile_query(doctype, txt, searchfield, start, page_len, filters):
from webnotes.widgets.reportview import get_match_cond
return webnotes.conn.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)


+ 10
- 1
core/doctype/profile/profile.txt View File

@@ -2,7 +2,7 @@
{
"creation": "2013-03-07 11:54:44",
"docstatus": 0,
"modified": "2013-09-06 12:10:25",
"modified": "2013-09-16 14:47:47",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -177,6 +177,15 @@
"no_copy": 1,
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "reset_password_key",
"fieldtype": "Data",
"hidden": 1,
"label": "Reset Password Key",
"print_hide": 1,
"read_only": 1
},
{
"depends_on": "eval:!doc.__islocal",
"doctype": "DocField",


+ 1
- 1
webnotes/auth.py View File

@@ -263,7 +263,7 @@ class CookieManager:
webnotes.cookies[k][b'expires'] = expires.encode('utf-8')


def update_password(user, password):
def _update_password(user, password):
webnotes.conn.sql("""insert into __Auth (user, `password`)
values (%s, password(%s))
on duplicate key update `password`=password(%s)""", (user,


+ 0
- 23
webnotes/handler.py View File

@@ -76,29 +76,6 @@ def uploadfile():
ret = None

return ret
@webnotes.whitelist(allow_guest=True)
def reset_password(user):
from webnotes.model.code import get_obj
from webnotes.utils import random_string
user = webnotes.form_dict.get('user', '')
if user in ["demo@erpnext.com", "Administrator"]:
return "Not allowed"
if webnotes.conn.sql("""select name from tabProfile where name=%s""", user):
new_password = random_string(8)
webnotes.conn.sql("""update `__Auth` set password=password(%s)
where `user`=%s""", (new_password, user))

# Hack!
webnotes.session["user"] = "Administrator"
profile = get_obj("Profile", user)
profile.password_reset_mail(new_password)
return "Password has been reset and sent to your email id."
else:
return "No such user (%s)" % user


def handle():
"""handle request"""


+ 2
- 1
webnotes/webutils.py View File

@@ -205,7 +205,8 @@ def get_website_settings():
"webnotes": webnotes,
"utils": webnotes.utils,
"post_login": [
{"label": "Logout", "url": "server.py?cmd=web_logout", "icon": "icon-signout"},
{"label": "Reset Password", "url": "update-password", "icon": "icon-key"},
{"label": "Logout", "url": "server.py?cmd=web_logout", "icon": "icon-signout"}
]
})


+ 22
- 11
website/js/website.js View File

@@ -4,16 +4,6 @@ if(!window.wn) wn = {};


wn = {
show_message: function(text, icon) {
if(!icon) icon="icon-refresh icon-spin";
treemapper.hide_message();
$('<div class="message-overlay"></div>')
.html('<div class="content"><i class="'+icon+' text-muted"></i><br>'
+text+'</div>').appendTo(document.body);
},
hide_message: function(text) {
$('.message-overlay').remove();
},
call: function(opts) {
wn.prepare_call(opts);
$.ajax({
@@ -106,6 +96,26 @@ wn = {
get_sid: function() {
var sid = getCookie("sid");
return sid && sid!=="Guest";
},
get_modal: function(title, body_html) {
var modal = $('<div class="modal" style="overflow: auto;">\
<div class="modal-dialog">\
<div class="modal-content">\
<div class="modal-header">\
<a type="button" class="close" \
data-dismiss="modal" aria-hidden="true">&times;</a>\
<h4 class="modal-title">'+title+'</h4>\
</div>\
<div class="modal-body ui-front">'+body_html+'\
</div>\
</div>\
</div>\
</div>').appendTo(document.body);
return modal;
},
msgprint: function(html, title) {
return wn.get_modal(title || "Message", html).modal("show");
}
}

@@ -235,4 +245,5 @@ wn.send_message = function(opts, btn) {
args: opts,
callback: opts.callback
});
}
}


+ 1
- 1
website/templates/includes/login.js View File

@@ -27,7 +27,7 @@ login.do_login = function(){
return false;
}
} else if(window.is_forgot) {
args.cmd = "reset_password";
args.cmd = "core.doctype.profile.profile.reset_password";
args.user = ($("#login_id").val() || "").trim();
if(!args.user) {


+ 69
- 0
website/templates/pages/update-password.html View File

@@ -0,0 +1,69 @@
{% extends base_template %}

{% block content %}
<div style="max-width: 750px;">
<div class="row" style="margin-top: 40px; margin-bottom: 20px">
<div class="col-sm-offset-3 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="icon-key"></i> Reset Password</h4>
</div>
<div class="panel-body">
<div class="form-group">
<input id="old_password" type="password"
class="form-control" placeholder="Old Password">
</div>
<div class="form-group">
<input id="new_password" type="password"
class="form-control" placeholder="New Password">
</div>
<div class="form-group">
<button type="submit" id="update"
class="btn btn-primary">Update</button>
</div>
</div>
</div>
</div>
</div>
</div>

<script>

$(document).ready(function() {
if(get_url_arg("key")) {
$("#old_password").parent().toggle(false);
}
$("#update").click(function() {
var args = {
key: get_url_arg("key") || "",
old_password: $("#old_password").val(),
new_password: $("#new_password").val()
}
if(!args.old_password && !args.key) {
wn.msgprint("Old Password Required.");
return;
}
if(!args.new_password) {
wn.msgprint("New Password Required.")
return;
}
wn.call({
type: "POST",
method: "core.doctype.profile.profile.update_password",
btn: $("#update"),
args: args,
callback: function(r) {
if(r.message) {
$("input").val("");
wn.msgprint(r.message);
}
}
})
})
});

</script>
{% endblock %}

Loading…
Cancel
Save