diff --git a/password_security/models/res_company.py b/password_security/models/res_company.py index f8b9116993..1c22ac9657 100644 --- a/password_security/models/res_company.py +++ b/password_security/models/res_company.py @@ -9,6 +9,8 @@ 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 dae396133f..787f488883 100644 --- a/password_security/models/res_users.py +++ b/password_security/models/res_users.py @@ -55,16 +55,17 @@ def write(self, vals): def get_password_policy(self): data = super(ResUsers, self).get_password_policy() company_id = self.env.user.company_id - data.update( - { - "password_lower": company_id.password_lower, - "password_upper": company_id.password_upper, - "password_numeric": company_id.password_numeric, - "password_special": company_id.password_special, - "password_length": company_id.password_length, - "password_estimate": company_id.password_estimate, - } - ) + if company_id.password_policy_enabled: + data.update( + { + "password_lower": company_id.password_lower, + "password_upper": company_id.password_upper, + "password_numeric": company_id.password_numeric, + "password_special": company_id.password_special, + "password_length": company_id.password_length, + "password_estimate": company_id.password_estimate, + } + ) return data def _check_password_policy(self, passwords): @@ -115,6 +116,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 @@ -124,25 +127,28 @@ def _check_password_rules(self, password): if not password: return True company_id = self.company_id - password_regex = [ - "^", - "(?=.*?[a-z]){" + str(company_id.password_lower) + ",}", - "(?=.*?[A-Z]){" + str(company_id.password_upper) + ",}", - "(?=.*?\\d){" + str(company_id.password_numeric) + ",}", - r"(?=.*?[\W_]){" + str(company_id.password_special) + ",}", - ".{%d,}$" % int(company_id.password_length), - ] - if not re.search("".join(password_regex), password): - raise ValidationError(self.password_match_message()) - - estimation = self.get_estimation(password) - if estimation["score"] < company_id.password_estimate: - raise UserError(estimation["feedback"]["warning"]) + if company_id.password_policy_enabled: + password_regex = [ + "^", + "(?=.*?[a-z]){" + str(company_id.password_lower) + ",}", + "(?=.*?[A-Z]){" + str(company_id.password_upper) + ",}", + "(?=.*?\\d){" + str(company_id.password_numeric) + ",}", + r"(?=.*?[\W_]){" + str(company_id.password_special) + ",}", + ".{%d,}$" % int(company_id.password_length), + ] + if not re.search("".join(password_regex), password): + raise ValidationError(self.password_match_message()) + + estimation = self.get_estimation(password) + if estimation["score"] < company_id.password_estimate: + raise UserError(estimation["feedback"]["warning"]) return True 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 +171,8 @@ def _validate_pass_reset(self): :return: True on allowed reset """ for rec_id in self: + if not rec_id.company_id.password_policy_enabled: + continue pass_min = rec_id.company_id.password_minimum if pass_min <= 0: pass @@ -202,6 +210,7 @@ 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_security_home.py b/password_security/tests/test_password_security_home.py index 65b7495418..7d1e9477b1 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!" @@ -219,6 +221,11 @@ def test_web_auth_reset_password_success(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/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 @@ -
-
+
+
+ +
-