Skip to content

Commit

Permalink
[REV] password_security: Restore password_estimate.
Browse files Browse the repository at this point in the history
This reverts commit c8d5d68 which
should not have been removed as part of the migration to 15.0.
#482
  • Loading branch information
amh-mw committed Sep 4, 2024
1 parent f712770 commit 3fe632a
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 7 deletions.
2 changes: 2 additions & 0 deletions password_security/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ It contains features such as
* Password minimum number of uppercase letters
* Password minimum number of numbers
* Password minimum number of special characters
* Password strength estimation

**Table of contents**

Expand Down Expand Up @@ -70,6 +71,7 @@ These are defined at the company level:
password_special 0 Minimum number of unique special character in password
password_history 30 Disallow reuse of this many previous passwords
password_minimum 24 Amount of hours that must pass until another reset
password_estimate 3 Required score for the strength estimation.
===================== ======= ===================================================

Usage
Expand Down
3 changes: 3 additions & 0 deletions password_security/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"auth_password_policy_signup",
],
"website": "https://github.com/OCA/server-auth",
"external_dependencies": {
"python": ["zxcvbn"],
},
"license": "LGPL-3",
"data": [
"views/res_config_settings_views.xml",
Expand Down
13 changes: 12 additions & 1 deletion password_security/models/res_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# Copyright 2017 Kaushal Prajapati <kbprajapati@live.com>.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

from odoo import fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class ResCompany(models.Model):
Expand Down Expand Up @@ -33,6 +34,11 @@ class ResCompany(models.Model):
default=1,
help="Require number of unique special characters",
)
password_estimate = fields.Integer(
"Estimation",
default=3,
help="Required score for the strength estimation. Between 0 and 4",
)
password_history = fields.Integer(
"History",
default=30,
Expand All @@ -44,3 +50,8 @@ class ResCompany(models.Model):
default=24,
help="Amount of hours until a user may change password again",
)

@api.constrains("password_estimate")
def _check_password_estimate(self):
if self.password_estimate < 0 or self.password_estimate > 4:
raise ValidationError(_("The estimation must be between 0 and 4."))
3 changes: 3 additions & 0 deletions password_security/models/res_config_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ class ResConfigSettings(models.TransientModel):
password_special = fields.Integer(
related="company_id.password_special", readonly=False
)
password_estimate = fields.Integer(
related="company_id.password_estimate", readonly=False
)
24 changes: 24 additions & 0 deletions password_security/models/res_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,24 @@
# Copyright 2018 Modoolar <info@modoolar.com>.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

import logging
import re
from datetime import datetime, timedelta

from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError

_logger = logging.getLogger(__name__)
try:
import zxcvbn

zxcvbn.feedback._ = _
except ImportError:
_logger.debug(

Check warning on line 19 in password_security/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

password_security/models/res_users.py#L18-L19

Added lines #L18 - L19 were not covered by tests
"Could not import zxcvbn. Please make sure this library is available"
" in your environment."
)


def delta_now(**kwargs):
return datetime.now() + timedelta(**kwargs)
Expand Down Expand Up @@ -42,6 +54,7 @@ def get_password_policy(self):
"password_upper": company_id.password_upper,
"password_numeric": company_id.password_numeric,
"password_special": company_id.password_special,
"password_estimate": company_id.password_estimate,
}
)
return data
Expand All @@ -56,6 +69,10 @@ def _check_password_policy(self, passwords):

return result

@api.model
def get_estimation(self, password):
return zxcvbn.zxcvbn(password)

def password_match_message(self):
self.ensure_one()
company_id = self.company_id
Expand Down Expand Up @@ -114,6 +131,13 @@ def _check_password_rules(self, password):
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:
if estimation["feedback"]["warning"]:
raise UserError(estimation["feedback"]["warning"])

Check warning on line 137 in password_security/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

password_security/models/res_users.py#L137

Added line #L137 was not covered by tests
else:
raise UserError(_("Choose a stronger password!"))

Check warning on line 139 in password_security/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

password_security/models/res_users.py#L139

Added line #L139 was not covered by tests

return True

def _password_has_expired(self):
Expand Down
1 change: 1 addition & 0 deletions password_security/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ These are defined at the company level:
password_special 0 Minimum number of unique special character in password
password_history 30 Disallow reuse of this many previous passwords
password_minimum 24 Amount of hours that must pass until another reset
password_estimate 3 Required score for the strength estimation.
===================== ======= ===================================================
1 change: 1 addition & 0 deletions password_security/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ It contains features such as
* Password minimum number of uppercase letters
* Password minimum number of numbers
* Password minimum number of special characters
* Password strength estimation
1 change: 1 addition & 0 deletions password_security/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from . import test_change_password
from . import test_res_users
from . import test_res_config_settings
from . import test_login
from . import test_password_history
from . import test_reset_password
Expand Down
1 change: 1 addition & 0 deletions password_security/tests/test_password_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def test_check_password_history(self):
user = self.env.ref("base.user_admin")
user.company_id.update(
{
"password_estimate": 0,
"password_lower": 0,
"password_history": 1,
"password_numeric": 0,
Expand Down
24 changes: 24 additions & 0 deletions password_security/tests/test_res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2023 Onestein (<https://www.onestein.eu>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase


class TestConfigSettings(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.config = cls.env["res.config.settings"].create({})

def test_01_password_estimate_range(self):
"""The estimation must be between 0 and 4"""
self.config.password_estimate = 0
self.config.password_estimate = 2
self.config.password_estimate = 4

with self.assertRaises(ValidationError):
self.config.password_estimate = 5

with self.assertRaises(ValidationError):
self.config.password_estimate = -1
18 changes: 12 additions & 6 deletions password_security/views/res_config_settings_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,18 @@
<field name="password_special" class="oe_inline" />
</span>
</div>
<div class="mt16">
<span id="minlength">
Minimum number of characters
</span>
</div>
</div>
<div class="mt16">
<span id="minlength">
Minimum number of characters
</span>
</div>
<div class="mt16">
<span>
Minimum number of strength estimation
<field name="password_estimate" class="oe_inline" />
</span>
</div>
</div>
</xpath>

<!-- Add oe_inline attribute to minlength -->
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pyjwt
pysaml2
python-jose
python-ldap
zxcvbn

0 comments on commit 3fe632a

Please sign in to comment.