oca-server-auth/odoo-bringout-oca-server-auth-password_security/password_security/tests/test_login.py
2025-08-29 15:43:06 +02:00

149 lines
5.4 KiB
Python

# Copyright 2023 Onestein (<https://www.onestein.eu>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from datetime import datetime, timedelta
from unittest import mock
from odoo import http, registry
from odoo.exceptions import UserError, ValidationError
from odoo.tests.common import HOST, HttpCase, Opener, get_db_name, new_test_user, tagged
@tagged("-at_install", "post_install")
class TestPasswordSecurityLogin(HttpCase):
def setUp(self):
super().setUp()
self.username = "jackoneill"
self.passwd = "!asdQWE12345_3"
# Create user with strong password: no error raised
new_test_user(self.env, self.username, password=self.passwd)
def login(self, username, password):
"""Log in with provided credentials."""
self.session = http.root.session_store.new()
self.opener = Opener(self.env.cr)
self.opener.cookies.set("session_id", self.session.sid, domain=HOST, path="/")
with mock.patch("odoo.http.db_filter") as db_filter:
db_filter.side_effect = lambda dbs, host=None: [get_db_name()]
res_post = self.url_open(
"/web/login",
data={
"login": username,
"password": password,
"csrf_token": http.Request.csrf_token(self),
},
)
res_post.raise_for_status()
return res_post
def test_01_create_user_fail(self):
"""It should fail when creating user with short password"""
# Short password: UserError is raised
with self.assertRaises(UserError):
new_test_user(self.env, "new_user", password="abc")
def test_02_create_user_fail(self):
"""It should fail when creating user with weak password"""
# Weak password: ValidationError is raised
with self.assertRaises(ValidationError):
new_test_user(self.env, "new_user", password="abcdefgh")
def test_03_web_login_success(self):
"""Allow authenticating by login"""
# Log in
response = self.login(self.username, self.passwd)
# Ensure we end up on the right page
self.assertEqual(response.request.path_url, "/web")
self.assertEqual(response.status_code, 200)
def test_04_web_login_fail(self):
"""Fail authenticating with wrong password"""
# Try to log in
response = self.login(self.username, "wrong")
# Ensure we stay on the login page
self.assertEqual(response.request.path_url, "/web/login")
self.assertEqual(response.status_code, 200)
self.assertIn(
"Wrong login/password",
response.text,
)
def test_05_web_login_expire_pass(self):
"""It should expire password if necessary"""
# Make password expired
three_days_ago = datetime.now() - timedelta(days=3)
with registry(get_db_name()).cursor() as cr:
env = self.env(cr)
user = env["res.users"].search([("login", "=", self.username)])
user.password_write_date = three_days_ago
user.company_id.password_expiration = 1
# Try to log in
response = self.login(self.username, self.passwd)
# Ensure we end up on the password reset page
self.assertIn("/web/reset_password", response.request.path_url)
def test_06_web_login_log_out_if_expired(self):
"""It should log out user if password expired"""
# Log in
response = self.login(self.username, self.passwd)
# Ensure we end up on the right page
self.assertEqual(response.request.path_url, "/web")
self.assertEqual(response.status_code, 200)
# Make password expired while still logged in
three_days_ago = datetime.now() - timedelta(days=3)
with registry(get_db_name()).cursor() as cr:
env = self.env(cr)
user = env["res.users"].search([("login", "=", self.username)])
user.password_write_date = three_days_ago
user.company_id.password_expiration = 1
# Try to access just a page
req_page1 = self.url_open("/web")
self.assertEqual(req_page1.request.path_url, "/web")
self.assertEqual(req_page1.status_code, 200)
# Try to log in again
response = self.login(self.username, self.passwd)
# Ensure we end up on the password reset page
self.assertIn("/web/reset_password", response.request.path_url)
# Try to access just a page: user kicked out
req_page2 = self.url_open("/web")
self.assertEqual("/web/login", req_page2.request.path_url)
self.assertEqual(req_page2.status_code, 200)
def test_07_web_login_redirect(self):
"""It should redirect w/ hash to reset after expiration"""
# Emulate password expired
with mock.patch(
"odoo.addons.password_security.models.res_users.ResUsers._password_has_expired"
) as func_password_has_expired:
func_password_has_expired.return_value = True
# Try to log in
response = self.login(self.username, self.passwd)
# Ensure we end up on the password reset page
self.assertIn("/web/reset_password", response.request.path_url)
# Try to access just a page: user kicked out
req_page = self.url_open("/web")
self.assertEqual("/web/login", req_page.request.path_url)
self.assertEqual(req_page.status_code, 200)