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>
47 lines
1.7 KiB
XML
47 lines
1.7 KiB
XML
<?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>
|