[MERGE] [IMP] User creation flow

Addons-side branch:
- mail_mail.send() and email_template.send() are now able to get the ir_mail_server exceptions up using a new argument (raise_exception, as for access rights); default behavior of all calls to those methods is not changed;
- auth_signup
-- handles the (re)set password email sending possible failure by cancelling the reset password values; having issues with the outgoing email server should not prevent from creating users but should not consider the email was sent if it was not the case;
-- instead of having reset_password in context to send the reset password email, we now have a no_reset_password to avoid sending a reset password email. If not present, the reset password email is sent when creating a user. This allows to avoid adding the key in the context of each res.users many2one;
-- res.users form view (re)set password buttons now have the oe_link class

bzr revid: tde@openerp.com-20130604155001-5twq3pdru12eh1x6
This commit is contained in:
Thibault Delavallée 2013-06-04 17:50:01 +02:00
commit af0c4c6045
9 changed files with 39 additions and 20 deletions

View File

@ -23,6 +23,7 @@ import random
from urllib import urlencode
from urlparse import urljoin
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
from openerp.osv import osv, fields
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
@ -103,6 +104,9 @@ class res_partner(osv.Model):
def action_signup_prepare(self, cr, uid, ids, context=None):
return self.signup_prepare(cr, uid, ids, context=context)
def signup_cancel(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'signup_token': False, 'signup_type': False, 'signup_expiration': False}, context=context)
def signup_prepare(self, cr, uid, ids, signup_type="signup", expiration=False, context=None):
""" generate a new token for the partners with the given validity, if necessary
:param expiration: the expiration datetime of the token (string, optional)
@ -202,7 +206,7 @@ class res_users(osv.Model):
})
if partner.company_id:
values['company_id'] = partner.company_id.id
values['company_ids'] = [(6,0,[partner.company_id.id])]
values['company_ids'] = [(6, 0, [partner.company_id.id])]
self._signup_create_user(cr, uid, values, context=context)
else:
# no token, sign up an external user
@ -259,25 +263,26 @@ class res_users(osv.Model):
pass
if not bool(template):
template = self.pool.get('ir.model.data').get_object(cr, uid, 'auth_signup', 'reset_password_email')
mail_obj = self.pool.get('mail.mail')
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)
mail_id = self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, True, context=context)
mail_state = mail_obj.read(cr, uid, mail_id, ['state'], context=context)
if mail_state and mail_state['state'] == 'exception':
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Cannot send email: no outgoing email server configured.\nYou can configure it under %(menu:base_setup.menu_general_configuration)s."), context)
else:
return True
try:
self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, force_send=True, raise_exception=True, context=context)
except Exception:
raise
def create(self, cr, uid, values, context=None):
if context is None:
context = {}
# overridden to automatically invite user to sign up
user_id = super(res_users, self).create(cr, uid, values, context=context)
user = self.browse(cr, uid, user_id, context=context)
if context and context.get('reset_password') and user.email:
ctx = dict(context, create_user=True)
self.action_reset_password(cr, uid, [user.id], context=ctx)
if user.email and not context.get('no_reset_password'):
context.update({'create_user': True})
try:
self.action_reset_password(cr, uid, [user.id], context=context)
except MailDeliveryException:
self.pool.get('res.partner').signup_cancel(cr, uid, [user.partner_id.id], context=context)
return user_id

View File

@ -31,9 +31,11 @@
<!-- add Reset Password button -->
<xpath expr="//div[@class='oe_right oe_button_box']//button" position="replace">
<button string="Send Reset Password Instructions"
class="oe_link"
type="object" name="action_reset_password"
attrs="{'invisible': [('state', '!=', 'active')]}"/>
<button string="Send an Invitation Email"
class="oe_link"
type="object" name="action_reset_password" context="{'create_user': 1}"
attrs="{'invisible': [('state', '!=', 'new')]}"/>
</xpath>

View File

@ -358,7 +358,7 @@ class email_template(osv.osv):
values['attachment_ids'] = attachment_ids
return values
def send_mail(self, cr, uid, template_id, res_id, force_send=False, context=None):
def send_mail(self, cr, uid, template_id, res_id, force_send=False, raise_exception=False, context=None):
"""Generates a new mail message for the given template and record,
and schedules it for delivery through the ``mail`` module's scheduler.
@ -400,7 +400,7 @@ class email_template(osv.osv):
mail_mail.write(cr, uid, msg_id, {'attachment_ids': [(6, 0, attachment_ids)]}, context=context)
if force_send:
mail_mail.send(cr, uid, [msg_id], context=context)
mail_mail.send(cr, uid, [msg_id], raise_exception=raise_exception, context=context)
return msg_id
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -27,6 +27,7 @@ from urlparse import urljoin
from openerp import tools
from openerp import SUPERUSER_ID
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
from openerp.osv import fields, osv
from openerp.tools.translate import _
@ -292,7 +293,7 @@ class mail_mail(osv.Model):
'email_to': email_to,
}
def send(self, cr, uid, ids, auto_commit=False, context=None):
def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None):
""" Sends the selected emails immediately, ignoring their current
state (mails that have already been sent should not be passed
unless they should actually be re-sent).
@ -303,6 +304,8 @@ class mail_mail(osv.Model):
:param bool auto_commit: whether to force a commit of the mail status
after sending each mail (meant only for scheduler processing);
should never be True during normal transactions (default: False)
:param bool raise_exception: whether to raise an exception if the
email sending process has failed
:return: True
"""
ir_mail_server = self.pool.get('ir.mail_server')
@ -348,9 +351,16 @@ class mail_mail(osv.Model):
# see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1
if mail_sent:
self._postprocess_sent_message(cr, uid, mail, context=context)
except Exception:
except Exception as e:
_logger.exception('failed sending mail.mail %s', mail.id)
mail.write({'state': 'exception'})
if raise_exception:
if isinstance(e, AssertionError):
# get the args of the original error, wrap into a value and throw a MailDeliveryException
# that is an except_orm, with name and value as arguments
value = '. '.join(e.args)
raise MailDeliveryException(_("Mail Delivery Failed"), value)
raise
if auto_commit == True:
cr.commit()

