- All 16 columns per spec (user, attempted_login, result, failure_reason, event_time, ip/geo fields, user_agent triple, device_type, database). - Check constraint binds failure_reason presence to result value. - Three composite indexes (user+time, login+time, geo_state+time) supporting the per-user, failure-burst, and geo cron queries. - Minimal admin-read ACL added so subsequent tests can verify writes. - 3 TransactionCase tests passing: model create, failure_reason nullable on success, geo_lookup_state='internal' accepted. Odoo 19 deprecation note: this implementation uses the declarative models.Constraint and models.Index attributes (Odoo 19 silently drops the legacy `_sql_constraints = [...]` list and `init()`/raw-SQL pattern with only a warning). Captured in CLAUDE.md rule #9. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo.tests.common import TransactionCase, tagged
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestFusionLoginAuditModel(TransactionCase):
|
|
|
|
def test_model_exists_and_creates(self):
|
|
"""Audit row can be created with all expected fields."""
|
|
Audit = self.env['fusion.login.audit'].sudo()
|
|
rec = Audit.create({
|
|
'attempted_login': 'demo@example.com',
|
|
'result': 'success',
|
|
'ip_address': '203.0.113.5',
|
|
'user_agent_raw': 'Mozilla/5.0 Test',
|
|
'browser': 'Test 1.0',
|
|
'os': 'TestOS',
|
|
'device_type': 'desktop',
|
|
'database': self.env.cr.dbname,
|
|
'geo_lookup_state': 'pending',
|
|
})
|
|
self.assertTrue(rec.id)
|
|
self.assertEqual(rec.result, 'success')
|
|
self.assertEqual(rec.geo_lookup_state, 'pending')
|
|
self.assertEqual(rec.database, self.env.cr.dbname)
|
|
self.assertTrue(rec.event_time) # default fires
|
|
|
|
def test_failure_reason_optional(self):
|
|
"""failure_reason is null on success rows."""
|
|
rec = self.env['fusion.login.audit'].sudo().create({
|
|
'attempted_login': 'demo@example.com',
|
|
'result': 'success',
|
|
})
|
|
self.assertFalse(rec.failure_reason)
|
|
|
|
def test_geo_state_internal_value(self):
|
|
"""`internal` is an accepted geo_lookup_state value (distinct from private_ip)."""
|
|
rec = self.env['fusion.login.audit'].sudo().create({
|
|
'attempted_login': 'demo@example.com',
|
|
'result': 'success',
|
|
'geo_lookup_state': 'internal',
|
|
})
|
|
self.assertEqual(rec.geo_lookup_state, 'internal')
|