[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', 'name': 'Signup',
'description': """ 'description': """
Allow users to sign up. Allow users to sign up and reset their password
======================= ===============================================
""", """,
'author': 'OpenERP SA', 'author': 'OpenERP SA',
'version': '1.0', 'version': '1.0',
'category': 'Authentication', 'category': 'Authentication',
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'installable': True, 'installable': True,
'depends': ['base_setup'], 'depends': [
'base_setup',
'email_template',
],
'data': [ 'data': [
'auth_signup_data.xml', 'auth_signup_data.xml',
'res_config.xml', 'res_config.xml',

View File

@ -18,5 +18,20 @@
<field name="value" ref="default_template_user"/> <field name="value" ref="default_template_user"/>
</record> </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> </data>
</openerp> </openerp>

View File

@ -19,10 +19,12 @@
# #
############################################################################## ##############################################################################
import logging import logging
import urllib
import werkzeug
import openerp import openerp
from openerp.modules.registry import RegistryManager from openerp.modules.registry import RegistryManager
from ..res_users import SignupError from ..res_users import SignupError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -56,4 +58,21 @@ class Controller(openerp.addons.web.http.Controller):
cr.commit() cr.commit()
return {} 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: # 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/> # along with this program. If not, see <http://www.gnu.org/licenses/>
# #
############################################################################## ##############################################################################
from datetime import datetime, timedelta
import random import random
import time
import urllib import urllib
import urlparse import urlparse
from openerp.osv import osv, fields from openerp.osv import osv, fields
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval from openerp.tools.safe_eval import safe_eval
from openerp.tools.translate import _
class SignupError(Exception): class SignupError(Exception):
pass pass
@ -33,10 +34,12 @@ class SignupError(Exception):
def random_token(): def random_token():
# the token has an entropy of about 120 bits (6 bits/char * 20 chars) # the token has an entropy of about 120 bits (6 bits/char * 20 chars)
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' 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): class res_partner(osv.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
@ -218,3 +221,31 @@ class res_users(osv.Model):
# create a copy of the template user (attached to a specific partner_id if given) # create a copy of the template user (attached to a specific partner_id if given)
values['active'] = True values['active'] = True
return self.copy(cr, uid, template_user_id, values, context=context) 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="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/> <field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<!-- add state field in header -->
<xpath expr="//sheet" position="before"> <xpath expr="//sheet" position="before">
<header> <header>
<field name="state" widget="statusbar"/> <field name="state" widget="statusbar"/>
</header> </header>
</xpath> </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> </field>
</record> </record>

View File

@ -43,8 +43,13 @@ openerp.auth_signup = function(instance) {
.fail(self.on_token_failed) .fail(self.on_token_failed)
}); });
} }
// bind reset password link
this.$('a.oe_reset_password').click(this.do_reset_password);
return d; return d;
}, },
on_token_loaded: function(result) { on_token_loaded: function(result) {
// select the right the database // select the right the database
this.selected_db = result.db; this.selected_db = result.db;
@ -66,6 +71,7 @@ openerp.auth_signup = function(instance) {
this.$("form input[name=login]").val(result.login || ""); this.$("form input[name=login]").val(result.login || "");
} }
}, },
on_token_failed: function(result, ev) { on_token_failed: function(result, ev) {
if (ev) { if (ev) {
ev.preventDefault(); ev.preventDefault();
@ -74,6 +80,7 @@ openerp.auth_signup = function(instance) {
delete this.params.db; delete this.params.db;
delete this.params.token; delete this.params.token;
}, },
on_submit: function(ev) { on_submit: function(ev) {
if (ev) { if (ev) {
ev.preventDefault(); ev.preventDefault();
@ -124,6 +131,26 @@ openerp.auth_signup = function(instance) {
this._super(ev); 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> <a class="oe_signup_show oe_signup_back" href="#">Back to Login</a>
</li> </li>
</t> </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> </t>
</templates> </templates>