153 lines
3.8 KiB
Python
153 lines
3.8 KiB
Python
"""
|
|
ⒸAngelaMos | 2025
|
|
Handles all Scan model database queries
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
from sqlalchemy.orm import (
|
|
Session,
|
|
joinedload,
|
|
)
|
|
|
|
from config import settings
|
|
from models.Scan import Scan
|
|
|
|
|
|
class ScanRepository:
|
|
"""
|
|
Repository for Scan database operations
|
|
"""
|
|
|
|
@staticmethod
|
|
def create_scan(db: Session, user_id: int, target_url: str, commit: bool = True) -> Scan:
|
|
"""
|
|
Create a new scan
|
|
|
|
Args:
|
|
db: Database session
|
|
user_id: User ID who initiated the scan
|
|
target_url: Target URL to scan
|
|
commit: Whether to commit the transaction
|
|
|
|
Returns:
|
|
Scan: Created scan instance
|
|
"""
|
|
scan = Scan(
|
|
user_id=user_id,
|
|
target_url=target_url,
|
|
scan_date=datetime.now(UTC),
|
|
)
|
|
db.add(scan)
|
|
if commit:
|
|
db.commit()
|
|
db.refresh(scan)
|
|
return scan
|
|
|
|
@staticmethod
|
|
def get_by_id(db: Session, scan_id: int) -> Scan | None:
|
|
"""
|
|
Get scan by ID with test results loaded
|
|
|
|
Args:
|
|
db: Database session
|
|
scan_id: Scan ID
|
|
|
|
Returns:
|
|
Scan | None: Scan instance or None if not found
|
|
"""
|
|
return (
|
|
db.query(Scan)
|
|
.options(joinedload(Scan.test_results))
|
|
.filter(Scan.id == scan_id)
|
|
.first()
|
|
)
|
|
|
|
@staticmethod
|
|
def get_by_user(
|
|
db: Session, user_id: int, skip: int = 0, limit: int | None = None
|
|
) -> list[Scan]:
|
|
"""
|
|
Get all scans for a user with pagination.
|
|
|
|
Args:
|
|
db: Database session
|
|
user_id: User ID
|
|
skip: Number of records to skip
|
|
limit: Maximum number of records to return (DEFAULT_PAGINATION_LIMIT)
|
|
|
|
Returns:
|
|
list[Scan]: List of scans with test results
|
|
"""
|
|
if limit is None:
|
|
limit = settings.DEFAULT_PAGINATION_LIMIT
|
|
|
|
return (
|
|
db.query(Scan)
|
|
.options(joinedload(Scan.test_results))
|
|
.filter(Scan.user_id == user_id)
|
|
.order_by(Scan.scan_date.desc())
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
@staticmethod
|
|
def get_recent(db: Session, limit: int | None = None) -> list[Scan]:
|
|
"""
|
|
Get most recent scans across all users.
|
|
|
|
Args:
|
|
db: Database session
|
|
limit: Maximum number of scans to return (DEFAULT_PAGINATION_LIMIT)
|
|
|
|
Returns:
|
|
list[Scan]: List of recent scans
|
|
"""
|
|
if limit is None:
|
|
limit = settings.DEFAULT_PAGINATION_LIMIT
|
|
|
|
return (
|
|
db.query(Scan)
|
|
.options(joinedload(Scan.test_results))
|
|
.order_by(Scan.scan_date.desc())
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
@staticmethod
|
|
def delete(db: Session, scan_id: int, commit: bool = True) -> bool:
|
|
"""
|
|
Delete a scan (cascades to test results).
|
|
|
|
Args:
|
|
db: Database session
|
|
scan_id: Scan ID to delete
|
|
commit: Whether to commit the transaction
|
|
|
|
Returns:
|
|
bool: True if deleted, False if not found
|
|
"""
|
|
scan = ScanRepository.get_by_id(db, scan_id)
|
|
if scan:
|
|
db.delete(scan)
|
|
if commit:
|
|
db.commit()
|
|
return True
|
|
return False
|
|
|
|
@staticmethod
|
|
def count_by_user(db: Session, user_id: int) -> int:
|
|
"""
|
|
Count total scans for a user.
|
|
|
|
Args:
|
|
db: Database session
|
|
user_id: User ID
|
|
|
|
Returns:
|
|
int: Total number of scans
|
|
"""
|
|
return db.query(Scan).filter(Scan.user_id == user_id).count()
|