[FIX] auto_totp: tour & check RPC w/ token

* Not sure how the tour passed during merge as it would not be looking
  for the button in the right tab, it would fail locally, fix this
  issue by properly switching to the Account Security tab
* add the missing test of RPC (which should not work on an account
  with totp enabled)
* also reorder ops & fix comments: turns out `totp_login_enabled`
  checks that totp is enabled *then disables it*

closes odoo/odoo#55979

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
Xavier Morel
2020-08-17 09:30:53 +00:00
parent bfa00919cd
commit 17ae856cc1
2 changed files with 41 additions and 7 deletions
@@ -56,6 +56,10 @@ tour.register('totp_tour_setup', {
content: "Open preferences / profile screen",
trigger: '[data-menu=settings]',
run: 'click',
}, {
content: "Switch to security tab",
trigger: 'a[role=tab]:contains("Account Security")',
run: 'click',
}, {
content: "Check that the button has changed",
trigger: 'button:contains(Disable two-factor authentication)',
@@ -133,6 +137,10 @@ tour.register('totp_login_enabled', {
content: "Open preferences / profile screen",
trigger: '[data-menu=settings]',
run: 'click',
}, {
content: "Switch to security tab",
trigger: 'a[role=tab]:contains("Account Security")',
run: 'click',
}, {
content: "Check that the button has changed",
trigger: 'button:contains(Enable two-factor authentication)',
+33 -7
View File
@@ -1,11 +1,12 @@
import time
from xmlrpc.client import Fault
from passlib.totp import TOTP
from odoo import http
from odoo.exceptions import AccessDenied
from odoo.service import common as auth, model
from odoo.tests import tagged, HttpCase
from odoo.tests import tagged, HttpCase, get_db_name
from ..controllers.home import Home
@@ -15,8 +16,9 @@ class TestTOTP(HttpCase):
super().setUp()
totp = None
# test endpoint as doing totp on the client side is not really an option
# (needs sha1 and hmac + BE packing of 64b integers)
# might be possible to do client-side using `crypto.subtle` instead of
# this horror show, but requires working on 64b integers, & BigInt is
# significantly less well supported than crypto
def totp_hook(self, secret=None):
nonlocal totp
if totp is None:
@@ -43,14 +45,38 @@ class TestTOTP(HttpCase):
# 1. Enable 2FA
self.start_tour('/web', 'totp_tour_setup', login='demo')
# 2. Check 2FA is required
# 2. Verify that RPC is blocked because 2FA is on.
self.assertFalse(
self.xmlrpc_common.authenticate(get_db_name(), 'demo', 'demo', {}),
"Should not have returned a uid"
)
self.assertFalse(
self.xmlrpc_common.authenticate(get_db_name(), 'demo', 'demo', {'interactive': True}),
'Trying to fake the auth type should not work'
)
uid = self.env.ref('base.user_demo').id
with self.assertRaisesRegex(Fault, r'Access Denied'):
self.xmlrpc_object.execute_kw(
get_db_name(), uid, 'demo',
'res.users', 'read', [uid, ['login']]
)
# 3. Check 2FA is required and disable it
self.start_tour('/', 'totp_login_enabled', login=None)
# 3. TODO: verify that RPC is blocked because 2FA is on.
# 4. Finally, disable 2FA otherwise we can't re-login
# 4. Finally, check that 2FA is in fact disabled
self.start_tour('/', 'totp_login_disabled', login=None)
# 5. Check that rpc is now re-allowed
uid = self.xmlrpc_common.authenticate(get_db_name(), 'demo', 'demo', {})
self.assertEqual(uid, self.env.ref('base.user_demo').id)
[r] = self.xmlrpc_object.execute_kw(
get_db_name(), uid, 'demo',
'res.users', 'read', [uid, ['login']]
)
self.assertEqual(r['login'], 'demo')
def test_totp_administration(self):
self.start_tour('/web', 'totp_tour_setup', login='demo')
self.start_tour('/web', 'totp_admin_disables', login='admin')