feat(fusion_login_audit): standalone views + menus
List, form, and search views for fusion.login.audit, plus a "Login Events" full-history action and a "Failed Logins (24h)" pre-filtered action. Both surface under Settings -> Technical -> Login Audit (menu items gated by base.group_system). Views are no-create / no-edit / no-delete to enforce append-only at the UI layer too. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,9 @@ bursts. Daily retention cron honours a configurable horizon.
|
|||||||
'data': [
|
'data': [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'security/security.xml',
|
'security/security.xml',
|
||||||
|
'views/fusion_login_audit_views.xml',
|
||||||
'views/res_users_views.xml',
|
'views/res_users_views.xml',
|
||||||
|
'views/menus.xml',
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': False,
|
'application': False,
|
||||||
|
|||||||
118
fusion_login_audit/views/fusion_login_audit_views.xml
Normal file
118
fusion_login_audit/views/fusion_login_audit_views.xml
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<!-- List -->
|
||||||
|
<record id="view_fusion_login_audit_list" model="ir.ui.view">
|
||||||
|
<field name="name">fusion.login.audit.list</field>
|
||||||
|
<field name="model">fusion.login.audit</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list create="false" edit="false" delete="false"
|
||||||
|
default_order="event_time desc"
|
||||||
|
decoration-success="result=='success'"
|
||||||
|
decoration-danger="result=='failure'">
|
||||||
|
<field name="event_time"/>
|
||||||
|
<field name="user_id"/>
|
||||||
|
<field name="attempted_login"/>
|
||||||
|
<field name="result" widget="badge"/>
|
||||||
|
<field name="failure_reason"/>
|
||||||
|
<field name="ip_address"/>
|
||||||
|
<field name="country_code"/>
|
||||||
|
<field name="city"/>
|
||||||
|
<field name="browser"/>
|
||||||
|
<field name="device_type"/>
|
||||||
|
<field name="database" optional="hide"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Form (readonly) -->
|
||||||
|
<record id="view_fusion_login_audit_form" model="ir.ui.view">
|
||||||
|
<field name="name">fusion.login.audit.form</field>
|
||||||
|
<field name="model">fusion.login.audit</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form create="false" edit="false" delete="false">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<group string="Event">
|
||||||
|
<field name="event_time" readonly="1"/>
|
||||||
|
<field name="result" readonly="1" widget="badge"/>
|
||||||
|
<field name="failure_reason" readonly="1"/>
|
||||||
|
<field name="user_id" readonly="1"/>
|
||||||
|
<field name="attempted_login" readonly="1"/>
|
||||||
|
<field name="database" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<group string="Source">
|
||||||
|
<field name="ip_address" readonly="1"/>
|
||||||
|
<field name="ip_hostname" readonly="1"/>
|
||||||
|
<field name="country_code" readonly="1"/>
|
||||||
|
<field name="country_name" readonly="1"/>
|
||||||
|
<field name="geo_state" readonly="1"/>
|
||||||
|
<field name="city" readonly="1"/>
|
||||||
|
<field name="geo_lookup_state" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group string="Client">
|
||||||
|
<field name="device_type" readonly="1"/>
|
||||||
|
<field name="browser" readonly="1"/>
|
||||||
|
<field name="os" readonly="1"/>
|
||||||
|
<field name="user_agent_raw" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Search -->
|
||||||
|
<record id="view_fusion_login_audit_search" model="ir.ui.view">
|
||||||
|
<field name="name">fusion.login.audit.search</field>
|
||||||
|
<field name="model">fusion.login.audit</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search>
|
||||||
|
<field name="attempted_login"/>
|
||||||
|
<field name="user_id"/>
|
||||||
|
<field name="ip_address"/>
|
||||||
|
<field name="country_code"/>
|
||||||
|
<filter name="filter_success" string="Successes"
|
||||||
|
domain="[('result','=','success')]"/>
|
||||||
|
<filter name="filter_failure" string="Failures"
|
||||||
|
domain="[('result','=','failure')]"/>
|
||||||
|
<separator/>
|
||||||
|
<filter name="filter_24h" string="Last 24 hours"
|
||||||
|
domain="[('event_time','>=', (context_today() - relativedelta(days=1)).strftime('%Y-%m-%d 00:00:00'))]"/>
|
||||||
|
<filter name="filter_7d" string="Last 7 days"
|
||||||
|
domain="[('event_time','>=', (context_today() - relativedelta(days=7)).strftime('%Y-%m-%d 00:00:00'))]"/>
|
||||||
|
<filter name="filter_30d" string="Last 30 days"
|
||||||
|
domain="[('event_time','>=', (context_today() - relativedelta(days=30)).strftime('%Y-%m-%d 00:00:00'))]"/>
|
||||||
|
<separator/>
|
||||||
|
<filter name="filter_unknown_user" string="Unknown users"
|
||||||
|
domain="[('user_id','=',False)]"/>
|
||||||
|
<group>
|
||||||
|
<filter name="group_user" string="User"
|
||||||
|
context="{'group_by': 'user_id'}"/>
|
||||||
|
<filter name="group_country" string="Country"
|
||||||
|
context="{'group_by': 'country_code'}"/>
|
||||||
|
<filter name="group_ip" string="IP"
|
||||||
|
context="{'group_by': 'ip_address'}"/>
|
||||||
|
</group>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Window actions -->
|
||||||
|
<record id="action_fusion_login_audit_all" model="ir.actions.act_window">
|
||||||
|
<field name="name">Login Events</field>
|
||||||
|
<field name="res_model">fusion.login.audit</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="search_view_id" ref="view_fusion_login_audit_search"/>
|
||||||
|
<field name="context">{}</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_fusion_login_audit_failures_24h" model="ir.actions.act_window">
|
||||||
|
<field name="name">Failed Logins (24h)</field>
|
||||||
|
<field name="res_model">fusion.login.audit</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="search_view_id" ref="view_fusion_login_audit_search"/>
|
||||||
|
<field name="context">{'search_default_filter_failure': 1, 'search_default_filter_24h': 1}</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
24
fusion_login_audit/views/menus.xml
Normal file
24
fusion_login_audit/views/menus.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<menuitem id="menu_fusion_login_audit_root"
|
||||||
|
name="Login Audit"
|
||||||
|
parent="base.menu_administration"
|
||||||
|
groups="base.group_system"
|
||||||
|
sequence="100"/>
|
||||||
|
|
||||||
|
<menuitem id="menu_fusion_login_audit_all"
|
||||||
|
name="Login Events"
|
||||||
|
parent="menu_fusion_login_audit_root"
|
||||||
|
action="action_fusion_login_audit_all"
|
||||||
|
groups="base.group_system"
|
||||||
|
sequence="10"/>
|
||||||
|
|
||||||
|
<menuitem id="menu_fusion_login_audit_failures"
|
||||||
|
name="Failed Logins (24h)"
|
||||||
|
parent="menu_fusion_login_audit_root"
|
||||||
|
action="action_fusion_login_audit_failures_24h"
|
||||||
|
groups="base.group_system"
|
||||||
|
sequence="20"/>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user