11"""Domain phishing check router module."""
22
3- import socket
43import json
5- import os
4+ import socket
65from datetime import datetime , timedelta
7- from typing import Dict , List , Optional , Any , Union
86from pathlib import Path
7+ from typing import Any , Dict , List , Optional , Union
98
109import dnstwist
11- from fastapi import APIRouter , Depends , HTTPException , Request , Query , Header
12- from pydantic import BaseModel , Field , validator , EmailStr
10+ from fastapi import APIRouter , HTTPException , Query , Request
11+ from google .cloud import datastore
12+ from pydantic import BaseModel , EmailStr , Field , validator
1313from redis import Redis
1414
15- from config .settings import REDIS_HOST , REDIS_PORT , REDIS_DB
15+ from config .settings import REDIS_DB , REDIS_HOST , REDIS_PORT
1616from models .responses import BaseResponse
17- from utils .validation import validate_email_with_tld , validate_variables
18- from utils .token import confirm_token
19- from google .cloud import datastore
2017from utils .custom_limiter import custom_rate_limiter
18+ from utils .token import confirm_token
2119
2220router = APIRouter ()
2321
3735
3836
3937def validate_file_content (file_path : Path , min_lines : int = 1 ) -> None :
38+ """Validate the content of a file to ensure it has sufficient lines."""
4039 if not file_path .exists ():
4140 raise FileNotFoundError (f"File not found: { file_path } " )
4241 with open (file_path , "r" ) as f :
@@ -55,10 +54,13 @@ def validate_file_content(file_path: Path, min_lines: int = 1) -> None:
5554
5655
5756class DomainPhishingRequest (BaseModel ):
57+ """Request model for domain phishing check."""
58+
5859 domain : str = Field (..., description = "Domain to check for phishing variants" )
5960
6061 @validator ("domain" )
6162 def validate_domain (cls , v : str ) -> str :
63+ """Validate the domain format and length."""
6264 if not v or not isinstance (v , str ):
6365 raise ValueError ("Domain must be a non-empty string" )
6466 if len (v ) > 255 :
@@ -69,13 +71,17 @@ def validate_domain(cls, v: str) -> str:
6971
7072
7173class DomainPhishingSummaryResponse (BaseResponse ):
74+ """Summary response model for domain phishing check."""
75+
7276 total_scanned : int
7377 total_live : int = 0
7478 unique_fuzzers : int = 0
7579 last_checked : Optional [str ] = None
7680
7781
7882class DomainPhishingResponse (BaseResponse ):
83+ """Detailed response model for domain phishing check."""
84+
7985 total_scanned : int
8086 total_live : int = 0
8187 unique_fuzzers : int = 0
@@ -85,6 +91,7 @@ class DomainPhishingResponse(BaseResponse):
8591
8692
8793def is_domain_live (domain : str ) -> bool :
94+ """Check if a domain is live by resolving its IP address."""
8895 try :
8996 socket .gethostbyname (domain )
9097 return True
@@ -93,6 +100,7 @@ def is_domain_live(domain: str) -> bool:
93100
94101
95102def get_cached_result (domain : str ) -> Optional [Dict ]:
103+ """Retrieve cached phishing check results from Redis."""
96104 cache_key = f"phishing_check:{ domain } "
97105 cached_data = redis_client .get (cache_key )
98106 if cached_data :
@@ -104,13 +112,15 @@ def get_cached_result(domain: str) -> Optional[Dict]:
104112
105113
106114def cache_result (domain : str , result : Dict , expiry_hours : int = 24 ) -> None :
115+ """Cache phishing check results in Redis."""
107116 cache_key = f"phishing_check:{ domain } "
108117 if isinstance (result .get ("last_checked" ), datetime ):
109118 result ["last_checked" ] = result ["last_checked" ].isoformat ()
110119 redis_client .setex (cache_key , timedelta (hours = expiry_hours ), json .dumps (result ))
111120
112121
113122async def verify_user_access (email : str , token : str ) -> bool :
123+ """Verify user access based on email and token."""
114124 if not email or not token :
115125 return False
116126 try :
0 commit comments