diff --git a/base_user_empty_password/README.rst b/base_user_empty_password/README.rst new file mode 100644 index 0000000000..1c779f7128 --- /dev/null +++ b/base_user_empty_password/README.rst @@ -0,0 +1,94 @@ +==================== +Empty users password +==================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:512d1e5b2dee0d04bf83cf2186bc757d4bc2e0f660342c92128bce2ba1bb571c + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github + :target: https://github.com/OCA/server-auth/tree/18.0/base_user_empty_password + :alt: OCA/server-auth +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-auth-18-0/server-auth-18-0-base_user_empty_password + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module provides a wizard to allow emptying users password field. + +This could be useful to force the user to use another sign on method +than Odoo. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp + +Contributors +------------ + +- Akim Juillerat akim.juilllerat@camptocamp.com +- Chau Le chaulb@trobz.com + +Other credits +------------- + +The migration of this module from 14.0 to 18.0 was financially supported +by Camptocamp. + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-grindtildeath| image:: https://github.com/grindtildeath.png?size=40px + :target: https://github.com/grindtildeath + :alt: grindtildeath + +Current `maintainer `__: + +|maintainer-grindtildeath| + +This module is part of the `OCA/server-auth `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_user_empty_password/__init__.py b/base_user_empty_password/__init__.py new file mode 100644 index 0000000000..9b4296142f --- /dev/null +++ b/base_user_empty_password/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/base_user_empty_password/__manifest__.py b/base_user_empty_password/__manifest__.py new file mode 100644 index 0000000000..881a57834a --- /dev/null +++ b/base_user_empty_password/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +{ + "name": "Empty users password", + "summary": "Allows to empty password of users", + "version": "18.0.1.0.0", + "development_status": "Beta", + "category": "Uncategorized", + "website": "https://github.com/OCA/server-auth", + "author": "Camptocamp, Odoo Community Association (OCA)", + "maintainers": ["grindtildeath"], + "license": "AGPL-3", + "depends": [ + "base", + ], + "data": [ + "security/ir.model.access.csv", + "views/res_users.xml", + "wizard/empty_password.xml", + ], +} diff --git a/base_user_empty_password/i18n/base_user_empty_password.pot b/base_user_empty_password/i18n/base_user_empty_password.pot new file mode 100644 index 0000000000..a421ed92e2 --- /dev/null +++ b/base_user_empty_password/i18n/base_user_empty_password.pot @@ -0,0 +1,84 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_user_empty_password +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.1alpha1+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-09-27 05:16+0000\n" +"PO-Revision-Date: 2024-09-27 05:16+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: base_user_empty_password +#: model_terms:ir.ui.view,arch_db:base_user_empty_password.empty_password_wizard_view +msgid "Are you sure you want to empty password of selected users?" +msgstr "" + +#. module: base_user_empty_password +#: model_terms:ir.ui.view,arch_db:base_user_empty_password.empty_password_wizard_view +msgid "Cancel" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__create_uid +msgid "Created by" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__create_date +msgid "Created on" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__display_name +msgid "Display Name" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.actions.act_window,name:base_user_empty_password.empty_password_wizard_action +#: model_terms:ir.ui.view,arch_db:base_user_empty_password.empty_password_wizard_view +msgid "Empty Password" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model,name:base_user_empty_password.model_empty_password_wizard +msgid "Empty Password Wizard" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_res_users__has_password +msgid "Has Password" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__id +msgid "ID" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_user_empty_password +#. odoo-python +#: code:addons/base_user_empty_password/wizard/empty_password.py:0 +msgid "This can only be used on users." +msgstr "" + +#. module: base_user_empty_password +#: model:ir.model,name:base_user_empty_password.model_res_users +#: model:ir.model.fields,field_description:base_user_empty_password.field_empty_password_wizard__user_ids +msgid "User" +msgstr "" diff --git a/base_user_empty_password/models/__init__.py b/base_user_empty_password/models/__init__.py new file mode 100644 index 0000000000..8835165330 --- /dev/null +++ b/base_user_empty_password/models/__init__.py @@ -0,0 +1 @@ +from . import res_users diff --git a/base_user_empty_password/models/res_users.py b/base_user_empty_password/models/res_users.py new file mode 100644 index 0000000000..84cb481682 --- /dev/null +++ b/base_user_empty_password/models/res_users.py @@ -0,0 +1,25 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import fields, models + + +class ResUsers(models.Model): + _inherit = "res.users" + + has_password = fields.Boolean(compute="_compute_has_password") + + def _compute_has_password(self): + # Bypass ORM as password is always empty in cache + self.env.cr.execute( + """SELECT id, password FROM res_users WHERE id IN %s;""", (tuple(self.ids),) + ) + res = {row[0]: row[1] for row in self.env.cr.fetchall()} + for user in self: + user.has_password = bool(res.get(user.id)) + + def _empty_password(self): + # Update in DB to avoid using crypt context + self.env.cr.execute( + """UPDATE res_users SET password = %s WHERE id IN %s""", + ("", (tuple(self.ids),)), + ) diff --git a/base_user_empty_password/pyproject.toml b/base_user_empty_password/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/base_user_empty_password/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/base_user_empty_password/readme/CONTRIBUTORS.md b/base_user_empty_password/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..fd802b9c91 --- /dev/null +++ b/base_user_empty_password/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Akim Juillerat +- Chau Le diff --git a/base_user_empty_password/readme/CREDITS.md b/base_user_empty_password/readme/CREDITS.md new file mode 100644 index 0000000000..573d68b7e8 --- /dev/null +++ b/base_user_empty_password/readme/CREDITS.md @@ -0,0 +1 @@ +The migration of this module from 14.0 to 18.0 was financially supported by Camptocamp. diff --git a/base_user_empty_password/readme/DESCRIPTION.md b/base_user_empty_password/readme/DESCRIPTION.md new file mode 100644 index 0000000000..cdb902d245 --- /dev/null +++ b/base_user_empty_password/readme/DESCRIPTION.md @@ -0,0 +1,3 @@ +This module provides a wizard to allow emptying users password field. + +This could be useful to force the user to use another sign on method than Odoo. diff --git a/base_user_empty_password/security/ir.model.access.csv b/base_user_empty_password/security/ir.model.access.csv new file mode 100644 index 0000000000..ca08092624 --- /dev/null +++ b/base_user_empty_password/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_empty_password_wizard,access_empty_password_wizard,model_empty_password_wizard,base.group_erp_manager,1,1,1,1 diff --git a/base_user_empty_password/static/description/icon.png b/base_user_empty_password/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/base_user_empty_password/static/description/icon.png differ diff --git a/base_user_empty_password/static/description/index.html b/base_user_empty_password/static/description/index.html new file mode 100644 index 0000000000..61ac6795b2 --- /dev/null +++ b/base_user_empty_password/static/description/index.html @@ -0,0 +1,434 @@ + + + + + +Empty users password + + + +
+

