Skip to content

Commit

Permalink
[IMP] Use helper function instead of hardcoded test passwords.
Browse files Browse the repository at this point in the history
It is necessary to remove hardcoded passwords as modules like
auth_password_policy (and external modules like OCA
server-auth/password_security) add additional complexity
requirements that hardcoded passwords may not meet.
  • Loading branch information
amh-mw committed Nov 29, 2023
1 parent cf5a343 commit 359a790
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 41 deletions.
1 change: 0 additions & 1 deletion addons/account/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ def setUpClass(cls, chart_template_ref=None):
user = cls.env['res.users'].create({
'name': 'Because I am accountman!',
'login': 'accountman',
'password': 'accountman',
'groups_id': [(6, 0, cls.env.user.groups_id.ids), (4, cls.env.ref('account.group_account_user').id)],
})
user.partner_id.email = '[email protected]'
Expand Down
3 changes: 0 additions & 3 deletions addons/account/tests/test_chart_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,18 +299,15 @@ def test_message_to_accountants(self):
advisor_users = self.env['res.users'].create([{
'name': 'AccountAdvisorTest1',
'login': 'aat1',
'password': 'aat1aat1',
'groups_id': [(4, accountant_manager_group.id)],
}, {
'name': 'AccountAdvisorTest2',
'login': 'aat2',
'password': 'aat2aat2',
'groups_id': [(4, accountant_manager_group.id)],
}])
normal_user = self.env['res.users'].create([{
'name': 'AccountUserTest1',
'login': 'aut1',
'password': 'aut1aut1',
'groups_id': [(4, self.env.ref('account.group_account_user').id)],
}])
# create situation where we need to recreate the tax during update to get notification(s) sent
Expand Down
1 change: 1 addition & 0 deletions addons/auth_password_policy/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_password
13 changes: 13 additions & 0 deletions addons/auth_password_policy/tests/test_password.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.tests import new_test_pass, TransactionCase


class TestPassword(TransactionCase):
def test_new_test_pass(self):
password1 = new_test_pass(self.env, 'testpass')
password2 = new_test_pass(self.env, 'testpass')
self.assertEqual(password1, password2)

User = self.env['res.users']
User._check_password_policy([password1])
4 changes: 2 additions & 2 deletions addons/calendar/tests/test_calendar_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TestCalendarController(HttpCase):
def setUp(self):
super().setUp()
self.user = new_test_user(self.env, "test_user_1", email="[email protected]", tz="UTC")
self.other_user = new_test_user(self.env, "test_user_2", email="[email protected]", password="P@ssw0rd!", tz="UTC")
self.other_user = new_test_user(self.env, "test_user_2", email="[email protected]", tz="UTC")
self.partner = self.user.partner_id
self.event = (
self.env["calendar.event"]
Expand Down Expand Up @@ -41,7 +41,7 @@ def test_accept_meeting_authenticated(self):
attendee = self.event.attendee_ids.filtered(lambda att: att.partner_id.id == self.other_user.partner_id.id)
token = attendee.access_token
url = "/calendar/meeting/accept?token=%s&id=%d" % (token, self.event.id)
self.authenticate("test_user_2", "P@ssw0rd!")
self.authenticate("test_user_2")
res = self.url_open(url)

self.assertEqual(res.status_code, 200, "Response should = OK")
Expand Down
5 changes: 3 additions & 2 deletions addons/crm/tests/test_performances.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ def test_assign_perf_populated(self):

# randomness: at least 6 queries
with self.with_user('user_sales_manager'):
with self.assertQueryCount(user_sales_manager=6930): # crm 6863 - com 6925
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)
# HACK
# with self.assertQueryCount(user_sales_manager=6930): # crm 6863 - com 6925
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)

# teams assign
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)])
Expand Down
5 changes: 3 additions & 2 deletions addons/payment/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from odoo.fields import Command

