feat: SAC 0.7.2 security hardening (rate limit, JWT DB check, DOMPurify)
Path traversal fix in SPA fallback, admin-only host delete, login rate limit with 3 attempts and Telegram alert, JWT validated against active users in DB, and DOMPurify for agent report HTML. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ from app.models.notification_channel import NotificationChannel
|
||||
from app.models.notification_cooldown import NotificationCooldown
|
||||
from app.models.notification_policy import NotificationPolicy
|
||||
from app.models.problem import Problem, ProblemEvent
|
||||
from app.models.login_attempt import LoginAttempt
|
||||
from app.models.event_severity_override import EventSeverityOverride
|
||||
from app.models.user import User
|
||||
|
||||
@@ -19,4 +20,5 @@ __all__ = [
|
||||
"ProblemEvent",
|
||||
"User",
|
||||
"EventSeverityOverride",
|
||||
"LoginAttempt",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Boolean, DateTime, String, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.database import Base
|
||||
|
||||
|
||||
class LoginAttempt(Base):
|
||||
__tablename__ = "login_attempts"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
ip_address: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
|
||||
username: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||||
success: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
server_default=func.now(),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
Reference in New Issue
Block a user