feat(fusion_login_audit): failure-burst alert email + cooldown
Mail template + helpers (_fc_alert_*, _fc_recent_failure_count, _fc_send_failure_alert) wired into _check_credentials so that crossing the consecutive-failure threshold within the window queues exactly one mail.mail per attempted login per 60-minute cooldown. Master switch x_fc_login_audit_alert_enabled honoured. Recipients are members of base.group_system with a non-empty email and share=False; the __system__ superuser is excluded by Odoo''s default user filter. Tests (3 new, 22 total green): test_failure_burst_queues_one_email test_cooldown_suppresses_second_alert test_alert_disabled_master_switch setUp ensures base.user_admin has an email (fusion-dev''s admin user ships without one; the only user with an email is __system__, which is filtered out of standard res.users searches). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
46
fusion_login_audit/data/mail_template_data.xml
Normal file
46
fusion_login_audit/data/mail_template_data.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="mail_template_failure_burst" model="mail.template">
|
||||
<field name="name">Fusion Login Audit — Failure Burst Alert</field>
|
||||
<field name="model_id" ref="base.model_res_users"/>
|
||||
<field name="subject">[Login Audit] Failed login attempts for {{ ctx.get('attempted_login') }}</field>
|
||||
<field name="body_html" type="html">
|
||||
<div>
|
||||
<p>The login audit detected
|
||||
<strong t-out="ctx.get('failure_count')"/> failed login attempt(s)
|
||||
in the last <t t-out="ctx.get('window_min')"/> minute(s) for
|
||||
<strong t-out="ctx.get('attempted_login')"/>.</p>
|
||||
<p>Most recent attempts:</p>
|
||||
<table border="1" cellpadding="4" cellspacing="0"
|
||||
style="border-collapse: collapse; font-family: sans-serif; font-size: 12px;">
|
||||
<thead style="background: #f3f4f6;">
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>IP</th>
|
||||
<th>Country</th>
|
||||
<th>Browser</th>
|
||||
<th>OS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="ctx.get('rows', [])" t-as="row">
|
||||
<td t-out="row['event_time']"/>
|
||||
<td t-out="row['ip_address']"/>
|
||||
<td t-out="row.get('country_code') or ''"/>
|
||||
<td t-out="row.get('browser') or ''"/>
|
||||
<td t-out="row.get('os') or ''"/>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="color: #6b7280; font-size: 11px;">
|
||||
Sent by Fusion Login Audit. Tune the threshold and window in
|
||||
Settings → General Settings → Login Audit.
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user