summaryrefslogtreecommitdiff
path: root/addons/auth_totp/static
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/auth_totp/static
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/auth_totp/static')
-rw-r--r--addons/auth_totp/static/tests/totp_flow.js247
1 files changed, 247 insertions, 0 deletions
diff --git a/addons/auth_totp/static/tests/totp_flow.js b/addons/auth_totp/static/tests/totp_flow.js
new file mode 100644
index 00000000..eea24504
--- /dev/null
+++ b/addons/auth_totp/static/tests/totp_flow.js
@@ -0,0 +1,247 @@
+odoo.define('auth_totp.tours', function(require) {
+"use strict";
+
+const tour = require('web_tour.tour');
+const ajax = require('web.ajax');
+
+function openRoot() {
+ return [{
+ content: "return to client root to avoid race condition",
+ trigger: 'body',
+ run() {
+ $('body').addClass('wait');
+ window.location = '/web';
+ }
+ }, {
+ content: "wait for client reload",
+ trigger: 'body:not(.wait)',
+ run() {}
+ }];
+}
+function openUserProfileAtSecurityTab() {
+ return [{
+ content: 'Open user account menu',
+ trigger: '.o_user_menu .oe_topbar_name',
+ run: 'click',
+ }, {
+ 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',
+ }];
+}
+
+tour.register('totp_tour_setup', {
+ test: true,
+ url: '/web'
+}, [...openUserProfileAtSecurityTab(), {
+ content: "Open totp wizard",
+ trigger: 'button[name=totp_enable_wizard]',
+}, {
+ content: "Check that we have to enter enhanced security mode",
+ trigger: 'div:contains("confirm your password")',
+ run: () => {},
+}, {
+ content: "Input password",
+ trigger: '[name=password]',
+ run: 'text demo', // FIXME: better way to do this?
+}, {
+ content: "Confirm",
+ trigger: "button:contains(Confirm Password)",
+}, {
+ content: "Check the wizard has opened",
+ trigger: 'div:contains("Scan the image below")',
+ run: () => {}
+}, {
+ content: "Get secret from collapsed div",
+ trigger: 'a:contains("show the code")',
+ run(helpers) {
+ const secret = this.$anchor.closest('div').find('code').text();
+ ajax.jsonRpc('/totphook', 'call', {
+ secret
+ }).then((token) => {
+ helpers._text(helpers._get_action_values('input[name=code]'), token);
+ helpers._click(helpers._get_action_values('button.btn-primary:contains(Enable)'));
+ $('body').addClass('got-token')
+ });
+ }
+}, {
+ content: 'wait for rpc',
+ trigger: 'body.got-token',
+ run() {}
+},
+...openRoot(),
+...openUserProfileAtSecurityTab(),
+{
+ content: "Check that the button has changed",
+ trigger: 'button:contains(Disable two-factor authentication)',
+ run: () => {}
+}]);
+
+tour.register('totp_login_enabled', {
+ test: true,
+ url: '/'
+}, [{
+ content: "check that we're on the login page or go to it",
+ trigger: 'input#login, a:contains(Sign in)'
+}, {
+ content: "input login",
+ trigger: 'input#login',
+ run: 'text demo',
+}, {
+ content: 'input password',
+ trigger: 'input#password',
+ run: 'text demo',
+}, {
+ content: "click da button",
+ trigger: 'button:contains("Log in")',
+}, {
+ content: "expect totp screen",
+ trigger: 'label:contains(Authentication Code)',
+}, {
+ content: "input code",
+ trigger: 'input[name=totp_token]',
+ run(helpers) {
+ ajax.jsonRpc('/totphook', 'call', {}).then((token) => {
+ helpers._text(helpers._get_action_values(), token);
+ // FIXME: is there a way to put the button as its own step trigger without
+ // the tour straight blowing through and not waiting for this?
+ helpers._click(helpers._get_action_values('button:contains("Verify")'));
+ });
+ }
+}, {
+ content: "check we're logged in",
+ trigger: ".o_user_menu .oe_topbar_name",
+ run: () => {}
+},
+// now go and disable totp would be annoying to do in a separate tour
+// because we'd need to login & totp again as HttpCase.authenticate can't
+// succeed w/ totp enabled
+...openUserProfileAtSecurityTab(),
+{
+ content: "Open totp wizard",
+ trigger: 'button[name=totp_disable]',
+}, {
+ content: "Check that we have to enter enhanced security mode",
+ trigger: 'div:contains("confirm your password")',
+ run: () => {},
+}, {
+ content: "Input password",
+ trigger: '[name=password]',
+ run: 'text demo', // FIXME: better way to do this?
+}, {
+ content: "Confirm",
+ trigger: "button:contains(Confirm Password)",
+},
+...openRoot(),
+...openUserProfileAtSecurityTab(),
+{
+ content: "Check that the button has changed",
+ trigger: 'button:contains(Enable two-factor authentication)',
+ run: () => {}
+}]);
+
+tour.register('totp_login_disabled', {
+ test: true,
+ url: '/'
+}, [{
+ content: "check that we're on the login page or go to it",
+ trigger: 'input#login, a:contains(Sign in)'
+}, {
+ content: "input login",
+ trigger: 'input#login',
+ run: 'text demo',
+}, {
+ content: 'input password',
+ trigger: 'input#password',
+ run: 'text demo',
+}, {
+ content: "click da button",
+ trigger: 'button:contains("Log in")',
+},
+// normally we'd end the tour here as it's all we care about but there are a
+// bunch of ongoing queries from the loading of the web client which cause
+// issues, so go and open the preferences / profile screen to make sure
+// everything settles down
+...openUserProfileAtSecurityTab(),
+]);
+
+const columns = {};
+tour.register('totp_admin_disables', {
+ test: true,
+ url: '/web'
+}, [tour.stepUtils.showAppsMenuItem(), {
+ content: 'Go to settings',
+ trigger: '[data-menu-xmlid="base.menu_administration"]'
+}, {
+ content: 'Wait for page',
+ trigger: '.o_menu_brand:contains("Settings")',
+ run: () => {}
+}, {
+ content: "Open Users menu",
+ trigger: '[data-menu-xmlid="base.menu_users"]'
+}, {
+ content: "Open Users view",
+ trigger: '[data-menu-xmlid="base.menu_action_res_users"]',
+ run: function (helpers) {
+ // funny story: the users view we're trying to reach, sometimes we're
+ // already there, but if we re-click the next step executes before the
+ // action has the time to re-load, the one after that doesn't, and our
+ // selection get discarded by the action reloading, so here try to
+ // see if we're already on the users action through the breadcrumb and
+ // just close the menu if so
+ const $crumb = $('.breadcrumb');
+ if ($crumb.text().indexOf('Users') === -1) {
+ // on general settings page, click menu
+ helpers.click();
+ } else {
+ // else close menu
+ helpers.click($('[data-menu-xmlid="base.menu_users"]'));
+ }
+ }
+}, {
+ content: "Find Demo User",
+ trigger: 'td.o_data_cell:contains("demo")',
+ run: function (helpers) {
+ const $titles = this.$anchor.closest('table').find('tr:first th');
+ for (let i=0; i<$titles.length; ++i) {
+ columns[$titles[i].getAttribute('data-name')] = i;
+ }
+ const $row = this.$anchor.closest('tr');
+ const sel = $row.find('.o_list_record_selector input[type=checkbox]');
+ const totp = $row[0].children[columns['totp_enabled']].querySelector('input');
+ if (totp.checked) {
+ helpers.click(sel);
+ }
+ }
+}, {
+ content: "Open Actions menu",
+ trigger: 'button.o_dropdown_toggler_btn:contains("Action")'
+}, {
+ content: "Select totp remover",
+ trigger: 'a.dropdown-item:contains(Disable TOTP on users)'
+}, { // enhanced security yo
+ content: "Check that we have to enter enhanced security mode",
+trigger: 'div:contains("confirm your password")',
+ run: () => {},
+}, {
+ content: "Input password",
+ trigger: '[name=password]',
+ run: 'text admin', // FIXME: better way to do this?
+}, {
+ content: "Confirm",
+ trigger: "button:contains(Confirm Password)",
+}, {
+ content: "check that demo user has been de-totp'd",
+ trigger: "td.o_data_cell:contains(demo)",
+ run: function () {
+ const totpcell = this.$anchor.closest('tr')[0].children[columns['totp_enabled']];
+ if (totpcell.querySelector('input').checked) {
+ throw new Error("totp should have been disabled on demo user");
+ }
+ }
+}])
+});