Empty users password

+ + +

Beta License: AGPL-3 OCA/server-auth Translate me on Weblate Try me on Runboat

+

This module provides a wizard to allow emptying users password field.

+

This could be useful to force the user to use another sign on method +than Odoo.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+ +
+

Other credits

+

The migration of this module from 14.0 to 18.0 was financially supported +by Camptocamp.

+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

grindtildeath

+

This module is part of the OCA/server-auth project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/base_user_empty_password/tests/__init__.py b/base_user_empty_password/tests/__init__.py new file mode 100644 index 0000000000..da234a960b --- /dev/null +++ b/base_user_empty_password/tests/__init__.py @@ -0,0 +1 @@ +from . import test_user_empty_password diff --git a/base_user_empty_password/tests/test_user_empty_password.py b/base_user_empty_password/tests/test_user_empty_password.py new file mode 100644 index 0000000000..933a497403 --- /dev/null +++ b/base_user_empty_password/tests/test_user_empty_password.py @@ -0,0 +1,39 @@ +# Copyright 2021 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo.exceptions import UserError + +from odoo.addons.base.tests.common import SavepointCaseWithUserDemo + + +class TestUserEmptyPassword(SavepointCaseWithUserDemo): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.wizard_model = cls.env["empty.password.wizard"] + + def test_empty_password_button(self): + """Test that the wizard's default_get correctly assigns user_ids.""" + context = { + "active_model": "res.users", + "active_ids": [self.user_demo.id], + } + + wizard = self.wizard_model.with_context(**context).create({}) + + wizard.empty_password_button() + + self.assertIn(self.user_demo, wizard.user_ids) + self.assertFalse(self.user_demo.has_password) + + def test_invalid_model(self): + """Test that the wizard raises a UserError + when active_model is not res.users. + """ + context = { + "active_model": "res.partner", + "active_ids": [self.user_demo.id], + } + + with self.assertRaises(UserError): + self.wizard_model.with_context(**context).create({}) diff --git a/base_user_empty_password/views/res_users.xml b/base_user_empty_password/views/res_users.xml new file mode 100644 index 0000000000..83ef384cbb --- /dev/null +++ b/base_user_empty_password/views/res_users.xml @@ -0,0 +1,15 @@ + + + + res.users.form + res.users + + + + + + + + + + diff --git a/base_user_empty_password/wizard/__init__.py b/base_user_empty_password/wizard/__init__.py new file mode 100644 index 0000000000..00e7d95e31 --- /dev/null +++ b/base_user_empty_password/wizard/__init__.py @@ -0,0 +1 @@ +from . import empty_password diff --git a/base_user_empty_password/wizard/empty_password.py b/base_user_empty_password/wizard/empty_password.py new file mode 100644 index 0000000000..d19a291e81 --- /dev/null +++ b/base_user_empty_password/wizard/empty_password.py @@ -0,0 +1,27 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class EmptyPasswordWizard(models.TransientModel): + _name = "empty.password.wizard" + _description = "Empty Password Wizard" + + user_ids = fields.Many2many("res.users", readonly=True) + + @api.model + def default_get(self, fields): + res = super().default_get(fields) + + if self.env.context.get("active_model") != "res.users": + raise UserError(_("This can only be used on users.")) + + res["user_ids"] = self.env.context.get("active_ids") or [] + + return res + + def empty_password_button(self): + self.ensure_one() + self.user_ids._empty_password() + return {"type": "ir.actions.client", "tag": "reload"} diff --git a/base_user_empty_password/wizard/empty_password.xml b/base_user_empty_password/wizard/empty_password.xml new file mode 100644 index 0000000000..158f05b126 --- /dev/null +++ b/base_user_empty_password/wizard/empty_password.xml @@ -0,0 +1,31 @@ + + + + Empty Password + empty.password.wizard + +
+ +
+

Are you sure you want to empty password of selected users?

+
+
+
+ +
+
+ + Empty Password + empty.password.wizard + form + new + + +