Initial commit: CI Agent competitive-intelligence monitoring app
FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.db.base import ensure_aware_utc
|
||||
from app.models.email_code import EmailCode
|
||||
from app.models.enums import EmailCodePurpose
|
||||
|
||||
|
||||
class EmailCodeRepository:
|
||||
def __init__(self, db: AsyncSession) -> None:
|
||||
self.db = db
|
||||
|
||||
async def create(
|
||||
self, *, user_id: uuid.UUID, purpose: EmailCodePurpose, code_hash: str, expires_at: datetime
|
||||
) -> EmailCode:
|
||||
record = EmailCode(
|
||||
user_id=user_id, purpose=purpose, code_hash=code_hash, expires_at=expires_at
|
||||
)
|
||||
self.db.add(record)
|
||||
await self.db.flush()
|
||||
return record
|
||||
|
||||
async def get_latest_valid(
|
||||
self, user_id: uuid.UUID, purpose: EmailCodePurpose, code_hash: str
|
||||
) -> EmailCode | None:
|
||||
"""Most recent unused, unexpired code for this user/purpose whose
|
||||
hash matches. `invalidate_unused` is what actually guarantees only
|
||||
the most recently issued code can ever satisfy this - this method
|
||||
alone doesn't enforce that."""
|
||||
result = await self.db.execute(
|
||||
select(EmailCode)
|
||||
.where(
|
||||
EmailCode.user_id == user_id,
|
||||
EmailCode.purpose == purpose,
|
||||
EmailCode.code_hash == code_hash,
|
||||
EmailCode.used_at.is_(None),
|
||||
)
|
||||
.order_by(EmailCode.created_at.desc())
|
||||
)
|
||||
for record in result.scalars().all():
|
||||
if ensure_aware_utc(record.expires_at) > datetime.now(UTC):
|
||||
return record
|
||||
return None
|
||||
|
||||
async def mark_used(self, record: EmailCode) -> None:
|
||||
record.used_at = datetime.now(UTC)
|
||||
await self.db.flush()
|
||||
|
||||
async def invalidate_unused(self, user_id: uuid.UUID, purpose: EmailCodePurpose) -> None:
|
||||
"""Called right before issuing a fresh code - a resend must fully
|
||||
supersede every prior unused code for this purpose, not just make
|
||||
them harder to guess. Without this, an old code (e.g. still sitting
|
||||
in an old email) stays valid until it naturally expires, even after
|
||||
the user has explicitly asked for a new one."""
|
||||
await self.db.execute(
|
||||
update(EmailCode)
|
||||
.where(
|
||||
EmailCode.user_id == user_id,
|
||||
EmailCode.purpose == purpose,
|
||||
EmailCode.used_at.is_(None),
|
||||
)
|
||||
.values(used_at=datetime.now(UTC))
|
||||
)
|
||||
await self.db.flush()
|
||||
Reference in New Issue
Block a user