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

184 lines
7.1 KiB
Python

# Copyright 2016 LasLabs Inc.
# Copyright 2023 Onestein (<https://www.onestein.eu>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from unittest import mock
from freezegun import freeze_time
from requests.exceptions import HTTPError
from odoo import http
from odoo.exceptions import ValidationError
from odoo.tests.common import HOST, HttpCase, Opener, get_db_name, tagged
from odoo.addons.auth_signup.models.res_users import SignupError
class EndTestException(Exception):
"""It allows for isolation of resources by raise"""
@tagged("-at_install", "post_install")
class TestPasswordSecuritySignup(HttpCase):
def signup(self, username, password):
"""Signup user"""
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/signup",
data={
"login": username,
"name": username,
"password": password,
"confirm_password": password,
"csrf_token": http.Request.csrf_token(self),
},
)
res_post.raise_for_status()
return res_post
def test_01_signup_user_fail(self):
"""It should fail when signup user with weak password"""
# Weak password: signup failed
response = self.signup("jackoneill", "jackoneill")
# Ensure we stay in the signup page
self.assertEqual(response.request.path_url, "/web/signup")
self.assertEqual(response.status_code, 200)
self.assertIn(
"Must contain the following:",
response.text,
)
def test_02_signup_user_success(self):
"""It should succeed when signup user with strong password"""
# Weak password: signup failed
response = self.signup("jackoneill", "!asdQWE12345_3")
# Ensure we were logged in
self.assertEqual(
response.request.path_url, "/web/login_successful?account_created=True"
)
self.assertEqual(response.status_code, 200)
def test_03_create_user_signup(self):
"""Password is checked when signup to create a new user"""
partner = self.env["res.partner"].create({"name": "test partner"})
vals = {
"name": "Test User",
"login": "test_user",
"email": "test_user@odoo.com",
"password": "test_user_password",
"partner_id": partner.id,
}
# Weak password: SignupError is raised
with self.assertRaises(SignupError):
self.env["res.users"].signup(vals)
# Stronger password: no error raised
vals["password"] = "asdQWE12345_3"
with freeze_time("2020-01-01"):
login, pwd = self.env["res.users"].signup(vals)
# check created user
created_user = self.env["res.users"].search([("login", "=", "test_user")])
self.assertEqual(login, "test_user")
password_write_date = created_user.password_write_date
self.assertTrue(password_write_date)
# Weak password: ValidationError is raised
with self.assertRaises(ValidationError):
created_user.password = "test_user_password"
self.assertEqual(password_write_date, created_user.password_write_date)
# Stronger password: no error raised
created_user.password = "!asdQWE12345_3"
self.assertNotEqual(password_write_date, created_user.password_write_date)
def test_04_web_auth_signup_invalid_qcontext(self):
"""It should catch AttributeError"""
with mock.patch("odoo.http.db_filter") as db_filter:
db_filter.side_effect = lambda dbs, host=None: [get_db_name()]
with self.assertRaises(AttributeError):
# 'TestPasswordSecuritySignup' object has no attribute 'session'
self.url_open(
"/web/signup",
data={
"csrf_token": http.Request.csrf_token(self),
},
)
def test_05_web_auth_signup_invalid_qcontext(self):
"""It should catch EndTestException on signup qcontext"""
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.addons.auth_signup.controllers.main.AuthSignupHome.get_auth_signup_qcontext"
) as qcontext:
qcontext.side_effect = EndTestException
with self.assertRaises(HTTPError):
# Catch HTTPError: 400 Client Error: BAD REQUEST
self.signup("jackoneill", "!asdQWE12345_3")
def test_06_web_auth_signup_invalid_render(self):
"""It should render & return signup form on invalid"""
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()]
# Signup: no name or partner given for new user
response = self.url_open(
"/web/signup",
data={
"login": "test@test.com",
"password": "!asdQWE12345_7",
"confirm_password": "!asdQWE12345_7",
"csrf_token": http.Request.csrf_token(self),
},
)
# Ensure we stay in the signup page
self.assertEqual(response.request.path_url, "/web/signup")
self.assertEqual(response.status_code, 200)
self.assertIn(
"Signup: no name or partner given for new user",
response.text,
)
self.assertIn("X-Frame-Options", response.headers)
self.assertEqual(response.headers["X-Frame-Options"], "SAMEORIGIN")
self.assertIn("Content-Security-Policy", response.headers)
self.assertEqual(
response.headers["Content-Security-Policy"], "frame-ancestors 'self'"
)
def test_07_cloned_user_password_write_date(self):
"""Users that are cloned should have their password_write_date updated"""
partner = self.env["res.partner"].create({"name": "test partner"})
vals = {
"name": "Test User",
"login": "test_user",
"email": "test_user@odoo.com",
"password": "Test_user_password123$",
"partner_id": partner.id,
}
with freeze_time("2020-01-01"):
self.env["res.users"].signup(vals)
original_user = self.env["res.users"].search([("login", "=", "test_user")])
copied_user = original_user.copy()
self.assertTrue(
copied_user.password_write_date > original_user.password_write_date
)