)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"efa59caad228ea6064c8002f26ae62463105e952","unresolved":true,"context_lines":[{"line_number":34,"context_line":"To activited :"},{"line_number":35,"context_line":"OPENSTACK_KEYSTONE_MFA_TOTP_ENABLED \u003d True"},{"line_number":36,"context_line":"and an user with a role in OPENSTACK_MFA_ROLES"},{"line_number":37,"context_line":"exemple: OPENSTACK_MFA_ROLES \u003d [ \u0027admin\u0027, \u0027mfa-role\u0027]"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"Closes-Bug: #2142657"},{"line_number":40,"context_line":"Blueprint: #enabling-mfa-dashboard"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":10,"id":"44378719_b6a4bd84","line":37,"updated":"2026-03-10 13:09:27.000000000","message":"```suggestion\nexample: OPENSTACK_MFA_ROLES \u003d [ \u0027admin\u0027, \u0027mfa-role\u0027]\n```","commit_id":"d8a9f4207b15382f388c6cf636c3e1338e44006d"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"7211aea7272b3619c56951b39dbbc0ce648ecb35","unresolved":false,"context_lines":[{"line_number":34,"context_line":"To activited :"},{"line_number":35,"context_line":"OPENSTACK_KEYSTONE_MFA_TOTP_ENABLED \u003d True"},{"line_number":36,"context_line":"and an user with a role in OPENSTACK_MFA_ROLES"},{"line_number":37,"context_line":"exemple: OPENSTACK_MFA_ROLES \u003d [ \u0027admin\u0027, \u0027mfa-role\u0027]"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"Closes-Bug: #2142657"},{"line_number":40,"context_line":"Blueprint: #enabling-mfa-dashboard"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":10,"id":"dc1540e8_e588f91f","line":37,"in_reply_to":"44378719_b6a4bd84","updated":"2026-03-10 13:22:39.000000000","message":"Done","commit_id":"d8a9f4207b15382f388c6cf636c3e1338e44006d"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"0b13d149f906ff0dee4aba11372e7fb72662e4dd","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"1f68b7ab_66733849","updated":"2026-02-25 12:01:31.000000000","message":"Hello,\n\nPlease add release note.","commit_id":"b5df04b4f699dae8927b382ca4d60789cd7bb858"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"d06a9de429d1504560bf9c6076ddd7934456da24","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"44e2b285_1bd7bbfc","in_reply_to":"1f68b7ab_66733849","updated":"2026-02-25 15:46:04.000000000","message":"https://review.opendev.org/c/openstack/horizon/+/977978?usp\u003dsearch","commit_id":"b5df04b4f699dae8927b382ca4d60789cd7bb858"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"939c4c4ac1502a196d2003eb2cba5f0d322b163a","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":3,"id":"1878cd91_b8c7008d","updated":"2026-02-25 16:04:50.000000000","message":"Please add support translation in JS files.","commit_id":"1b1bf574379f132759adc41493b1c038844a4fef"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"635b4dcf768364e23cb496af4f7ba94a76f0a41a","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":3,"id":"d858ad8f_363e2488","in_reply_to":"1878cd91_b8c7008d","updated":"2026-03-06 15:33:05.000000000","message":"I removed the JS files to have a code architecture that is as similar as possible to the rest of the project.","commit_id":"1b1bf574379f132759adc41493b1c038844a4fef"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"335afe120d3327e7658f3a198bfe00394e5e2ece","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"fc30cf0f_769cacae","in_reply_to":"d858ad8f_363e2488","updated":"2026-03-10 13:07:48.000000000","message":"Done","commit_id":"1b1bf574379f132759adc41493b1c038844a4fef"},{"author":{"_account_id":8648,"name":"Radomir Dopieralski","email":"openstack@dopieralski.pl","username":"thesheep"},"change_message_id":"1091f21b6444ad51d6d4c499de9c455d603202fe","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"fe2a7d14_eeb1f6d1","updated":"2026-04-09 15:03:24.000000000","message":"Some comments I have by just looking at the code. I\u0027m going to test it some more, and probably have more notes. Thank you for working on it.","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"ce3fe2fc3fbeea0e2a50a845af2b8c0495b50818","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":21,"id":"1a91cd04_ddc90b68","updated":"2026-06-11 11:47:31.000000000","message":"Hello @blasseye@ikmail.com, thank you for your patch and your patience!\nThere are a few things where I would ask for a fix or clarification.\n\nA few points from a user/visual perspective.\n1) In ```Enable Multi-Factor Authentication``` form:\n```I understand and have an authenticator app ready``` (checkbox) has an asterisk (meaning it is required) but the asterisk is weirdly located under the checkbox. It looks really odd. I tried different sizes of windows, still the same. Would be possible to move it beside of the checkbox?\n\n2) The first tab is ```Security Notice```, this part of the form has buttons ```Cancel``` and ```Enable MFA``` both immediately available, but ```Enable MFA``` click does nothing. You need to go through all the tabs (```Security Notice```, ```TOTP Credential \u0026 QR Code```, ```Verify Code```), fill them and then the ```Enable MFA``` button in the form works and does something.\nSo I would prefer to change the ```Enable MFA``` button in the form to the ```Next``` button for the first two tabs, so this button will move you to the next tab and only the last one will have an ```Enable MFA``` button for example the same like it is for create network. Buttons cancel, back, next (which turn to create at the last tab). WDYT? I think that it will be much more user friendly.","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"d3326fc6049332cdd20bbdbb32402760d7ad9a43","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"e2f3f948_1d4296aa","updated":"2026-06-10 23:56:10.000000000","message":"Hello, I think more friendly add information about Google app 😉","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"fbe4ac23d549311a0b5206c7801d230ae5afacdc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"7ef03998_4942607d","in_reply_to":"179695e1_b67fddff","updated":"2026-06-22 08:15:16.000000000","message":"Done","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"abf13164af8b3fb67dc3e1780527f37931c5ad0d","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":21,"id":"179695e1_b67fddff","in_reply_to":"1a91cd04_ddc90b68","updated":"2026-06-15 09:50:00.000000000","message":"Thank you for prompting me to look into this; I had overlooked the “wizard \u003d True” option.","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"8e9a4d30fb10afcd2e959c157baa1b1cccaf5fbe","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"33722346_1bcb6a51","in_reply_to":"e2f3f948_1d4296aa","updated":"2026-06-12 07:04:39.000000000","message":"I intentionally chose to focus only on free and open-source applications. I\u0027m open to change.","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"466ea40568d8456bc115ce53650bcdf3d2bb0732","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"0e11c693_a99f6754","updated":"2026-06-15 12:27:48.000000000","message":"recheck","commit_id":"afa88253b0dab0249f5a8af89680af4c7ecc70ee"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"ae2cc5c2bb01ac0e06387bfefa56e15f6e4f4fe7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"60980022_186a8ce6","updated":"2026-06-15 11:17:18.000000000","message":"recheck","commit_id":"afa88253b0dab0249f5a8af89680af4c7ecc70ee"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"8e3df954dfd3a584a837fe837a35f90d187e4a26","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":25,"id":"e51bb8b2_a76e24dc","updated":"2026-06-18 22:31:04.000000000","message":"I found a few typos in the commit message\n\"activited\" -\u003e \"activated\"\n\"Custome\" -\u003e \"Custom\"\n\"exemple\" -\u003e\"example\"\n\nfirst pass at testing the creation of my new credential using FreeOTP is working nicely.","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"601712b92361e487f57293b493f64271b1a4d5b0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":25,"id":"d33f957e_c7ffc26d","in_reply_to":"b330b4bd_6e2fe0a9","updated":"2026-06-22 08:32:53.000000000","message":"Done","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"fbe4ac23d549311a0b5206c7801d230ae5afacdc","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":25,"id":"b330b4bd_6e2fe0a9","in_reply_to":"e51bb8b2_a76e24dc","updated":"2026-06-22 08:15:16.000000000","message":"Thanks, I\u0027ll take care of it.","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"8af7770f77072c7cbfffaf487b75f1a36cb4f988","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":27,"id":"e00d6563_2a598051","updated":"2026-06-24 12:19:47.000000000","message":"Miss click...","commit_id":"d894ea4f64fcc75a6942ac444520b91864d01dd5"}],"doc/source/configuration/settings.rst":[{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"2a4c34fc6e07b5d038c6aacc851ee520b40da556","unresolved":true,"context_lines":[{"line_number":652,"context_line":"be present in ``AUTHENTICATION_PLUGINS``."},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"OPENSTACK_MFA_ROLES"},{"line_number":655,"context_line":"-----------------------------------"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"1dc5a441_5e177c8a","line":655,"updated":"2026-03-17 10:48:52.000000000","message":"```suggestion\n-------------------\n```","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"6a1bba05e16e17c743bf15f2a3e416d07b02a637","unresolved":false,"context_lines":[{"line_number":652,"context_line":"be present in ``AUTHENTICATION_PLUGINS``."},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"OPENSTACK_MFA_ROLES"},{"line_number":655,"context_line":"-----------------------------------"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"23cc0e28_eb6cd386","line":655,"in_reply_to":"1dc5a441_5e177c8a","updated":"2026-03-17 11:14:26.000000000","message":"Done","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"883b30a953b375f26fbbc82610579808bd9f0b08","unresolved":false,"context_lines":[{"line_number":652,"context_line":"be present in ``AUTHENTICATION_PLUGINS``."},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"OPENSTACK_MFA_ROLES"},{"line_number":655,"context_line":"-----------------------------------"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"d428d66d_f65df49b","line":655,"in_reply_to":"23cc0e28_eb6cd386","updated":"2026-03-17 11:18:01.000000000","message":"Patchset 16*","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"2a4c34fc6e07b5d038c6aacc851ee520b40da556","unresolved":true,"context_lines":[{"line_number":654,"context_line":"OPENSTACK_MFA_ROLES"},{"line_number":655,"context_line":"-----------------------------------"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""},{"line_number":659,"context_line":"Default: ``[\u0027admin\u0027]``"},{"line_number":660,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"a48e234d_6a13eaca","line":657,"updated":"2026-03-17 10:48:52.000000000","message":"Already 2026.2","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"6a1bba05e16e17c743bf15f2a3e416d07b02a637","unresolved":false,"context_lines":[{"line_number":654,"context_line":"OPENSTACK_MFA_ROLES"},{"line_number":655,"context_line":"-----------------------------------"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""},{"line_number":659,"context_line":"Default: ``[\u0027admin\u0027]``"},{"line_number":660,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"b2c963e1_951d7f3c","line":657,"in_reply_to":"a48e234d_6a13eaca","updated":"2026-03-17 11:14:26.000000000","message":"Done","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"883b30a953b375f26fbbc82610579808bd9f0b08","unresolved":false,"context_lines":[{"line_number":654,"context_line":"OPENSTACK_MFA_ROLES"},{"line_number":655,"context_line":"-----------------------------------"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""},{"line_number":659,"context_line":"Default: ``[\u0027admin\u0027]``"},{"line_number":660,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"ff6d3733_4444082d","line":657,"in_reply_to":"b2c963e1_951d7f3c","updated":"2026-03-17 11:18:01.000000000","message":"Patchset 16*","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"2a4c34fc6e07b5d038c6aacc851ee520b40da556","unresolved":true,"context_lines":[{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""},{"line_number":659,"context_line":"Default: ``[\u0027admin\u0027]``"},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"List of roles that are allowed to activate Multi-Factor Authentication (MFA)."},{"line_number":662,"context_line":"Users with one of these roles can enable MFA using password + TOTP"}],"source_content_type":"text/x-rst","patch_set":15,"id":"97734ded_d15e0919","line":659,"updated":"2026-03-17 10:48:52.000000000","message":"Hmm, may be member too?","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"d5ea6f6ecb21c086216cb8e883f0926157bc8549","unresolved":false,"context_lines":[{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""},{"line_number":659,"context_line":"Default: ``[\u0027admin\u0027]``"},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"List of roles that are allowed to activate Multi-Factor Authentication (MFA)."},{"line_number":662,"context_line":"Users with one of these roles can enable MFA using password + TOTP"}],"source_content_type":"text/x-rst","patch_set":15,"id":"b05ba593_43c92c9c","line":659,"in_reply_to":"77232752_acf166fe","updated":"2026-03-25 15:03:25.000000000","message":"Done","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"6a1bba05e16e17c743bf15f2a3e416d07b02a637","unresolved":true,"context_lines":[{"line_number":656,"context_line":""},{"line_number":657,"context_line":".. versionadded:: ..."},{"line_number":658,"context_line":""},{"line_number":659,"context_line":"Default: ``[\u0027admin\u0027]``"},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"List of roles that are allowed to activate Multi-Factor Authentication (MFA)."},{"line_number":662,"context_line":"Users with one of these roles can enable MFA using password + TOTP"}],"source_content_type":"text/x-rst","patch_set":15,"id":"77232752_acf166fe","line":659,"in_reply_to":"97734ded_d15e0919","updated":"2026-03-17 11:14:26.000000000","message":"By default, I only assign the “admin” role, because for the dashboard to function properly, the user must have the necessary role to modify the options --enable-multi-factor-auth and --multi-factor-auth-rule and view their TOTP credentials, and by default in Keystone, only users with the “admin” role have this permission.","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"2a4c34fc6e07b5d038c6aacc851ee520b40da556","unresolved":true,"context_lines":[{"line_number":663,"context_line":"authentication."},{"line_number":664,"context_line":""},{"line_number":665,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER"},{"line_number":666,"context_line":"-----------------------------------"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":".. versionadded:: ..."},{"line_number":669,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"6b929de5_564eaee2","line":666,"updated":"2026-03-17 10:48:52.000000000","message":"```suggestion\n----------------------------\n```","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"6a1bba05e16e17c743bf15f2a3e416d07b02a637","unresolved":false,"context_lines":[{"line_number":663,"context_line":"authentication."},{"line_number":664,"context_line":""},{"line_number":665,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER"},{"line_number":666,"context_line":"-----------------------------------"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":".. versionadded:: ..."},{"line_number":669,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"ec14dabf_84116e88","line":666,"in_reply_to":"6b929de5_564eaee2","updated":"2026-03-17 11:14:26.000000000","message":"Done","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"883b30a953b375f26fbbc82610579808bd9f0b08","unresolved":false,"context_lines":[{"line_number":663,"context_line":"authentication."},{"line_number":664,"context_line":""},{"line_number":665,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER"},{"line_number":666,"context_line":"-----------------------------------"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":".. versionadded:: ..."},{"line_number":669,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"b8837df7_9ea664ed","line":666,"in_reply_to":"ec14dabf_84116e88","updated":"2026-03-17 11:18:01.000000000","message":"Patchset 16*","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"2a4c34fc6e07b5d038c6aacc851ee520b40da556","unresolved":true,"context_lines":[{"line_number":665,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER"},{"line_number":666,"context_line":"-----------------------------------"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":".. versionadded:: ..."},{"line_number":669,"context_line":""},{"line_number":670,"context_line":"Default: ``OpenStack``"},{"line_number":671,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"89a098f2_8c2d1580","line":668,"updated":"2026-03-17 10:48:52.000000000","message":"Already 2026.2","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"6a1bba05e16e17c743bf15f2a3e416d07b02a637","unresolved":false,"context_lines":[{"line_number":665,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER"},{"line_number":666,"context_line":"-----------------------------------"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":".. versionadded:: ..."},{"line_number":669,"context_line":""},{"line_number":670,"context_line":"Default: ``OpenStack``"},{"line_number":671,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"a7ef5d39_02f2dd1c","line":668,"in_reply_to":"89a098f2_8c2d1580","updated":"2026-03-17 11:14:26.000000000","message":"Done","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"883b30a953b375f26fbbc82610579808bd9f0b08","unresolved":false,"context_lines":[{"line_number":665,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER"},{"line_number":666,"context_line":"-----------------------------------"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":".. versionadded:: ..."},{"line_number":669,"context_line":""},{"line_number":670,"context_line":"Default: ``OpenStack``"},{"line_number":671,"context_line":""}],"source_content_type":"text/x-rst","patch_set":15,"id":"bd78604f_88d89fc8","line":668,"in_reply_to":"a7ef5d39_02f2dd1c","updated":"2026-03-17 11:18:01.000000000","message":"Patchset 16*","commit_id":"53c90c28dac40b48df9acbcf5c368961d59110aa"}],"openstack_auth/urls.py":[{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"a9083c2f0cde3546efd65b89fb03a99968cc3a8f","unresolved":true,"context_lines":[{"line_number":35,"context_line":"            name\u003d\u0027switch_system_scope\u0027),"},{"line_number":36,"context_line":"]"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"if utils.allow_expired_password_change():"},{"line_number":39,"context_line":"    urlpatterns.append("},{"line_number":40,"context_line":"        re_path(r\u0027^password/(?P\u003cuser_id\u003e[^/]+)/$\u0027,"},{"line_number":41,"context_line":"                views.PasswordView.as_view(),"}],"source_content_type":"text/x-python","patch_set":4,"id":"11dc7ef3_8963f61d","line":38,"updated":"2026-02-26 13:13:41.000000000","message":"Fixed in another MR.. Please rebase your code to latest version and remove different changes.","commit_id":"e22a17cb3e314abf78bf55b044918ea55e9dc8d8"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"635b4dcf768364e23cb496af4f7ba94a76f0a41a","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            name\u003d\u0027switch_system_scope\u0027),"},{"line_number":36,"context_line":"]"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"if utils.allow_expired_password_change():"},{"line_number":39,"context_line":"    urlpatterns.append("},{"line_number":40,"context_line":"        re_path(r\u0027^password/(?P\u003cuser_id\u003e[^/]+)/$\u0027,"},{"line_number":41,"context_line":"                views.PasswordView.as_view(),"}],"source_content_type":"text/x-python","patch_set":4,"id":"c4cd5e0c_9d0dc216","line":38,"in_reply_to":"11dc7ef3_8963f61d","updated":"2026-03-06 15:33:05.000000000","message":"Resolved","commit_id":"e22a17cb3e314abf78bf55b044918ea55e9dc8d8"}],"openstack_dashboard/api/keystone.py":[{"author":{"_account_id":8648,"name":"Radomir Dopieralski","email":"openstack@dopieralski.pl","username":"thesheep"},"change_message_id":"1091f21b6444ad51d6d4c499de9c455d603202fe","unresolved":true,"context_lines":[{"line_number":516,"context_line":"    current_options \u003d getattr(user, \u0027options\u0027, {}).copy()"},{"line_number":517,"context_line":"    current_options.update(options)"},{"line_number":518,"context_line":"    client \u003d keystoneclient(request, admin\u003dFalse)"},{"line_number":519,"context_line":"    return client.users.update(user_id, options\u003dcurrent_options)"},{"line_number":520,"context_line":""},{"line_number":521,"context_line":""},{"line_number":522,"context_line":"@profiler.trace"}],"source_content_type":"text/x-python","patch_set":16,"id":"5c99d560_f00e8f38","line":519,"updated":"2026-04-09 15:03:24.000000000","message":"Can this function just call the previous function, instead of duplicating its code? Something like:\n\n```python\ndef user_update_own_options(request, **options):\n  return user_update_options(request, request.user.id, **options)\n```","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"e8dbee8e533f253a4b21a164bb6d19088de42930","unresolved":true,"context_lines":[{"line_number":516,"context_line":"    current_options \u003d getattr(user, \u0027options\u0027, {}).copy()"},{"line_number":517,"context_line":"    current_options.update(options)"},{"line_number":518,"context_line":"    client \u003d keystoneclient(request, admin\u003dFalse)"},{"line_number":519,"context_line":"    return client.users.update(user_id, options\u003dcurrent_options)"},{"line_number":520,"context_line":""},{"line_number":521,"context_line":""},{"line_number":522,"context_line":"@profiler.trace"}],"source_content_type":"text/x-python","patch_set":16,"id":"ec63c272_86c90cdb","line":519,"in_reply_to":"5c99d560_f00e8f38","updated":"2026-04-10 09:39:25.000000000","message":"Good point, I\u0027ll look into that. I just need to be careful with admin permissions. We don\u0027t want users to be blocked from changing their own options.","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"bb2be9fc7fd9050a2673842547c10fa26637d5cb","unresolved":false,"context_lines":[{"line_number":516,"context_line":"    current_options \u003d getattr(user, \u0027options\u0027, {}).copy()"},{"line_number":517,"context_line":"    current_options.update(options)"},{"line_number":518,"context_line":"    client \u003d keystoneclient(request, admin\u003dFalse)"},{"line_number":519,"context_line":"    return client.users.update(user_id, options\u003dcurrent_options)"},{"line_number":520,"context_line":""},{"line_number":521,"context_line":""},{"line_number":522,"context_line":"@profiler.trace"}],"source_content_type":"text/x-python","patch_set":16,"id":"474225df_a1e7dd02","line":519,"in_reply_to":"ec63c272_86c90cdb","updated":"2026-05-28 12:34:31.000000000","message":"Done","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"}],"openstack_dashboard/dashboards/settings/mfa/panel.py":[{"author":{"_account_id":8648,"name":"Radomir Dopieralski","email":"openstack@dopieralski.pl","username":"thesheep"},"change_message_id":"1091f21b6444ad51d6d4c499de9c455d603202fe","unresolved":true,"context_lines":[{"line_number":29,"context_line":"    def allowed(self, context):"},{"line_number":30,"context_line":"        request \u003d context[\u0027request\u0027]"},{"line_number":31,"context_line":"        allowed_roles \u003d settings.OPENSTACK_MFA_ROLES"},{"line_number":32,"context_line":"        user_roles \u003d [role[\u0027name\u0027] for role in request.user.roles]"},{"line_number":33,"context_line":"        if request.user.is_superuser:"},{"line_number":34,"context_line":"            return True"},{"line_number":35,"context_line":"        return any(role in user_roles for role in allowed_roles)"}],"source_content_type":"text/x-python","patch_set":16,"id":"0d7d5ff0_f8a7335d","line":32,"updated":"2026-04-09 15:03:24.000000000","message":"should this be based on policy checks, rather than a separate setting?","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"e8dbee8e533f253a4b21a164bb6d19088de42930","unresolved":true,"context_lines":[{"line_number":29,"context_line":"    def allowed(self, context):"},{"line_number":30,"context_line":"        request \u003d context[\u0027request\u0027]"},{"line_number":31,"context_line":"        allowed_roles \u003d settings.OPENSTACK_MFA_ROLES"},{"line_number":32,"context_line":"        user_roles \u003d [role[\u0027name\u0027] for role in request.user.roles]"},{"line_number":33,"context_line":"        if request.user.is_superuser:"},{"line_number":34,"context_line":"            return True"},{"line_number":35,"context_line":"        return any(role in user_roles for role in allowed_roles)"}],"source_content_type":"text/x-python","patch_set":16,"id":"fd4a2699_e8bc13b6","line":32,"in_reply_to":"0d7d5ff0_f8a7335d","updated":"2026-04-10 09:39:25.000000000","message":"I think you\u0027ve got a better lead. I\u0027ll take a look at it.","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"bb2be9fc7fd9050a2673842547c10fa26637d5cb","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    def allowed(self, context):"},{"line_number":30,"context_line":"        request \u003d context[\u0027request\u0027]"},{"line_number":31,"context_line":"        allowed_roles \u003d settings.OPENSTACK_MFA_ROLES"},{"line_number":32,"context_line":"        user_roles \u003d [role[\u0027name\u0027] for role in request.user.roles]"},{"line_number":33,"context_line":"        if request.user.is_superuser:"},{"line_number":34,"context_line":"            return True"},{"line_number":35,"context_line":"        return any(role in user_roles for role in allowed_roles)"}],"source_content_type":"text/x-python","patch_set":16,"id":"df68bce5_b95e2bde","line":32,"in_reply_to":"fd4a2699_e8bc13b6","updated":"2026-05-28 12:34:31.000000000","message":"Done","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"}],"openstack_dashboard/dashboards/settings/mfa/templates/mfa/_select_credential_with_qr.html":[{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"ce3fe2fc3fbeea0e2a50a845af2b8c0495b50818","unresolved":true,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":"      // Fetch QR code from server"},{"line_number":111,"context_line":"      var xhr \u003d new XMLHttpRequest();"},{"line_number":112,"context_line":"      xhr.open(\u0027GET\u0027, \u0027/settings/mfa/credential/\u0027 + credId + \u0027/qr/\u0027, true);"},{"line_number":113,"context_line":"      xhr.setRequestHeader(\u0027X-Requested-With\u0027, \u0027XMLHttpRequest\u0027);"},{"line_number":114,"context_line":"      xhr.onreadystatechange \u003d function() {"},{"line_number":115,"context_line":"        if (xhr.readyState \u003d\u003d\u003d 4) {"}],"source_content_type":"text/html","patch_set":21,"id":"2225021d_8280a548","line":112,"range":{"start_line":112,"start_character":6,"end_line":112,"end_character":75},"updated":"2026-06-11 11:47:31.000000000","message":"As this Django URL is registered correctly in ```urls.py```, what is the reason to use ```/settings/mfa/credential/``` hardcoded here. If I am right then with this implementation it is expected that Horizon is at the site root which can be (I think quite often is) customized using ```WEBROOT``` or proxy prefix.\n\nedit: Now when I am verifying your patch practically, I can not see QR code at all and I am getting 404 in inspect-\u003enetwork, because the code is calling ```http://xxxx/settings/mfa/credential/__new__/qr/```\nBut reality of my deployment is:```http://xxxx/dashboard/settings/mfa/....```","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"863d52b986a69ad2f295c4a5d7ea02f9967b829d","unresolved":true,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":"      // Fetch QR code from server"},{"line_number":111,"context_line":"      var xhr \u003d new XMLHttpRequest();"},{"line_number":112,"context_line":"      xhr.open(\u0027GET\u0027, \u0027/settings/mfa/credential/\u0027 + credId + \u0027/qr/\u0027, true);"},{"line_number":113,"context_line":"      xhr.setRequestHeader(\u0027X-Requested-With\u0027, \u0027XMLHttpRequest\u0027);"},{"line_number":114,"context_line":"      xhr.onreadystatechange \u003d function() {"},{"line_number":115,"context_line":"        if (xhr.readyState \u003d\u003d\u003d 4) {"}],"source_content_type":"text/html","patch_set":21,"id":"4d904875_7f2d0470","line":112,"range":{"start_line":112,"start_character":6,"end_line":112,"end_character":75},"in_reply_to":"2225021d_8280a548","updated":"2026-06-22 08:35:54.000000000","message":"I\u0027ve made the change. Can you confirm that the problem is no longer occurring on your end?\nNormally, it should work when there\u0027s a slug for Horizon.","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"0cf23bf8aa2a7487b4d5cb9d93d2de8dce1a14f2","unresolved":false,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":"      // Fetch QR code from server"},{"line_number":111,"context_line":"      var xhr \u003d new XMLHttpRequest();"},{"line_number":112,"context_line":"      xhr.open(\u0027GET\u0027, \u0027/settings/mfa/credential/\u0027 + credId + \u0027/qr/\u0027, true);"},{"line_number":113,"context_line":"      xhr.setRequestHeader(\u0027X-Requested-With\u0027, \u0027XMLHttpRequest\u0027);"},{"line_number":114,"context_line":"      xhr.onreadystatechange \u003d function() {"},{"line_number":115,"context_line":"        if (xhr.readyState \u003d\u003d\u003d 4) {"}],"source_content_type":"text/html","patch_set":21,"id":"441baffc_8362ce62","line":112,"range":{"start_line":112,"start_character":6,"end_line":112,"end_character":75},"in_reply_to":"4d904875_7f2d0470","updated":"2026-06-24 08:51:47.000000000","message":"Works fine now, thanks!","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"}],"openstack_dashboard/dashboards/settings/mfa/utils.py":[{"author":{"_account_id":8648,"name":"Radomir Dopieralski","email":"openstack@dopieralski.pl","username":"thesheep"},"change_message_id":"1091f21b6444ad51d6d4c499de9c455d603202fe","unresolved":true,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":16,"context_line":"from cryptography.hazmat.primitives import hashes"},{"line_number":17,"context_line":"from cryptography.hazmat.primitives.twofactor import totp as crypto_totp"},{"line_number":18,"context_line":"from oslo_utils import timeutils"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"c2e6adcf_e3a98f5c","line":17,"updated":"2026-04-09 15:03:24.000000000","message":"do we need to add this library to requirements.txt?","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"bb2be9fc7fd9050a2673842547c10fa26637d5cb","unresolved":false,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":16,"context_line":"from cryptography.hazmat.primitives import hashes"},{"line_number":17,"context_line":"from cryptography.hazmat.primitives.twofactor import totp as crypto_totp"},{"line_number":18,"context_line":"from oslo_utils import timeutils"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"138fa194_f503c6c9","line":17,"in_reply_to":"197673a9_dd7c7802","updated":"2026-05-28 12:34:31.000000000","message":"Done","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"e8dbee8e533f253a4b21a164bb6d19088de42930","unresolved":true,"context_lines":[{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":16,"context_line":"from cryptography.hazmat.primitives import hashes"},{"line_number":17,"context_line":"from cryptography.hazmat.primitives.twofactor import totp as crypto_totp"},{"line_number":18,"context_line":"from oslo_utils import timeutils"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"197673a9_dd7c7802","line":17,"in_reply_to":"c2e6adcf_e3a98f5c","updated":"2026-04-10 09:39:25.000000000","message":"I drew heavily on the totp.py plugin from the Keystone project: keystone/auth/plugins/totp.py and it is listed in the requirements: \n\nhttps://opendev.org/openstack/keystone/src/branch/master/requirements.txt#:~:text\u003dcryptography%3E%3D2%2E7%20%23%20BSD%2FApache%2D2%2E0\n\nI\u0027ll add it","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"}],"openstack_dashboard/dashboards/settings/mfa/views.py":[{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"6258c18a3c4bf0b7b9c3b350d25fb85d8a30d6fa","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"c5f12b20_f301e31d","line":230,"updated":"2026-06-22 13:23:57.000000000","message":"Not sure if this is the best place to add my comment about a workflow question I have about if/when a customer deletes a credential and then wants to create a new one immediately. I found that I needed to log off and then log back in, in order for me to create a new credential after deleting the previous.\n\nIf this is expected behavior, do we document this need to logout and back in?","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"c37f2decdf4f8b1af8c1a53a20d5c654c84c8991","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"e0021de5_91939216","line":230,"in_reply_to":"2942ad22_8af87e60","updated":"2026-06-24 11:46:28.000000000","message":"I\u0027ve noticed that getting stuck if you delete the credential is an issue. But this bug is in Keystone, and I\u0027m currently working on a patch.  https://review.opendev.org/c/openstack/keystone/+/985969\n\nIf you see the message: \n```\nMFA is not enabled\nEnable multi-factor authentication to add an extra layer of security. \n```\nIt means that not all requirements have been met. The requirements are: \n- A TOTP credential \n- MFA enabled in keystone \n- The [TOTP, password] rule\n\nBut you can see the button \"disable MFA\" because in keystone MFA is enable.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"e3c54ff358f598d9e4ed6acbb528d9eedadf45b1","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"2942ad22_8af87e60","line":230,"in_reply_to":"41a8fc9b_41725283","updated":"2026-06-24 09:42:58.000000000","message":"Okay, I am not sure if it is exactly the issue that you are facing but when I enable MFA, then there is saved TOTP in User Credentials.\n\nThen in MFA I can see:\n```\nMFA is not enabled\nEnable multi-factor authentication to add an extra layer of security. \n```\nBut the button there is still red and shows ```Disable MFA```\n\nIt does not make much sense. When the MFA is not enabled, how can I Disable MFA?\nAnd on top of it, when I log out there is no way to log in again (via UI). Because login still requires a TOTP passcode, but as I deleted it in User Credentials, it does not exist anymore.\n\nWhen I Enable MFA, then there is created TOTP in User Credentials.\nWhen I Disable MFA, then the TOTP from User Credentials is deleted.\nwhy it does not work also vice versa?\nWhen I delete TOTP in User Credentials then MFA should be automatically disabled/deleted with all connected things. I guess?\n\n\nAm I missing something? Am I wrong? \nIf not then I do not like the current behavior much as it is (in my point of view) very easy to \"lock yourself\" out.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"319b09bf358235e687e0d4aca5591f461c2c0d2a","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"ff4f2073_9c695a2d","line":230,"in_reply_to":"8e6d9d39_ed48c526","updated":"2026-06-23 13:01:28.000000000","message":"I have a very generic devstack setup - all default settings. I have another setup that I can point to - maybe it is related to one of my setups.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"3029faddc6b42999780e0e8ec43959709de71011","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"e9e7de7a_017ff6ec","line":230,"in_reply_to":"9c2474b1_2522c786","updated":"2026-07-14 19:35:04.000000000","message":"I could not reproduce what I was seeing before. I was able to click \"Disable MFA\" and then select [x] Delete all TOTP credentials, and click \"Delete\", then re-click \"Enable MFA\" and successfully add a new credential. Jan\u0027s issue is still open, so, not marking resolved.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"33200ee32c3f82a12697ccfedba26c84633cf1f3","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"8e6d9d39_ed48c526","line":230,"in_reply_to":"c5f12b20_f301e31d","updated":"2026-06-23 12:14:47.000000000","message":"I didn\u0027t have that problem on my test/dev stack. Do you have a specific configuration?\n\nReport it to https://bugs.launchpad.net/horizon/ 😉","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"4145f0f809b45a7bd3614d92bb9452e6e1f9c237","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"9c2474b1_2522c786","line":230,"in_reply_to":"cf2394bc_5b0d684d","updated":"2026-07-14 09:13:46.000000000","message":"Hi @omcgonag@redhat.com,\nI tried your steps but I am not facing this issue in my environment.\nWhen I create new totp credentials in user credentials, I still can see Enable MFA button in MFA and I can see there message:\n``` MFA setup incomplete\nYou have a TOTP credential but MFA has not been fully activated. ```\nWhich seems to be proper behavior to me.\n\n@blasseye@ikmail.com,\nI am still keeping my -1 because of the issue that I am facing and I mentioned above.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"f60b9e0cd9102b80633f61b5818043acd2083456","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"cf2394bc_5b0d684d","line":230,"in_reply_to":"d6e7e8a3_159cc338","updated":"2026-06-24 12:47:50.000000000","message":"My steps were (1) create new credentials (2) add new FreeOTP credential (4) go back to MFA panel (3) see button change from Enable MFA to Disable MFA  (4) click Disable MFA (5) select delete on next screen (not just Disable, but delete entirely) (6) get back, and select Enable MFA (7) no matter what I do, I cannot add a new FreeOTP credential ... only after I logged out, and then back in, was I able to add a new credential.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"65bb145fa9d272bfad464e655af282693c26cdb1","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"d6e7e8a3_159cc338","line":230,"in_reply_to":"e0021de5_91939216","updated":"2026-06-24 12:17:25.000000000","message":"```\nopenstack user set --enable-multi-factor-auth --multi-factor-auth-rule password,totp mfa-member\n```\n\nIf you do this in the CLI without first creating a TOTP credential, you\u0027ll get stuck. But that\u0027s a keystone issue.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"6d6e82f340453f1cde210adaf68871b8347a7c58","unresolved":true,"context_lines":[{"line_number":227,"context_line":"    form_class \u003d mfa_forms.DisableMFAForm"},{"line_number":228,"context_line":"    form_id \u003d \"disable_mfa_form\""},{"line_number":229,"context_line":"    modal_id \u003d \"disable_mfa_modal\""},{"line_number":230,"context_line":"    page_title \u003d _(\"Disable Multi-Factor Authentication\")"},{"line_number":231,"context_line":"    submit_label \u003d _(\"Disable MFA\")"},{"line_number":232,"context_line":"    submit_url \u003d reverse_lazy(\"horizon:settings:mfa:disable\")"},{"line_number":233,"context_line":"    success_url \u003d reverse_lazy(\"horizon:settings:mfa:index\")"}],"source_content_type":"text/x-python","patch_set":26,"id":"41a8fc9b_41725283","line":230,"in_reply_to":"ff4f2073_9c695a2d","updated":"2026-06-24 09:11:22.000000000","message":"Hi @omcgonag@redhat.com,\nCould you be a little more specific what are your steps and the issue you are facing? I have generic devstack setup too (so I can try to reproduce your steps) but I probably do not face the issue that you do or at least I did not notice.","commit_id":"fdcae074fa581311845a6f795d0da233450ab55b"}],"openstack_dashboard/dashboards/settings/mfa/workflows.py":[{"author":{"_account_id":8648,"name":"Radomir Dopieralski","email":"openstack@dopieralski.pl","username":"thesheep"},"change_message_id":"1091f21b6444ad51d6d4c499de9c455d603202fe","unresolved":true,"context_lines":[{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""},{"line_number":45,"context_line":"            \"out of your account.\""},{"line_number":46,"context_line":"        )"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    def handle(self, request, context):"}],"source_content_type":"text/x-python","patch_set":16,"id":"31dcac57_f0828815","line":45,"updated":"2026-04-09 15:03:24.000000000","message":"perhaps a multi-line string (with \"\"\") would work here better","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"e8dbee8e533f253a4b21a164bb6d19088de42930","unresolved":true,"context_lines":[{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""},{"line_number":45,"context_line":"            \"out of your account.\""},{"line_number":46,"context_line":"        )"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    def handle(self, request, context):"}],"source_content_type":"text/x-python","patch_set":16,"id":"877e33b0_90769260","line":45,"in_reply_to":"31dcac57_f0828815","updated":"2026-04-10 09:39:25.000000000","message":"We don’t typically use multi-line triple-quoted strings for help_text in Horizon.\nAlso, indentation in \"\"\" strings may introduce unintended whitespace, so I used the \\n format for consistency and to avoid formatting issues.","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"6f1ed42f85b28152f27d121c4c17927b5b1b0bd0","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""},{"line_number":45,"context_line":"            \"out of your account.\""},{"line_number":46,"context_line":"        )"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    def handle(self, request, context):"}],"source_content_type":"text/x-python","patch_set":16,"id":"d471bd32_fba7cc74","line":45,"in_reply_to":"877e33b0_90769260","updated":"2026-05-28 12:53:14.000000000","message":"Done","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"d3326fc6049332cdd20bbdbb32402760d7ad9a43","unresolved":true,"context_lines":[{"line_number":38,"context_line":"        slug \u003d \"warning\""},{"line_number":39,"context_line":"        help_text \u003d _("},{"line_number":40,"context_line":"            \"Before you proceed:\\n\""},{"line_number":41,"context_line":"            \"- You will need an authenticator app (Aegis Authenticator, \""},{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""}],"source_content_type":"text/x-python","patch_set":21,"id":"453bad06_f08f395d","line":41,"updated":"2026-06-10 23:56:10.000000000","message":"```suggestion\n            \"- You will need an authenticator app (Google Authenticator, \"\n```","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"b8bbc6beebb785ce845f2bd50904a1e148e705da","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        slug \u003d \"warning\""},{"line_number":39,"context_line":"        help_text \u003d _("},{"line_number":40,"context_line":"            \"Before you proceed:\\n\""},{"line_number":41,"context_line":"            \"- You will need an authenticator app (Aegis Authenticator, \""},{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""}],"source_content_type":"text/x-python","patch_set":21,"id":"7850339b_a789ab44","line":41,"in_reply_to":"453bad06_f08f395d","updated":"2026-06-22 08:33:34.000000000","message":"Done","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"d3326fc6049332cdd20bbdbb32402760d7ad9a43","unresolved":true,"context_lines":[{"line_number":39,"context_line":"        help_text \u003d _("},{"line_number":40,"context_line":"            \"Before you proceed:\\n\""},{"line_number":41,"context_line":"            \"- You will need an authenticator app (Aegis Authenticator, \""},{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""},{"line_number":45,"context_line":"            \"out of your account.\""}],"source_content_type":"text/x-python","patch_set":21,"id":"441d86c6_0af0d3a2","line":42,"updated":"2026-06-10 23:56:10.000000000","message":"```suggestion\n            \"Aegis Authenticator, FreeOTP, etc.).\\n\"\n```","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"b8bbc6beebb785ce845f2bd50904a1e148e705da","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        help_text \u003d _("},{"line_number":40,"context_line":"            \"Before you proceed:\\n\""},{"line_number":41,"context_line":"            \"- You will need an authenticator app (Aegis Authenticator, \""},{"line_number":42,"context_line":"            \"FreeOTP, etc.).\\n\""},{"line_number":43,"context_line":"            \"- Save the QR code or secret key before continuing.\\n\""},{"line_number":44,"context_line":"            \"- If you lose access to your authenticator, you may be locked \""},{"line_number":45,"context_line":"            \"out of your account.\""}],"source_content_type":"text/x-python","patch_set":21,"id":"7e03d1e6_b7febdf1","line":42,"in_reply_to":"441d86c6_0af0d3a2","updated":"2026-06-22 08:33:34.000000000","message":"Done","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"ce3fe2fc3fbeea0e2a50a845af2b8c0495b50818","unresolved":true,"context_lines":[{"line_number":213,"context_line":"    def format_status_message(self, message):"},{"line_number":214,"context_line":"        if \"%s\" in message:"},{"line_number":215,"context_line":"            issuer \u003d getattr("},{"line_number":216,"context_line":"                django_settings, \"OPENSTACK_KEYSTONE_MFA_ISSUER\", None)"},{"line_number":217,"context_line":"            return message % (issuer if issuer else self.name)"},{"line_number":218,"context_line":"        return message"},{"line_number":219,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"955a4df0_723a148f","line":216,"range":{"start_line":216,"start_character":34,"end_line":216,"end_character":63},"updated":"2026-06-11 11:47:31.000000000","message":"I am a little bit confused. I am not familiar with all possible OpenStack settings but what exactly is ```OPENSTACK_KEYSTONE_MFA_ISSUER``` and where is it coming from? I can not find it in OpenStack documentation, neither defined here in the patch.\nShould it be ```OPENSTACK_TOTP_QRCODE_ISSUER```? Or am I missing something?\n\nI wonder if ```OPENSTACK_KEYSTONE_MFA_ISSUER``` was meant as a companion to ```OPENSTACK_KEYSTONE_MFA_TOTP_ENABLED```, but I only found ```OPENSTACK_TOTP_QRCODE_ISSUER``` defined and documented in this patch. Could you please clarify it for me?\n\nAlso... ```success_message/failure_message``` does not contain ```%s``` so this override never runs I guess?","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"601712b92361e487f57293b493f64271b1a4d5b0","unresolved":false,"context_lines":[{"line_number":213,"context_line":"    def format_status_message(self, message):"},{"line_number":214,"context_line":"        if \"%s\" in message:"},{"line_number":215,"context_line":"            issuer \u003d getattr("},{"line_number":216,"context_line":"                django_settings, \"OPENSTACK_KEYSTONE_MFA_ISSUER\", None)"},{"line_number":217,"context_line":"            return message % (issuer if issuer else self.name)"},{"line_number":218,"context_line":"        return message"},{"line_number":219,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"344e83b3_2d0c2a72","line":216,"range":{"start_line":216,"start_character":34,"end_line":216,"end_character":63},"in_reply_to":"447adef8_ea95e953","updated":"2026-06-22 08:32:53.000000000","message":"Done","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"1aa96ccf776d7d2bf036695e9f995ccb2d95092b","unresolved":true,"context_lines":[{"line_number":213,"context_line":"    def format_status_message(self, message):"},{"line_number":214,"context_line":"        if \"%s\" in message:"},{"line_number":215,"context_line":"            issuer \u003d getattr("},{"line_number":216,"context_line":"                django_settings, \"OPENSTACK_KEYSTONE_MFA_ISSUER\", None)"},{"line_number":217,"context_line":"            return message % (issuer if issuer else self.name)"},{"line_number":218,"context_line":"        return message"},{"line_number":219,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"447adef8_ea95e953","line":216,"range":{"start_line":216,"start_character":34,"end_line":216,"end_character":63},"in_reply_to":"955a4df0_723a148f","updated":"2026-06-12 09:46:45.000000000","message":"Thanks for your review. It was a feature I had used before but modified, and I didn\u0027t pay attention to it since it wasn\u0027t causing any errors.\n\nThis function is no longer useful. I\u0027m going to delete it.","commit_id":"019e18b7ec361b487b322d10e02d9ce0227ae6bc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5454985bc4344a8ef6faaf835c16d4650cfcb5b4","unresolved":false,"context_lines":[{"line_number":12,"context_line":""},{"line_number":13,"context_line":"import logging"},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from django.conf import settings as django_settings"},{"line_number":16,"context_line":"from django.utils.translation import gettext_lazy as _"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from horizon import exceptions"}],"source_content_type":"text/x-python","patch_set":23,"id":"9004e236_1510d767","line":15,"updated":"2026-06-16 16:48:02.000000000","message":"pep8: F401 \u0027django.conf.settings as django_settings\u0027 imported but unused","commit_id":"3e667e74a1e14ce29fc048ccd76239ca93748c89"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"62fd9b633197c898be6cf6607e4c6e2a2008a766","unresolved":true,"context_lines":[{"line_number":77,"context_line":"        name \u003d _(\"TOTP Credential \u0026 QR Code\")"},{"line_number":78,"context_line":"        slug \u003d \"select_credential_with_qr\""},{"line_number":79,"context_line":"        help_text \u003d _("},{"line_number":80,"context_line":"            \"Select a credential from the dropdown below. \""},{"line_number":81,"context_line":"            \"The corresponding QR code and secret key will \""},{"line_number":82,"context_line":"            \"be displayed automatically. \""},{"line_number":83,"context_line":"            \"Scan the QR code with your authenticator app \""}],"source_content_type":"text/x-python","patch_set":25,"id":"3ea25261_9d049a6f","line":80,"updated":"2026-06-18 22:24:55.000000000","message":"Just a nit pick... before the first credential is created, the dropdown is not yet there...\n\nMabye change it to:\n\"After you create your first credential, select one from the provided dropdown list\"\n\nbtw - so far, so good - I was able to create my credential using the FreeOTP app","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"fbe4ac23d549311a0b5206c7801d230ae5afacdc","unresolved":true,"context_lines":[{"line_number":77,"context_line":"        name \u003d _(\"TOTP Credential \u0026 QR Code\")"},{"line_number":78,"context_line":"        slug \u003d \"select_credential_with_qr\""},{"line_number":79,"context_line":"        help_text \u003d _("},{"line_number":80,"context_line":"            \"Select a credential from the dropdown below. \""},{"line_number":81,"context_line":"            \"The corresponding QR code and secret key will \""},{"line_number":82,"context_line":"            \"be displayed automatically. \""},{"line_number":83,"context_line":"            \"Scan the QR code with your authenticator app \""}],"source_content_type":"text/x-python","patch_set":25,"id":"e8632c7c_fca55329","line":80,"in_reply_to":"3ea25261_9d049a6f","updated":"2026-06-22 08:15:16.000000000","message":"I\u0027m sorry, I don\u0027t understand.\nIf there aren\u0027t any totps created yet, don\u0027t you think that\u0027s unclear?","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"33fcdded199c2a76a8be52c42f3f105e61280d21","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        name \u003d _(\"TOTP Credential \u0026 QR Code\")"},{"line_number":78,"context_line":"        slug \u003d \"select_credential_with_qr\""},{"line_number":79,"context_line":"        help_text \u003d _("},{"line_number":80,"context_line":"            \"Select a credential from the dropdown below. \""},{"line_number":81,"context_line":"            \"The corresponding QR code and secret key will \""},{"line_number":82,"context_line":"            \"be displayed automatically. \""},{"line_number":83,"context_line":"            \"Scan the QR code with your authenticator app \""}],"source_content_type":"text/x-python","patch_set":25,"id":"88391b2d_aec93688","line":80,"in_reply_to":"7274fe1b_1348b1aa","updated":"2026-06-22 13:52:18.000000000","message":"I am good with either option - you can pick one","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"650a988e3d086796d61913feccde7607b11bcee1","unresolved":true,"context_lines":[{"line_number":77,"context_line":"        name \u003d _(\"TOTP Credential \u0026 QR Code\")"},{"line_number":78,"context_line":"        slug \u003d \"select_credential_with_qr\""},{"line_number":79,"context_line":"        help_text \u003d _("},{"line_number":80,"context_line":"            \"Select a credential from the dropdown below. \""},{"line_number":81,"context_line":"            \"The corresponding QR code and secret key will \""},{"line_number":82,"context_line":"            \"be displayed automatically. \""},{"line_number":83,"context_line":"            \"Scan the QR code with your authenticator app \""}],"source_content_type":"text/x-python","patch_set":25,"id":"7274fe1b_1348b1aa","line":80,"in_reply_to":"8abfd1c1_aa26c5ea","updated":"2026-06-22 13:48:10.000000000","message":"Oh yes true... i understand, now i see the error.\nThere are 2 solutions: \n___\n1) \nSelect a credential from the dropdown below. The corresponding QR code and secret key will be displayed automatically. Scan the QR code with your authenticator app or enter the secret key manually.\n#### TOTP Credential\n[ThemableChoiceField]\n\n___\n\n2) \n#### TOTP Credential\n[ThemableChoiceField]\nSelect a credential from the dropdown above. The corresponding QR code and secret key will be displayed automatically. Scan the QR code with your authenticator app or enter the secret key manually.\n\n___\n\nI can\u0027t put the “description” between the title and the form field.","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"1f47c23d20698408ccadcfcaed3fd890997051c8","unresolved":true,"context_lines":[{"line_number":77,"context_line":"        name \u003d _(\"TOTP Credential \u0026 QR Code\")"},{"line_number":78,"context_line":"        slug \u003d \"select_credential_with_qr\""},{"line_number":79,"context_line":"        help_text \u003d _("},{"line_number":80,"context_line":"            \"Select a credential from the dropdown below. \""},{"line_number":81,"context_line":"            \"The corresponding QR code and secret key will \""},{"line_number":82,"context_line":"            \"be displayed automatically. \""},{"line_number":83,"context_line":"            \"Scan the QR code with your authenticator app \""}],"source_content_type":"text/x-python","patch_set":25,"id":"8abfd1c1_aa26c5ea","line":80,"in_reply_to":"e8632c7c_fca55329","updated":"2026-06-22 13:18:07.000000000","message":"Looking at the \"TOTP Credential \u0026 QR Code\" panel again, and seeing the TOP Credential \"Create a new TOTP credential\" drop down - I now see where my confusion exists...\n\nWHen I see the sentence \"Select a credential from the dropdown below\" - the first time I ever visited this panel, I was waiting for a new \"drop down\" box to appear - since the caption states \"Select a credential from the dropdown below\" - key word \"below\"\n\nMaybe put that caption/comment before the dropdown box?\n\nthen \"below\" would mean the dropdown box \"below\" the caption.\n\nIt is not obvious to me that the caption is attached to the dropdown box \"above\" the caption, which would mean \"below\" is truly below the currently displayed dropdown box.\n\nDid I just make things more confusing? Or, do you now see my point?","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"8e3df954dfd3a584a837fe837a35f90d187e4a26","unresolved":true,"context_lines":[{"line_number":120,"context_line":""},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"class VerifyTOTPAction(workflows.Action):"},{"line_number":123,"context_line":"    \"\"\"Ask the user for the current6-digit TOTP code to confirm setup.\"\"\""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    totp_code \u003d forms.RegexField("},{"line_number":126,"context_line":"        label\u003d_(\"TOTP Code\"),"}],"source_content_type":"text/x-python","patch_set":25,"id":"0389eaca_a3f2f064","line":123,"updated":"2026-06-18 22:31:04.000000000","message":"missing space after current","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"fbe4ac23d549311a0b5206c7801d230ae5afacdc","unresolved":true,"context_lines":[{"line_number":120,"context_line":""},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"class VerifyTOTPAction(workflows.Action):"},{"line_number":123,"context_line":"    \"\"\"Ask the user for the current6-digit TOTP code to confirm setup.\"\"\""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    totp_code \u003d forms.RegexField("},{"line_number":126,"context_line":"        label\u003d_(\"TOTP Code\"),"}],"source_content_type":"text/x-python","patch_set":25,"id":"c63478bd_4a62f233","line":123,"in_reply_to":"0389eaca_a3f2f064","updated":"2026-06-22 08:15:16.000000000","message":"Right ! Thanks","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"601712b92361e487f57293b493f64271b1a4d5b0","unresolved":false,"context_lines":[{"line_number":120,"context_line":""},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"class VerifyTOTPAction(workflows.Action):"},{"line_number":123,"context_line":"    \"\"\"Ask the user for the current6-digit TOTP code to confirm setup.\"\"\""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    totp_code \u003d forms.RegexField("},{"line_number":126,"context_line":"        label\u003d_(\"TOTP Code\"),"}],"source_content_type":"text/x-python","patch_set":25,"id":"3d416793_a24e643a","line":123,"in_reply_to":"c63478bd_4a62f233","updated":"2026-06-22 08:32:53.000000000","message":"Done","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"601712b92361e487f57293b493f64271b1a4d5b0","unresolved":false,"context_lines":[{"line_number":120,"context_line":""},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"class VerifyTOTPAction(workflows.Action):"},{"line_number":123,"context_line":"    \"\"\"Ask the user for the current6-digit TOTP code to confirm setup.\"\"\""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"    totp_code \u003d forms.RegexField("},{"line_number":126,"context_line":"        label\u003d_(\"TOTP Code\"),"}],"source_content_type":"text/x-python","patch_set":25,"id":"ca878139_4fb62221","line":123,"in_reply_to":"c63478bd_4a62f233","updated":"2026-06-22 08:32:53.000000000","message":"Done","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"}],"openstack_dashboard/defaults.py":[{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"890296936024948980ca5dce07958f79c82d42cf","unresolved":true,"context_lines":[{"line_number":581,"context_line":"# This value is displayed in authenticator applications (e.g., FreeOTP,"},{"line_number":582,"context_line":"# Google Authenticator, Authy) to help users identify the OpenStack account"},{"line_number":583,"context_line":"# associated with the generated TOTP token."},{"line_number":584,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER \u003d \u0027OpenStack\u0027"}],"source_content_type":"text/x-python","patch_set":25,"id":"d9ab9b04_03f5e94a","line":584,"updated":"2026-06-18 18:51:29.000000000","message":"I am just starting the review...\n\nFigured I would mention this, as I see this during my initial review...\n\nI believe we need to also set this default setting:\n\n```\n# Enable TOTP MFA enrollment panel in Settings dashboard.\nOPENSTACK_KEYSTONE_MFA_TOTP_ENABLED \u003d False\n```","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":32432,"name":"Owen McGonagle","email":"omcgonag@redhat.com","username":"omcgonag"},"change_message_id":"173bf4ea64670c20f3cba8b1d3bc10c474a5fbe1","unresolved":false,"context_lines":[{"line_number":581,"context_line":"# This value is displayed in authenticator applications (e.g., FreeOTP,"},{"line_number":582,"context_line":"# Google Authenticator, Authy) to help users identify the OpenStack account"},{"line_number":583,"context_line":"# associated with the generated TOTP token."},{"line_number":584,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER \u003d \u0027OpenStack\u0027"}],"source_content_type":"text/x-python","patch_set":25,"id":"98497d67_4f36673e","line":584,"in_reply_to":"356ae9a2_3e62bfa6","updated":"2026-06-18 22:21:13.000000000","message":"Thx, I did not see that, all set","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"},{"author":{"_account_id":35133,"name":"Jan Jasek","email":"jjasek@redhat.com","username":"janjasek"},"change_message_id":"7c0a5d47c8a516fba97c350dccc793dc60b3b5c7","unresolved":true,"context_lines":[{"line_number":581,"context_line":"# This value is displayed in authenticator applications (e.g., FreeOTP,"},{"line_number":582,"context_line":"# Google Authenticator, Authy) to help users identify the OpenStack account"},{"line_number":583,"context_line":"# associated with the generated TOTP token."},{"line_number":584,"context_line":"OPENSTACK_TOTP_QRCODE_ISSUER \u003d \u0027OpenStack\u0027"}],"source_content_type":"text/x-python","patch_set":25,"id":"356ae9a2_3e62bfa6","line":584,"in_reply_to":"d9ab9b04_03f5e94a","updated":"2026-06-18 19:00:08.000000000","message":"Hello @omcgonag@redhat.com,\nI do not think we need, as it is already in ```openstack_auth/defaults.py```\n\nhttps://github.com/openstack/horizon/blob/e4837ab45aa52891465c31d7191d60c7e32de491/openstack_auth/defaults.py#L186","commit_id":"347e676792d009ed2558ae258744890b3ffed61e"}],"releasenotes/notes/enable-mfa-from-horizon-d53fd6f4453b2abb.yaml":[{"author":{"_account_id":8648,"name":"Radomir Dopieralski","email":"openstack@dopieralski.pl","username":"thesheep"},"change_message_id":"1091f21b6444ad51d6d4c499de9c455d603202fe","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":16,"id":"98775e57_51859381","line":14,"updated":"2026-04-09 15:03:24.000000000","message":"Would be nice to also mention the new settings here.","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"},{"author":{"_account_id":36012,"name":"Benjamin Lasseye","display_name":"Benjamin Lasseye","email":"blasseye@ikmail.com","username":"blasseye"},"change_message_id":"bb2be9fc7fd9050a2673842547c10fa26637d5cb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"3ef0a294_6c65db17","line":14,"in_reply_to":"98775e57_51859381","updated":"2026-05-28 12:34:31.000000000","message":"Done","commit_id":"388a36d679d218b0fe0a2fd1566b122493cf82e3"}]}
