[FIX-MOV] auth_totp, auth_totp_invite: move 2FA invite mail to new bridge module

Since 29db699e9b, auth_top depends of mail module, which lead to delay auth_totp
installation - not during DB creation anymore. As mail module is not installed
during DB creation, once an app that depends on mail is installed after DB
creation, auth_top module is finally installed and the session token now depends
auth_top module. As a result, the user is automatically logged out.

This commit moves the invite mail (and the dependance to 'mail' module) to a
new bridge module. Auth_totp module will now be reinstalled during DB creation
automatically.

Task-2638538
Parent Task-2487630
COM PR: odoo/odoo#76022
UPG PR: odoo/upgrade#2808

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
David Beguin
2021-09-06 15:47:23 +00:00
parent e38c91748d
commit eb2e328275
11 changed files with 147 additions and 97 deletions
+1 -2
View File
@@ -14,14 +14,13 @@ Note: logically, two-factor prevents password-based RPC access for users
where it is enabled. In order to be able to execute RPC scripts, the user
can setup API keys to replace their main password.
""",
'depends': ['web', 'mail'],
'depends': ['web'],
'category': 'Extra Tools',
'auto_install': True,
'data': [
'security/security.xml',
'security/ir.model.access.csv',
'data/ir_action_data.xml',
'data/mail_template_data.xml',
'views/res_users_views.xml',
'views/templates.xml',
'wizard/auth_totp_wizard_views.xml',
-25
View File
@@ -1,18 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Invite to user 2FA -->
<record model="ir.actions.server" id="action_invite_totp">
<field name="name">Invite to use two-factor authentication</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="binding_model_id" ref="base.model_res_users"/>
<field name="binding_view_types">list</field>
<field name="state">code</field>
<field name="code">
action = records.action_totp_invite()
</field>
<field name="groups_id" eval="[(4, ref('base.group_erp_manager'))]"/>
</record>
<!-- Action called from the contextual menu -->
<record model="ir.actions.server" id="action_disable_totp">
<field name="name">Disable two-factor authentication</field>
@@ -25,16 +12,4 @@
</field>
<field name="groups_id" eval="[(4, ref('base.group_erp_manager'))]"/>
</record>
<!--Action called when using the link in "Invite to use 2FA" mail-->
<record model="ir.actions.server" id="action_activate_two_factor_authentication">
<field name="name">Open two-factor authentication configuration</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="state">code</field>
<field name="code">
user = env.user
action = user.action_open_my_account_settings()
</field>
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
</record>
</odoo>
-36
View File
@@ -41,16 +41,6 @@ class Users(models.Model):
for r, v in zip(self, self.sudo()):
r.totp_enabled = bool(v.totp_secret)
def action_open_my_account_settings(self):
action = {
"name": _("Account Security"),
"type": "ir.actions.act_window",
"res_model": "res.users",
"views": [[self.env.ref('auth_totp.res_users_view_form_security').id, "form"]],
"res_id": self.id,
}
return action
def _rpc_api_keys_only(self):
# 2FA enabled means we can't allow password-based RPC
self.ensure_one()
@@ -89,32 +79,6 @@ class Users(models.Model):
_logger.info("2FA enable: SUCCESS for %s %r", self, self.login)
return True
def get_totp_invite_url(self):
return '/web#action=auth_totp.action_activate_two_factor_authentication'
def action_totp_invite(self):
invite_template = self.env.ref('auth_totp.mail_template_totp_invite')
users_to_invite = self.sudo().filtered(lambda user: not user.totp_secret)
for user in users_to_invite:
email_values = {
'email_from': self.env.user.email_formatted,
'author_id': self.env.user.partner_id.id,
}
invite_template.send_mail(user.id, force_send=True, email_values=email_values,
notif_layout='mail.mail_notification_light')
# Display a confirmation toaster
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': 'info',
'sticky': False,
'message': _("Invitation to use two-factor authentication sent for the following user(s): %s",
', '.join(users_to_invite.mapped('name'))),
}
}
@check_identity
def action_totp_disable(self):
logins = ', '.join(map(repr, self.mapped('login')))
@@ -31,8 +31,6 @@
disabled="1" type="object" class="fa fa-toggle-off o_auth_2fa_btn disabled" aria-label="Enable 2FA"></button>
<button attrs="{'invisible': &quot;[('id', '!=', uid)]&quot;}" name="action_totp_enable_wizard"
type="object" class="fa fa-toggle-off o_auth_2fa_btn disabled" aria-label="Enable 2FA"></button>
<button groups="base.group_erp_manager" attrs="{'invisible': &quot;[('id', '=', uid)]&quot;}"
name="action_totp_invite" string="Invite to use 2FA" type="object" class="btn btn-secondary"></button>
</div>
<button attrs="{'invisible': [('totp_enabled', '=', False)]}" name="action_totp_disable" type="object"
class="fa fa-toggle-on o_auth_2fa_btn text-primary enabled" aria-label="Disable 2FA"></button>
@@ -105,36 +103,4 @@
</group>
</field>
</record>
<!-- View used when coming from "invite to use 2FA" mail -->
<record model="ir.ui.view" id="res_users_view_form_security">
<field name="name">users preference: Account Security</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form_simple_modif"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<form position="attributes">
<attribute name='create'>0</attribute>
<attribute name='edit'>0</attribute>
<attribute name='delete'>0</attribute>
</form>
<h1 position="replace"/>
<xpath expr="//field[@name='image_1920']" position="replace"/>
<notebook position="replace">
<header>
</header>
<sheet>$0</sheet>
</notebook>
<notebook position="before">
<field name="image_1920" widget="image" class="oe_avatar" options="{'zoom': true, 'preview_image':'image_128'}"/>
<div class="oe_title">
<h1>
<field name="name" placeholder="Name" required="True" readonly="context.get('from_my_profile', False)"/>
</h1>
</div>
</notebook>
<page name="preferences_page" position="replace"></page>
<footer position="replace"/>
</field>
</record>
</odoo>
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
+21
View File
@@ -0,0 +1,21 @@
{
'name': '2FA Invite mail',
'description': """
2FA Invite mail
===============
Allow the users to invite another user to use Two-Factor authentication
by sending an email to the target user. This email redirect him to :
- the users security settings if the user is internal.
- the portal security settings page if the user is not internal.
""",
'depends': ['auth_totp', 'mail'],
'category': 'Extra Tools',
'auto_install': True,
'data': [
'data/ir_action_data.xml',
'data/mail_template_data.xml',
'views/res_users_views.xml',
],
'assets': {},
'license': 'LGPL-3',
}
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Invite to user 2FA -->
<record model="ir.actions.server" id="action_invite_totp">
<field name="name">Invite to use two-factor authentication</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="binding_model_id" ref="base.model_res_users"/>
<field name="binding_view_types">list</field>
<field name="state">code</field>
<field name="code">
action = records.action_totp_invite()
</field>
<field name="groups_id" eval="[(4, ref('base.group_erp_manager'))]"/>
</record>
<!--Action called when using the link in "Invite to use 2FA" mail-->
<record model="ir.actions.server" id="action_activate_two_factor_authentication">
<field name="name">Open two-factor authentication configuration</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="state">code</field>
<field name="code">
user = env.user
action = user.action_open_my_account_settings()
</field>
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
</record>
</odoo>
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import res_users
+44
View File
@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, models
class Users(models.Model):
_inherit = 'res.users'
def action_open_my_account_settings(self):
action = {
"name": _("Account Security"),
"type": "ir.actions.act_window",
"res_model": "res.users",
"views": [[self.env.ref('auth_totp_mail.res_users_view_form').id, "form"]],
"res_id": self.id,
}
return action
def get_totp_invite_url(self):
return '/web#action=auth_totp_mail.action_activate_two_factor_authentication'
def action_totp_invite(self):
invite_template = self.env.ref('auth_totp_mail.mail_template_totp_invite')
users_to_invite = self.sudo().filtered(lambda user: not user.totp_secret)
for user in users_to_invite:
email_values = {
'email_from': self.env.user.email_formatted,
'author_id': self.env.user.partner_id.id,
}
invite_template.send_mail(user.id, force_send=True, email_values=email_values,
notif_layout='mail.mail_notification_light')
# Display a confirmation toaster
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': 'info',
'sticky': False,
'message': _("Invitation to use two-factor authentication sent for the following user(s): %s",
', '.join(users_to_invite.mapped('name'))),
}
}
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="view_users_form">
<field name="name">res.users.view.form.inherit.auth.totp.mail</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_totp_enable_wizard']" position="after">
<button groups="base.group_erp_manager" attrs="{'invisible': &quot;[('id', '=', uid)]&quot;}"
name="action_totp_invite" string="Invite to use 2FA" type="object" class="btn btn-secondary"/>
</xpath>
</field>
</record>
<!-- View used when coming from "invite to use 2FA" mail -->
<record model="ir.ui.view" id="auth_totp_mail.res_users_view_form">
<field name="name">res.users.view.form.auth.totp.mail</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form_simple_modif"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<form position="attributes">
<attribute name='create'>0</attribute>
<attribute name='edit'>0</attribute>
<attribute name='delete'>0</attribute>
</form>
<h1 position="replace"/>
<xpath expr="//field[@name='image_1920']" position="replace"/>
<notebook position="replace">
<header>
</header>
<sheet>$0</sheet>
</notebook>
<notebook position="before">
<field name="image_1920" widget="image" class="oe_avatar" options="{'zoom': true, 'preview_image':'image_128'}"/>
<div class="oe_title">
<h1>
<field name="name" placeholder="Name" required="True" readonly="context.get('from_my_profile', False)"/>
</h1>
</div>
</notebook>
<page name="preferences_page" position="replace"></page>
<footer position="replace"/>
</field>
</record>
</odoo>