changes
This commit is contained in:
@@ -303,6 +303,54 @@ class TestFusionLoginAuditModel(TransactionCase):
|
||||
self.assertGreaterEqual(user.x_fc_login_audit_count, 1)
|
||||
self.assertEqual(user.x_fc_last_login_ip, '198.51.100.42')
|
||||
|
||||
def test_last_login_fields_not_stored(self):
|
||||
"""Regression guard for the 2026-06-03 invitation-acceptance hang.
|
||||
|
||||
x_fc_last_successful_login / x_fc_last_login_ip MUST stay non-stored.
|
||||
When they were store=True (computed from the audit One2many), creating
|
||||
the success audit row through the independent registry cursor forced a
|
||||
write-back onto the very res_users row the request had already locked
|
||||
(auth_signup had just set the password) -> a self-deadlock Postgres
|
||||
cannot see (the holder shows 'idle in transaction'). Workers wedged for
|
||||
up to limit_time_real and odoo-westin became unresponsive whenever an
|
||||
invitation was accepted. Non-stored means audit-row creation never
|
||||
touches res_users, so the deadlock cannot form.
|
||||
"""
|
||||
fields_ = self.env['res.users']._fields
|
||||
self.assertFalse(
|
||||
fields_['x_fc_last_successful_login'].store,
|
||||
"x_fc_last_successful_login must be non-stored (see docstring)")
|
||||
self.assertFalse(
|
||||
fields_['x_fc_last_login_ip'].store,
|
||||
"x_fc_last_login_ip must be non-stored (see docstring)")
|
||||
|
||||
def test_audit_row_create_does_not_write_res_users(self):
|
||||
"""Creating a login-audit row must not write the linked res_users row.
|
||||
|
||||
This is the behavioural half of the deadlock guard: with the fields
|
||||
non-stored, inserting an audit row for a user leaves that user's
|
||||
write_date untouched (no recompute -> no res_users UPDATE -> nothing
|
||||
to contend with the request's own row lock).
|
||||
"""
|
||||
user = self.env['res.users'].sudo().create({
|
||||
'name': 'NoWriteback Tester',
|
||||
'login': 'nowriteback-tester@example.com',
|
||||
'password': 'nowriteback-tester-pw-1',
|
||||
})
|
||||
user.flush_recordset()
|
||||
before = user.write_date
|
||||
self.env['fusion.login.audit'].sudo().create({
|
||||
'user_id': user.id,
|
||||
'attempted_login': user.login,
|
||||
'result': 'success',
|
||||
'database': self.env.cr.dbname,
|
||||
'ip_address': '198.51.100.7',
|
||||
})
|
||||
user.invalidate_recordset()
|
||||
self.assertEqual(
|
||||
user.write_date, before,
|
||||
"Audit-row create must not write back to res_users")
|
||||
|
||||
def test_action_view_login_audit_returns_window_action(self):
|
||||
"""The smart-button action returns an act_window scoped to this user."""
|
||||
user = self.env['res.users'].sudo().create({
|
||||
|
||||
Reference in New Issue
Block a user