diff --git a/password_security/__manifest__.py b/password_security/__manifest__.py index a5408f9614..de5e4f4f80 100644 --- a/password_security/__manifest__.py +++ b/password_security/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Password Security", "summary": "Allow admin to set password security requirements.", - "version": "15.0.1.1.4", + "version": "15.0.1.2.0", "author": "LasLabs, " "Onestein, " "Kaushal Prajapati, " diff --git a/password_security/migrations/15.0.1.2.0/post-migration.py b/password_security/migrations/15.0.1.2.0/post-migration.py new file mode 100644 index 0000000000..6345ae26ba --- /dev/null +++ b/password_security/migrations/15.0.1.2.0/post-migration.py @@ -0,0 +1,17 @@ +# Copyright 2023 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl) + +import logging + +from odoo import SUPERUSER_ID, api + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + if not version: + return + env = api.Environment(cr, SUPERUSER_ID, {}) + companies = env["res.company"].with_context(active_test=False).search([]) + _logger.info("Enable the password policy on %s companies", len(companies)) + companies.write({"password_policy_enabled": True}) diff --git a/password_security/models/res_company.py b/password_security/models/res_company.py index c96663115e..8245d5fc5e 100644 --- a/password_security/models/res_company.py +++ b/password_security/models/res_company.py @@ -9,6 +9,7 @@ class ResCompany(models.Model): _inherit = "res.company" + password_policy_enabled = fields.Boolean(default=False) password_expiration = fields.Integer( "Days", default=60, diff --git a/password_security/models/res_config_settings.py b/password_security/models/res_config_settings.py index 7db2462b08..13d6018025 100644 --- a/password_security/models/res_config_settings.py +++ b/password_security/models/res_config_settings.py @@ -6,6 +6,9 @@ class ResConfigSettings(models.TransientModel): _inherit = "res.config.settings" + password_policy_enabled = fields.Boolean( + related="company_id.password_policy_enabled", readonly=False + ) password_expiration = fields.Integer( related="company_id.password_expiration", readonly=False ) diff --git a/password_security/models/res_users.py b/password_security/models/res_users.py index 5e98f5c4cb..7eed74270c 100644 --- a/password_security/models/res_users.py +++ b/password_security/models/res_users.py @@ -55,6 +55,8 @@ def write(self, vals): def get_password_policy(self): data = super(ResUsers, self).get_password_policy() company_id = self.env.user.company_id + if not company_id.password_policy_enabled: + return data data.update( { "password_lower": company_id.password_lower, @@ -69,7 +71,8 @@ def get_password_policy(self): def _check_password_policy(self, passwords): result = super(ResUsers, self)._check_password_policy(passwords) - + if not self.env.user.company_id.password_policy_enabled: + return result for password in passwords: if not password: continue @@ -115,6 +118,8 @@ def password_match_message(self): return "\r".join(message) def _check_password(self, password): + if not self.env.user.company_id.password_policy_enabled: + return True self._check_password_rules(password) self._check_password_history(password) return True @@ -143,6 +148,8 @@ def _check_password_rules(self, password): def _password_has_expired(self): self.ensure_one() + if not self.company_id.password_policy_enabled: + return False if not self.password_write_date: return True @@ -165,6 +172,8 @@ def _validate_pass_reset(self): :return: True on allowed reset """ for user in self: + if not user.company_id.password_policy_enabled: + continue pass_min = user.company_id.password_minimum if pass_min <= 0: continue @@ -204,7 +213,8 @@ def _check_password_history(self, password): def _set_encrypted_password(self, uid, pw): """It saves password crypt history for history rules""" res = super(ResUsers, self)._set_encrypted_password(uid, pw) - + if not self.env.user.company_id.password_policy_enabled: + return res self.write({"password_history_ids": [(0, 0, {"password_crypt": pw})]}) return res diff --git a/password_security/tests/test_password_history.py b/password_security/tests/test_password_history.py index 00d6cb563f..a36e7381df 100644 --- a/password_security/tests/test_password_history.py +++ b/password_security/tests/test_password_history.py @@ -12,6 +12,7 @@ def test_check_password_history(self): user = self.env.ref("base.user_admin") user.company_id.update( { + "password_policy_enabled": True, "password_estimate": 0, "password_length": 0, "password_lower": 0, diff --git a/password_security/tests/test_password_security_home.py b/password_security/tests/test_password_security_home.py index d8d24302d0..8a221c3121 100644 --- a/password_security/tests/test_password_security_home.py +++ b/password_security/tests/test_password_security_home.py @@ -33,6 +33,8 @@ def __init__(self): class TestPasswordSecurityHome(TransactionCase): def setUp(self): super(TestPasswordSecurityHome, self).setUp() + self.main_comp = self.env.ref("base.main_company") + self.main_comp.password_policy_enabled = True self.PasswordSecurityHome = main.PasswordSecurityHome self.password_security_home = self.PasswordSecurityHome() self.passwd = "I am a password!" @@ -175,6 +177,11 @@ def test_web_auth_signup_invalid_render(self): @mock.patch("odoo.http.WebRequest.validate_csrf", return_value=True) class LoginCase(HttpCase): + def setUp(self): + super(LoginCase, self).setUp() + self.main_comp = self.env.ref("base.main_company") + self.main_comp.password_policy_enabled = True + def test_web_login_authenticate(self, *args): """It should allow authenticating by login""" response = self.url_open( diff --git a/password_security/tests/test_res_users.py b/password_security/tests/test_res_users.py index 9e6d8b875c..0de0ef3048 100644 --- a/password_security/tests/test_res_users.py +++ b/password_security/tests/test_res_users.py @@ -2,10 +2,10 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). from odoo.exceptions import UserError -from odoo.tests.common import SavepointCase +from odoo.tests.common import TransactionCase -class TestResUsers(SavepointCase): +class TestResUsers(TransactionCase): @classmethod def setUpClass(cls): super(TestResUsers, cls).setUpClass() @@ -17,6 +17,7 @@ def setUpClass(cls): } cls.password = "asdQWE123$%^" cls.main_comp = cls.env.ref("base.main_company") + cls.main_comp.password_policy_enabled = True cls.vals = { "name": "User", "login": cls.login, diff --git a/password_security/tests/test_reset_password.py b/password_security/tests/test_reset_password.py index 0c0e79c739..f1f6374e59 100644 --- a/password_security/tests/test_reset_password.py +++ b/password_security/tests/test_reset_password.py @@ -10,6 +10,7 @@ class TestPasswordSecurityReset(HttpCase): def setUp(self): super().setUp() + self.env.company.password_policy_enabled = True # Create user with strong password: no error raised new_test_user(self.env, "jackoneill", password="!asdQWE12345_3") diff --git a/password_security/views/res_config_settings_views.xml b/password_security/views/res_config_settings_views.xml index 7bcc8b2de7..a1d01cec3d 100644 --- a/password_security/views/res_config_settings_views.xml +++ b/password_security/views/res_config_settings_views.xml @@ -18,11 +18,23 @@ -
-
+
+
+ +
-