Skip to content
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
13 changes: 3 additions & 10 deletions password_security/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,8 @@
"Open Source Integrators,"
"Odoo Community Association (OCA)",
"category": "Base",
"depends": [
"auth_signup",
"auth_password_policy_signup",
],
"external_dependencies": {
"python": ["zxcvbn"],
},
"depends": ["auth_signup", "auth_password_policy_signup"],
"external_dependencies": {"python": ["zxcvbn"]},
"website": "https://github.com/OCA/server-auth",
"license": "LGPL-3",
"data": [
Expand All @@ -30,8 +25,6 @@
"security/res_users_pass_history.xml",
"views/res_company_view.xml",
],
"demo": [
"demo/res_users.xml",
],
"demo": ["demo/res_users.xml"],
"installable": True,
}
51 changes: 20 additions & 31 deletions password_security/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,34 @@

from odoo import http
from odoo.http import request

from odoo.addons.auth_signup.controllers.main import AuthSignupHome
from odoo.addons.web.controllers.main import ensure_db, Session
from odoo.addons.web.controllers.main import Session, ensure_db

from ..exceptions import PassError


class PasswordSecuritySession(Session):

@http.route()
def change_password(self, fields):
new_password = operator.itemgetter('new_password')(
dict(list(map(operator.itemgetter('name', 'value'), fields)))
new_password = operator.itemgetter("new_password")(
dict(list(map(operator.itemgetter("name", "value"), fields)))
)
user_id = request.env.user
user_id._check_password(new_password)
return super(PasswordSecuritySession, self).change_password(fields)


class PasswordSecurityHome(AuthSignupHome):

def do_signup(self, qcontext):
password = qcontext.get('password')
password = qcontext.get("password")
user_id = request.env.user
user_id._check_password(password)
return super(PasswordSecurityHome, self).do_signup(qcontext)

@http.route('/password_security/estimate', auth='none', type='json')
@http.route("/password_security/estimate", auth="none", type="json")
def estimate(self, password):
return request.env['res.users'].get_estimation(password)
return request.env["res.users"].get_estimation(password)

@http.route()
def web_login(self, *args, **kw):
Expand All @@ -48,45 +47,35 @@ def web_login(self, *args, **kw):
request.env.user.action_expire_password()
request.session.logout(keep_db=True)
# I was kicked out, so set login_success in request params to False
request.params['login_success'] = False
request.params["login_success"] = False
redirect = request.env.user.partner_id.signup_url
return http.redirect_with_hash(redirect)

@http.route()
def web_auth_signup(self, *args, **kw):
try:
return super(PasswordSecurityHome, self).web_auth_signup(
*args, **kw
)
return super(PasswordSecurityHome, self).web_auth_signup(*args, **kw)
except PassError as e:
qcontext = self.get_auth_signup_qcontext()
qcontext['error'] = str(e)
return request.render('auth_signup.signup', qcontext)
qcontext["error"] = str(e)
return request.render("auth_signup.signup", qcontext)

@http.route()
def web_auth_reset_password(self, *args, **kw):
""" It provides hook to disallow front-facing resets inside of min
"""It provides hook to disallow front-facing resets inside of min
Unfortuantely had to reimplement some core logic here because of
nested logic in parent
"""
qcontext = self.get_auth_signup_qcontext()
if (
request.httprequest.method == 'POST' and
qcontext.get('login') and
'error' not in qcontext and
'token' not in qcontext
request.httprequest.method == "POST"
and qcontext.get("login")
and "error" not in qcontext
and "token" not in qcontext
):
login = qcontext.get('login')
user_ids = request.env.sudo().search(
[('login', '=', login)],
limit=1,
)
login = qcontext.get("login")
user_ids = request.env.sudo().search([("login", "=", login)], limit=1,)
if not user_ids:
user_ids = request.env.sudo().search(
[('email', '=', login)],
limit=1,
)
user_ids = request.env.sudo().search([("email", "=", login)], limit=1,)
user_ids._validate_pass_reset()
return super(PasswordSecurityHome, self).web_auth_reset_password(
*args, **kw
)
return super(PasswordSecurityHome, self).web_auth_reset_password(*args, **kw)
10 changes: 2 additions & 8 deletions password_security/demo/res_users.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>

<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2016 LasLabs Inc.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
-->

<odoo>

<record id="base.user_root" model="res.users">
<field name="password_write_date"
eval="datetime.now()"
/>
<field name="password_write_date" eval="datetime.now()" />
</record>

</odoo>
1 change: 1 addition & 0 deletions password_security/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class PassError(UserError):
""" Example: When you try to create an insecure password."""

def __init__(self, msg):
self.message = msg
super(PassError, self).__init__(msg)
46 changes: 17 additions & 29 deletions password_security/models/res_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,49 @@
# Copyright 2017 Kaushal Prajapati <kbprajapati@live.com>.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

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


class ResCompany(models.Model):
_inherit = 'res.company'
_inherit = "res.company"

password_expiration = fields.Integer(
'Days',
default=60,
help='How many days until passwords expire',
"Days", default=60, help="How many days until passwords expire",
)
password_length = fields.Integer(
'Characters',
default=12,
help='Minimum number of characters',
"Characters", default=12, help="Minimum number of characters",
)
password_lower = fields.Integer(
'Lowercase',
default=1,
help='Require number of lowercase letters',
"Lowercase", default=1, help="Require number of lowercase letters",
)
password_upper = fields.Integer(
'Uppercase',
default=1,
help='Require number of uppercase letters',
"Uppercase", default=1, help="Require number of uppercase letters",
)
password_numeric = fields.Integer(
'Numeric',
default=1,
help='Require number of numeric digits',
"Numeric", default=1, help="Require number of numeric digits",
)
password_special = fields.Integer(
'Special',
default=1,
help='Require number of unique special characters',
"Special", default=1, help="Require number of unique special characters",
)
password_estimate = fields.Integer(
'Estimation',
"Estimation",
default=3,
help='Required score for the strength estimation. Between 0 and 4',
help="Required score for the strength estimation. Between 0 and 4",
)
password_history = fields.Integer(
'History',
"History",
default=30,
help='Disallow reuse of this many previous passwords - use negative '
'number for infinite, or 0 to disable',
help="Disallow reuse of this many previous passwords - use negative "
"number for infinite, or 0 to disable",
)
password_minimum = fields.Integer(
'Minimum Hours',
"Minimum Hours",
default=24,
help='Amount of hours until a user may change password again',
help="Amount of hours until a user may change password again",
)

@api.constrains('password_estimate')
@api.constrains("password_estimate")
def _check_password_estimate(self):
if 0 > self.password_estimate > 4:
raise ValidationError(_('The estimation must be between 0 and 4.'))
raise ValidationError(_("The estimation must be between 0 and 4."))
8 changes: 2 additions & 6 deletions password_security/models/res_config_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ class ResConfigSettings(models.TransientModel):
password_length = fields.Integer(
related="company_id.password_length", readonly=False
)
password_lower = fields.Integer(
related="company_id.password_lower", readonly=False
)
password_upper = fields.Integer(
related="company_id.password_upper", readonly=False
)
password_lower = fields.Integer(related="company_id.password_lower", readonly=False)
password_upper = fields.Integer(related="company_id.password_upper", readonly=False)
password_numeric = fields.Integer(
related="company_id.password_numeric", readonly=False
)
Expand Down
Loading