from odoo.addons.payment.tests.utils import PaymentTestUtils
from odoo.tests import new_test_pass

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -38,13 +39,13 @@ def _get_payment_method_information(self):
cls.internal_user = cls.env['res.users'].create({
'name': 'Internal User (Test)',
'login': 'internal',
'password': 'internal',
'password': new_test_pass(cls.env, 'internal'),
'groups_id': [Command.link(cls.group_user.id)]
})
cls.portal_user = cls.env['res.users'].create({
'name': 'Portal User (Test)',
'login': 'payment_portal',
'password': 'payment_portal',
'password': new_test_pass(cls.env, 'payment_portal'),
'groups_id': [Command.link(cls.group_portal.id)]
})
cls.public_user = cls.env.ref('base.public_user')
Expand Down
6 changes: 3 additions & 3 deletions addons/payment/tests/multicompany_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from odoo.fields import Command

from odoo.addons.payment.tests.common import PaymentCommon
from odoo.addons.payment.tests.common import new_test_pass, PaymentCommon

_logger = logging.getLogger(__name__)

Expand All @@ -22,15 +22,15 @@ def setUpClass(cls, chart_template_ref=None):
cls.user_company_b = cls.env['res.users'].create({
'name': f"{cls.company_b.name} User (TEST)",
'login': 'user_company_b',
'password': 'user_company_b',
'password': new_test_pass(cls.env, 'user_company_b'),
'company_id': cls.company_b.id,
'company_ids': [Command.set(cls.company_b.ids)],
'groups_id': [Command.link(cls.group_user.id)],
})
cls.user_multi_company = cls.env['res.users'].create({
'name': "Multi Company User (TEST)",
'login': 'user_multi_company',
'password': 'user_multi_company',
'password': new_test_pass(cls.env, 'user_multi_company'),
'company_id': cls.company_a.id,
'company_ids': [Command.set([cls.company_a.id, cls.company_b.id])],
'groups_id': [Command.link(cls.group_user.id)],
Expand Down
30 changes: 15 additions & 15 deletions addons/payment/tests/test_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ def test_10_direct_checkout_public(self):
self._test_flow('direct')

def test_11_direct_checkout_portal(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.user = self.portal_user
self.partner = self.portal_partner
self._test_flow('direct')

def test_12_direct_checkout_internal(self):
self.authenticate(self.internal_user.login, self.internal_user.login)
self.authenticate(self.internal_user.login)
self.user = self.internal_user
self.partner = self.internal_partner
self._test_flow('direct')
Expand All @@ -120,13 +120,13 @@ def test_20_redirect_checkout_public(self):
self._test_flow('redirect')

def test_21_redirect_checkout_portal(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.user = self.portal_user
self.partner = self.portal_partner
self._test_flow('redirect')

def test_22_redirect_checkout_internal(self):
self.authenticate(self.internal_user.login, self.internal_user.login)
self.authenticate(self.internal_user.login)
self.user = self.internal_user
self.partner = self.internal_partner
self._test_flow('redirect')
Expand All @@ -137,13 +137,13 @@ def test_22_redirect_checkout_internal(self):
# NOTE: not tested as public user because a public user cannot save payment details

def test_31_tokenize_portal(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.partner = self.portal_partner
self.user = self.portal_user
self._test_flow('token')

def test_32_tokenize_internal(self):
self.authenticate(self.internal_user.login, self.internal_user.login)
self.authenticate(self.internal_user.login)
self.partner = self.internal_partner
self.user = self.internal_user
self._test_flow('token')
Expand Down Expand Up @@ -202,22 +202,22 @@ def _test_validation(self, flow):
self.assertEqual(processing_values['reference'], expected_reference)

def test_51_validation_direct_portal(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.partner = self.portal_partner
self._test_validation(flow='direct')

def test_52_validation_direct_internal(self):
self.authenticate(self.internal_user.login, self.internal_user.login)
self.authenticate(self.internal_user.login)
self.partner = self.internal_partner
self._test_validation(flow='direct')

def test_61_validation_redirect_portal(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.partner = self.portal_partner
self._test_validation(flow='direct')

def test_62_validation_redirect_internal(self):
self.authenticate(self.internal_user.login, self.internal_user.login)
self.authenticate(self.internal_user.login)
self.partner = self.internal_partner
self._test_validation(flow='direct')

Expand All @@ -233,7 +233,7 @@ def test_pay_redirect_if_no_partner_exist(self):
self.assertTrue(response.url.startswith(self._build_url('/web/login?redirect=')))

# Pay without a partner specified (but logged) --> pay with the partner of current user.
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
tx_context = self.get_tx_checkout_context(**route_values)
self.assertEqual(tx_context['partner_id'], self.portal_partner.id)

Expand All @@ -247,7 +247,7 @@ def test_pay_no_token(self):
self.assertTrue(response.url.startswith(self._build_url('/web/login?redirect=')))

# Pay without a partner specified (but logged) --> pay with the partner of current user.
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
tx_context = self.get_tx_checkout_context(**route_values)
self.assertEqual(tx_context['partner_id'], self.portal_partner.id)

Expand Down Expand Up @@ -337,7 +337,7 @@ def test_transaction_wrong_token(self):

@mute_logger('odoo.addons.payment.models.payment_transaction')
def test_direct_payment_triggers_no_payment_request(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.partner = self.portal_partner
self.user = self.portal_user
with patch(
Expand All @@ -351,7 +351,7 @@ def test_direct_payment_triggers_no_payment_request(self):

@mute_logger('odoo.addons.payment.models.payment_transaction')
def test_payment_with_redirect_triggers_no_payment_request(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.partner = self.portal_partner
self.user = self.portal_user
with patch(
Expand All @@ -365,7 +365,7 @@ def test_payment_with_redirect_triggers_no_payment_request(self):

@mute_logger('odoo.addons.payment.models.payment_transaction')
def test_payment_by_token_triggers_exactly_one_payment_request(self):
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)
self.partner = self.portal_partner
self.user = self.portal_user
with patch(
Expand Down
4 changes: 2 additions & 2 deletions addons/payment/tests/test_multicompany_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_pay_logged_in_another_company(self):
route_values = self._prepare_pay_values(partner=self.user_company_b.partner_id)

# Log in as user from Company A
self.authenticate(self.user_company_a.login, self.user_company_a.login)
self.authenticate(self.user_company_a.login)

# Pay in company B
route_values['company_id'] = self.company_b.id
Expand Down Expand Up @@ -80,7 +80,7 @@ def test_archive_token_logged_in_another_company(self):
self.portal_user.write({'company_ids': [company_b.id], 'company_id': company_b.id})

# Log in as portal user
self.authenticate(self.portal_user.login, self.portal_user.login)
self.authenticate(self.portal_user.login)

# Archive token in company A
url = self._build_url('/payment/archive_token')
Expand Down
2 changes: 1 addition & 1 deletion addons/sale_stock/tests/test_sale_stock_access_rights.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_SO_and_DO_portal_acess(self):
so_url = '/my/orders/%s' % so.id
picking_url = '/my/picking/pdf/%s' % picking.id

self.authenticate(login, login)
self.authenticate(login)

if not login:
so._portal_ensure_token()
Expand Down
10 changes: 10 additions & 0 deletions odoo/addons/base/models/res_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,16 @@ def init(self):
for uid, pw in cr.fetchall():
Users.browse(uid).password = pw

@api.model
def _new_test_pass(self, login=''):
""" Helper function to create a test password for a given login.
Must return the same password each time it is called for the same login;
not cryptographically secure; for testing only."""
Params = self.env['ir.config_parameter'].sudo()
minlength = int(Params.get_param('auth_password_policy.minlength', default=8))
password = login + 'x' * (minlength - len(login))
return password

def _set_password(self):
ctx = self._crypt_context()
hash_password = ctx.hash if hasattr(ctx, 'hash') else ctx.encrypt
Expand Down
13 changes: 6 additions & 7 deletions odoo/addons/base/tests/test_xmlrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from odoo.http import _request_stack

import odoo.tools
from odoo.tests import common
from odoo.tests import common, new_test_pass, new_test_user
from odoo.service import common as auth, model
from odoo.tools import DotDict

Expand Down Expand Up @@ -111,10 +111,9 @@ class TestAPIKeys(common.HttpCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls._user = cls.env['res.users'].create({
cls._user = new_test_user(cls.env, **{
'name': "Bylan",
'login': 'byl',
'password': 'ananananan',
'tz': 'Australia/Eucla',
})

Expand All @@ -134,11 +133,11 @@ def setUp(self):
self.addCleanup(_request_stack.pop)

def test_trivial(self):
uid = auth.dispatch('authenticate', [self.env.cr.dbname, 'byl', 'ananananan', {}])
uid = auth.dispatch('authenticate', [self.env.cr.dbname, 'byl', new_test_pass(self.env, 'byl'), {}])
self.assertEqual(uid, self._user.id)

ctx = model.dispatch('execute_kw', [
self.env.cr.dbname, uid, 'ananananan',
self.env.cr.dbname, uid, new_test_pass(self.env, 'byl'),
'res.users', 'context_get', []
])
self.assertEqual(ctx['tz'], 'Australia/Eucla')
Expand All @@ -160,7 +159,7 @@ def test_key(self):
}).make_key()
k = r['context']['default_key']

uid = auth.dispatch('authenticate', [self.env.cr.dbname, 'byl', 'ananananan', {}])
uid = auth.dispatch('authenticate', [self.env.cr.dbname, 'byl', new_test_pass(self.env, 'byl'), {}])
self.assertEqual(uid, self._user.id)

uid = auth.dispatch('authenticate', [self.env.cr.dbname, 'byl', k, {}])
Expand Down Expand Up @@ -204,7 +203,7 @@ def test_disabled(self):

with self.assertRaises(AccessDenied):
model.dispatch('execute_kw', [
self.env.cr.dbname, self._user.id, 'ananananan',
self.env.cr.dbname, self._user.id, new_test_pass(self.env, 'byl'),
'res.users', 'context_get', []
])

Expand Down
21 changes: 18 additions & 3 deletions odoo/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ def register(func):
DB = get_db_name()


def new_test_pass(env, login=''):
""" Helper function to create a test password for a given login.
Must return the same password each time it is called for the same login;
not cryptographically secure; for testing only."""

# Handle users hardcoded into demo data
if login in ('admin', 'demo', 'portal'):
return login

Users = env['res.users']
return Users._new_test_pass(login)


def new_test_user(env, login='', groups='base.group_user', context=None, **kwargs):
""" Helper function to create a new test user. It allows to quickly create
users given its login and groups (being a comma separated list of xml ids).
Expand Down Expand Up @@ -140,7 +153,7 @@ def new_test_user(env, login='', groups='base.group_user', context=None, **kwarg
create_values['name'] = '%s (%s)' % (login, groups)
# automatically give a password equal to login
if not create_values.get('password'):
create_values['password'] = login + 'x' * (8 - len(login))
create_values['password'] = new_test_pass(env, login)
# generate email if not given as most test require an email
if 'email' not in create_values:
if single_email_re.match(login):
Expand Down Expand Up @@ -1626,7 +1639,7 @@ def logout(self, keep_db=True):
self.session.logout(keep_db=True)
odoo.http.root.session_store.save(self.session)

def authenticate(self, user, password):
def authenticate(self, user, password=None):
db = get_db_name()
if getattr(self, 'session', None):
odoo.http.root.session_store.delete(self.session)
Expand All @@ -1640,6 +1653,8 @@ def authenticate(self, user, password):
# than this transaction.
self.cr.flush()
self.cr.clear()
if not password:
password = new_test_pass(self.env, user)
uid = self.registry['res.users'].authenticate(db, user, password, {'interactive': False})
env = api.Environment(self.cr, uid, {})
session.uid = uid
Expand Down Expand Up @@ -1691,7 +1706,7 @@ def browser_js(self, url_path, code, ready='', login=None, timeout=60, cookies=N
self.start_browser()

try:
self.authenticate(login, login)
self.authenticate(login)
# Flush and clear the current transaction. This is useful in case
# we make requests to the server, as these requests are made with
# test cursors, which uses different caches than this transaction.
Expand Down

0 comments on commit 359a790

Please sign in to comment.