View File

@ -26,7 +26,7 @@
<field name="signature" position="before">
<field name="notification_email_send"/>
</field>
<field name="email" position="after">
<field name="signature" position="before">
<field name="alias_domain" invisible="1"/>
<field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
</field>

View File

@ -172,7 +172,7 @@ class wizard_user(osv.osv_memory):
@return: browse record of model res.users
"""
res_users = self.pool.get('res.users')
create_context = dict(context or {}, noshortcut=True) # to prevent shortcut creation
create_context = dict(context or {}, noshortcut=True, no_reset_password=True) # to prevent shortcut creation
values = {
'login': extract_email(wizard_user.email),
'partner_id': wizard_user.partner_id.id,

View File

@ -101,7 +101,7 @@
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<data>
<xpath expr="//field[@name='email']" position="after">
<xpath expr="//field[@name='tz']" position="after">
<field name="default_section_id"/>
</xpath>
</data>

View File

@ -230,6 +230,7 @@ class share_wizard(osv.TransientModel):
current_user = user_obj.browse(cr, UID_ROOT, uid, context=context)
# modify context to disable shortcuts when creating share users
context['noshortcut'] = True
context['no_reset_password'] = True
created_ids = []
existing_ids = []
if wizard_data.user_type == 'emails':

View File

@ -191,7 +191,8 @@ Thanks,''') % (name, self.pool.get('ir.config_parameter').get_param(cr, uid, 'we
'action_id': act_id[0],
'survey_id': [[6, 0, survey_ids]]
}
user = user_ref.create(cr, uid, res_data)
create_ctx = dict(context, no_reset_password=True)
user = user_ref.create(cr, uid, res_data, context=create_ctx)
if user not in new_user:
new_user.append(user)
created+= "- %s (Login: %s, Password: %s)\n" % (partner.name or _('Unknown'),\