Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][REV] password_security: Restore password_estimate. #687

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
"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 @@

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 @@
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
Loading