bemade-addons/unifi_integration/models/udm_firewall.py
Benoît Vézina b2183d8601 fml unifi
2025-03-11 16:19:49 -04:00

98 lines
4.2 KiB
Python

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class UdmFirewallRule(models.Model):
"""Represents a firewall rule in the UniFi system
This model stores firewall rules that control network traffic. Each rule
specifies what traffic is allowed or blocked based on various criteria such
as source/destination addresses, ports, and protocols.
Rules are linked to a specific site and are automatically deleted when
the site is deleted (cascade).
"""
_name = 'udm.firewall.rule'
_description = 'UniFi Firewall Rule'
_order = 'sequence, id'
site_id = fields.Many2one('udm.site', string='Site', required=True,
ondelete='cascade',
help='Site this firewall rule belongs to')
name = fields.Char(string='Name', required=True,
help='Rule name')
description = fields.Text(string='Description',
help='Detailed description of the rule purpose')
enabled = fields.Boolean(string='Enabled', default=True,
help='Whether this rule is active')
sequence = fields.Integer(string='Sequence', default=10,
help='Order in which rules are evaluated')
action = fields.Selection([
('accept', 'Accept'),
('drop', 'Drop'),
('reject', 'Reject')
], string='Action', required=True, default='drop',
help='Action to take when rule matches')
protocol = fields.Selection([
('tcp', 'TCP'),
('udp', 'UDP'),
('icmp', 'ICMP'),
('all', 'All')
], string='Protocol', required=True, default='all',
help='Network protocol this rule applies to')
source = fields.Char(string='Source',
help='Source network or IP address in CIDR format')
destination = fields.Char(string='Destination',
help='Destination network or IP address in CIDR format')
src_address = fields.Char(string='Source Address',
help='Legacy field, use source instead')
dst_address = fields.Char(string='Destination Address',
help='Legacy field, use destination instead')
src_port = fields.Char(string='Source Port',
help='Source port number or range (e.g. 80 or 1024-2048)')
dst_port = fields.Char(string='Destination Port',
help='Destination port number or range (e.g. 80 or 1024-2048)')
raw_data = fields.Text(string='Raw Data',
help='Raw firewall rule data in JSON format')
# Computed fields
rule_summary = fields.Char(string='Rule Summary', compute='_compute_rule_summary')
@api.depends('action', 'protocol', 'src_address', 'dst_address', 'src_port', 'dst_port')
def _compute_rule_summary(self):
"""Compute a human-readable summary of the firewall rule
This method generates a concise description of the rule's action,
protocol, and source/destination addresses and ports. The summary
is used in list views and reports to quickly understand what the
rule does without viewing all details.
Example summaries:
- ACCEPT TCP from 192.168.1.0/24:80 to 10.0.0.0/8:443
- DROP ICMP from 172.16.0.0/16 to any
- REJECT UDP from any to 192.168.2.10:53
"""
for record in self:
parts = []
if record.action:
parts.append(record.action.upper())
if record.protocol:
parts.append(record.protocol.upper())
# Use new source/destination fields if available, fall back to legacy fields
src_addr = record.source or record.src_address or 'any'
dst_addr = record.destination or record.dst_address or 'any'
src = f"from {src_addr}"
if record.src_port:
src += f":{record.src_port}"
parts.append(src)
dst = f"to {dst_addr}"
if record.dst_port:
dst += f":{record.dst_port}"
parts.append(dst)
record.rule_summary = ' '.join(parts)