98 lines
4.2 KiB
Python
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)
|