[ADD] auth_signup: merge in functionality of auth_reset_password

bzr revid: rco@openerp.com-20121203144424-39wrr5z78smswox2
This commit is contained in:
Raphael Collet 2012-12-03 15:44:24 +01:00
parent 772a721d85
commit 41ceffd52b
7 changed files with 120 additions and 10 deletions

View File

@ -22,15 +22,18 @@
{
'name': 'Signup',
'description': """
Allow users to sign up.
=======================
Allow users to sign up and reset their password
===============================================
""",
'author': 'OpenERP SA',
'version': '1.0',
'category': 'Authentication',
'website': 'http://www.openerp.com',
'installable': True,
'depends': ['base_setup'],
'depends': [
'base_setup',
'email_template',
],
'data': [
'auth_signup_data.xml',
'res_config.xml',

View File

@ -18,5 +18,20 @@
<field name="value" ref="default_template_user"/>
</record>
<!-- Email template for reset password -->
<record id="reset_password_email" model="email.template">
<field name="name">Reset Password</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="email_from"><![CDATA[${object.company_id.name} <${object.company_id.email}>]]></field>
<field name="email_to">${object.email}</field>
<field name="subject">Password reset</field>
<field name="body_html"><![CDATA[
<p>A password reset was requested for the OpenERP account linked to this email.</p>
<p>You may change your password by following <a href="${object.signup_url}">this link</a>.</p>
<p>Note: If you do not expect this, you can safely ignore this email.</p>]]></field>
</record>
</data>
</openerp>

View File

@ -19,10 +19,12 @@
#
##############################################################################
import logging
import urllib
import werkzeug
import openerp
from openerp.modules.registry import RegistryManager
from ..res_users import SignupError
_logger = logging.getLogger(__name__)
@ -56,4 +58,21 @@ class Controller(openerp.addons.web.http.Controller):
cr.commit()
return {}
@openerp.addons.web.http.httprequest
def reset_password(self, req, dbname, login):
""" retrieve user, and perform reset password """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
try:
res_users = registry.get('res.users')
res_users.reset_password(cr, openerp.SUPERUSER_ID, login)
cr.commit()
message = 'An email has been sent with credentials to reset your password'
except Exception as e:
# signup error
_logger.exception('error when resetting password')
message = e.message
params = [('action', 'login'), ('error_message', message)]
return werkzeug.utils.redirect("/#" + urllib.urlencode(params))
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -18,14 +18,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
from datetime import datetime, timedelta
import random
import time
import urllib
import urlparse
from openerp.osv import osv, fields
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
from openerp.tools.translate import _
class SignupError(Exception):
pass
@ -33,10 +34,12 @@ class SignupError(Exception):
def random_token():
# the token has an entropy of about 120 bits (6 bits/char * 20 chars)
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
return ''.join(random.choice(chars) for _ in xrange(20))
return ''.join(random.choice(chars) for i in xrange(20))
def now(**kwargs):
dt = datetime.now() + timedelta(**kwargs)
return dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
def now():
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
class res_partner(osv.Model):
_inherit = 'res.partner'
@ -58,7 +61,7 @@ class res_partner(osv.Model):
# when required, make sure the partner has a valid signup token
if context and context.get('signup_valid') and not partner.user_ids:
self.signup_prepare(cr, uid, [partner.id], context=context)
action_template = None
params = {
'action': urllib.quote(action),
@ -218,3 +221,31 @@ class res_users(osv.Model):
# create a copy of the template user (attached to a specific partner_id if given)
values['active'] = True
return self.copy(cr, uid, template_user_id, values, context=context)
def reset_password(self, cr, uid, login, context=None):
""" retrieve the user corresponding to login (login or email),
and reset their password
"""
user_ids = self.search(cr, uid, [('login', '=', login)], context=context)
if not user_ids:
user_ids = self.search(cr, uid, [('email', '=', login)], context=context)
if len(user_ids) != 1:
raise Exception('Reset password: invalid username or email')
return self.action_reset_password(cr, uid, user_ids, context=context)
def action_reset_password(self, cr, uid, ids, context=None):
""" create signup token for each user, and send their signup url by email """
# prepare reset password signup
res_partner = self.pool.get('res.partner')
partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context)]
res_partner.signup_prepare(cr, uid, partner_ids, expiration=now(days=+1), context=context)
# send email to users with their signup url
template = self.pool.get('ir.model.data').get_object(cr, uid, 'auth_signup', 'reset_password_email')
assert template._name == 'email.template'
for user in self.browse(cr, uid, ids, context):
if not user.email:
raise osv.except_osv(_("Cannot send email: user has no email address."), user.name)
self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, context=context)
return True

View File

@ -7,11 +7,23 @@
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<!-- add state field in header -->
<xpath expr="//sheet" position="before">
<header>
<field name="state" widget="statusbar"/>
</header>
</xpath>
<!-- add Reset Password button -->
<xpath expr="//sheet/*[1]" position="before">
<div class="oe_right oe_button_box">
<button string="Reset Password" type="object" name="action_reset_password"
help="Send an email to the user to (re)set their password."/>
</div>
</xpath>
<!-- hide field set_password -->
<field name="new_password" position="replace">
<field name="new_password" groups="base.group_no_one"/>
</field>
</field>
</record>

View File

@ -43,8 +43,13 @@ openerp.auth_signup = function(instance) {
.fail(self.on_token_failed)
});
}
// bind reset password link
this.$('a.oe_reset_password').click(this.do_reset_password);
return d;
},
on_token_loaded: function(result) {
// select the right the database
this.selected_db = result.db;
@ -66,6 +71,7 @@ openerp.auth_signup = function(instance) {
this.$("form input[name=login]").val(result.login || "");
}
},
on_token_failed: function(result, ev) {
if (ev) {
ev.preventDefault();
@ -74,6 +80,7 @@ openerp.auth_signup = function(instance) {
delete this.params.db;
delete this.params.token;
},
on_submit: function(ev) {
if (ev) {
ev.preventDefault();
@ -124,6 +131,26 @@ openerp.auth_signup = function(instance) {
this._super(ev);
}
},
});
do_reset_password: function(ev) {
if (ev) {
ev.preventDefault();
}
var db = this.$("form [name=db]").val();
var login = this.$("form input[name=login]").val();
if (!db) {
this.do_warn("Login", "No database selected !");
return false;
} else if (!login) {
this.do_warn("Login", "Please enter a username or email address.")
return false;
}
var params = {
dbname : db,
login: login,
};
var url = "/auth_signup/reset_password?" + $.param(params);
window.location = url;
},
});
};

View File

@ -24,6 +24,9 @@
<a class="oe_signup_show oe_signup_back" href="#">Back to Login</a>
</li>
</t>
<t t-jquery="form ul:first li:last" t-operation="after">
<li><a class="oe_reset_password" href="#">Reset password</a></li>
</t>
</t>
</templates>