Files
links/netscan/models.py
2026-03-21 16:41:14 +11:00

85 lines
3.0 KiB
Python

from django.db import models
from .fields import EncryptedCharField
class ScanProfile(models.Model):
INTERVAL_CHOICES = [
(1, 'Every 1 day'),
(3, 'Every 3 days'),
(7, 'Every 7 days'),
(30, 'Every 30 days'),
]
SEVERITY_CHOICES = [
('warning', 'Warning and above'),
('critical', 'Critical only'),
]
name = models.CharField(max_length=200)
enabled = models.BooleanField(default=True)
schedule_interval = models.IntegerField(choices=INTERVAL_CHOICES, default=7)
gateway_ip = models.GenericIPAddressField(help_text='e.g. 192.168.1.1')
public_ip = models.GenericIPAddressField(help_text='Your public/WAN IP address')
network_cidr = models.CharField(max_length=50, blank=True, help_text='e.g. 192.168.1.0/24')
auth_provider_host = models.CharField(max_length=255, blank=True, help_text='e.g. pass.junv.cc')
domains = models.JSONField(default=list, blank=True, help_text='List of public hostnames to check')
cameras = models.JSONField(default=list, blank=True, help_text='List of camera IPs to probe')
telegram_bot_token = EncryptedCharField(blank=True)
telegram_chat_id = EncryptedCharField(blank=True)
notify_on_severity = models.CharField(max_length=20, choices=SEVERITY_CHOICES, default='critical')
last_run_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class ScanRun(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('running', 'Running'),
('success', 'Success'),
('failed', 'Failed'),
]
profile = models.ForeignKey(ScanProfile, on_delete=models.CASCADE, related_name='runs')
started_at = models.DateTimeField(auto_now_add=True)
finished_at = models.DateTimeField(null=True, blank=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
summary = models.JSONField(default=dict)
triggered_by = models.CharField(max_length=20, default='manual')
class Meta:
ordering = ['-started_at']
def __str__(self):
return f'{self.profile.name} run #{self.pk} ({self.status})'
@property
def duration_seconds(self):
if self.finished_at and self.started_at:
return int((self.finished_at - self.started_at).total_seconds())
return None
class ScanFinding(models.Model):
SEVERITY_CHOICES = [
('ok', 'OK'),
('info', 'Info'),
('warning', 'Warning'),
('critical', 'Critical'),
]
run = models.ForeignKey(ScanRun, on_delete=models.CASCADE, related_name='findings')
check_name = models.CharField(max_length=100)
severity = models.CharField(max_length=20, choices=SEVERITY_CHOICES)
title = models.CharField(max_length=255)
detail = models.TextField()
raw = models.JSONField(default=dict)
class Meta:
ordering = ['severity', 'check_name']
def __str__(self):
return f'[{self.severity.upper()}] {self.title}'