address backend security and test suggestions
This commit is contained in:
@@ -145,6 +145,20 @@ def _get_domain_selectors_from_db(db: Session, domain_name: str) -> List[str]:
|
||||
return []
|
||||
|
||||
|
||||
def _get_domain_selectors_map_from_db(db: Session, domain_names: List[str]) -> Dict[str, List[str]]:
|
||||
"""Return manually configured DKIM selectors for all requested domains."""
|
||||
if not domain_names:
|
||||
return {}
|
||||
|
||||
rows = db.query(Domain.name, Domain.dkim_selectors).filter(Domain.name.in_(domain_names)).all()
|
||||
selectors_by_domain: Dict[str, List[str]] = {}
|
||||
for name, selectors in rows:
|
||||
selectors_by_domain[name] = [
|
||||
selector.strip() for selector in (selectors or "").split(",") if selector.strip()
|
||||
]
|
||||
return selectors_by_domain
|
||||
|
||||
|
||||
@router.get("/summary", response_model=DomainSummaryResponse)
|
||||
async def get_domains_summary(db: Session = Depends(get_db)):
|
||||
"""
|
||||
@@ -161,9 +175,10 @@ async def get_domains_summary(db: Session = Depends(get_db)):
|
||||
|
||||
# Perform DNS checks concurrently for all domains
|
||||
provider = get_default_provider()
|
||||
manual_selectors_by_domain = _get_domain_selectors_map_from_db(db, domains)
|
||||
|
||||
async def _dns_for_domain(domain_name: str) -> DomainDNSResult:
|
||||
manual_selectors = _get_domain_selectors_from_db(db, domain_name)
|
||||
manual_selectors = manual_selectors_by_domain.get(domain_name, [])
|
||||
report_selectors = _get_selectors_from_reports(store, domain_name)
|
||||
combined = list(dict.fromkeys(manual_selectors + report_selectors))
|
||||
try:
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, Security, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
from pydantic import BaseModel, EmailStr
|
||||
|
||||
from app.core.security import api_key_header, require_admin_auth, security_bearer
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# Simple in-memory storage for setup status (for Milestone 1)
|
||||
@@ -33,6 +38,17 @@ class SystemConfigRequest(BaseModel):
|
||||
base_url: str
|
||||
|
||||
|
||||
async def require_setup_write_auth(
|
||||
request: Request,
|
||||
api_key: Optional[str] = Security(api_key_header),
|
||||
bearer: Optional[HTTPAuthorizationCredentials] = Security(security_bearer),
|
||||
) -> dict:
|
||||
"""Allow unauthenticated first-time setup writes, then require admin auth."""
|
||||
if not setup_status["is_setup_complete"]:
|
||||
return {"auth_type": "initial_setup"}
|
||||
return await require_admin_auth(request=request, api_key=api_key, bearer=bearer)
|
||||
|
||||
|
||||
@router.get("/status", response_model=SetupStatusResponse)
|
||||
async def get_setup_status():
|
||||
"""Get the current setup status"""
|
||||
@@ -43,7 +59,10 @@ async def get_setup_status():
|
||||
|
||||
|
||||
@router.post("/admin", status_code=201)
|
||||
async def setup_admin(request: AdminSetupRequest):
|
||||
async def setup_admin(
|
||||
request: AdminSetupRequest,
|
||||
_auth: dict = Depends(require_setup_write_auth),
|
||||
):
|
||||
"""
|
||||
Setup admin user during initial system configuration.
|
||||
For Milestone 1, this simply stores the admin email in memory.
|
||||
@@ -60,7 +79,10 @@ async def setup_admin(request: AdminSetupRequest):
|
||||
|
||||
|
||||
@router.post("/system", status_code=200)
|
||||
async def setup_system(request: SystemConfigRequest):
|
||||
async def setup_system(
|
||||
request: SystemConfigRequest,
|
||||
_auth: dict = Depends(require_setup_write_auth),
|
||||
):
|
||||
"""
|
||||
Setup system configuration.
|
||||
For Milestone 1, this simply stores the app name in memory.
|
||||
|
||||
Reference in New Issue
Block a user