mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 11:28:47 +02:00
Consistency sweep: enum members, keyword status codes, SimpleCookie
analytics.py filters by TransactionType.COMPRA instead of the string literal; budget.py uses keyword HTTPException args; the agent middleware parses cookies with stdlib SimpleCookie instead of a regex (ARCH-10); auth.py's lazy imports are hoisted — there was never an actual auth/db cycle (ARCH-20); transactions.py hoists or_/and_. Verified: dev container boots, agent auth paths return 401 for missing/garbage cookies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ from sqlmodel import Session, func, select
|
|||||||
|
|
||||||
from app.auth import get_current_user
|
from app.auth import get_current_user
|
||||||
from app.db import get_session
|
from app.db import get_session
|
||||||
from app.models.models import Category, Transaction
|
from app.models.models import Category, Transaction, TransactionType
|
||||||
from app.services.budget_projection import get_cycle_range
|
from app.services.budget_projection import get_cycle_range
|
||||||
from app.services.exchange_rate import get_converted_amount_expr
|
from app.services.exchange_rate import get_converted_amount_expr
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ def spending_by_category(
|
|||||||
func.sum(amount_crc).label("total"),
|
func.sum(amount_crc).label("total"),
|
||||||
func.count().label("count"),
|
func.count().label("count"),
|
||||||
)
|
)
|
||||||
.where(Transaction.transaction_type == "COMPRA")
|
.where(Transaction.transaction_type == TransactionType.COMPRA)
|
||||||
.group_by(Transaction.category_id)
|
.group_by(Transaction.category_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ def monthly_trend(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.where(
|
.where(
|
||||||
Transaction.transaction_type == "COMPRA",
|
Transaction.transaction_type == TransactionType.COMPRA,
|
||||||
Transaction.date >= start,
|
Transaction.date >= start,
|
||||||
Transaction.date < end,
|
Transaction.date < end,
|
||||||
)
|
)
|
||||||
@@ -171,7 +171,7 @@ def daily_spending(
|
|||||||
func.sum(amount_crc).label("total"),
|
func.sum(amount_crc).label("total"),
|
||||||
func.count().label("count"),
|
func.count().label("count"),
|
||||||
)
|
)
|
||||||
.where(Transaction.transaction_type == "COMPRA")
|
.where(Transaction.transaction_type == TransactionType.COMPRA)
|
||||||
.group_by(func.date(Transaction.date))
|
.group_by(func.date(Transaction.date))
|
||||||
.order_by(func.date(Transaction.date))
|
.order_by(func.date(Transaction.date))
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -248,9 +248,9 @@ def upsert_balance_override(
|
|||||||
_user: str = Depends(get_current_user),
|
_user: str = Depends(get_current_user),
|
||||||
):
|
):
|
||||||
if year < MIN_YEAR or year > MAX_YEAR:
|
if year < MIN_YEAR or year > MAX_YEAR:
|
||||||
raise HTTPException(400, f"Year must be between {MIN_YEAR} and {MAX_YEAR}")
|
raise HTTPException(status_code=400, detail=f"Year must be between {MIN_YEAR} and {MAX_YEAR}")
|
||||||
if year == FRESH_START_YEAR and month < FRESH_START_MONTH:
|
if year == FRESH_START_YEAR and month < FRESH_START_MONTH:
|
||||||
raise HTTPException(400, f"Cannot override before {FRESH_START_YEAR}-{FRESH_START_MONTH:02d}")
|
raise HTTPException(status_code=400, detail=f"Cannot override before {FRESH_START_YEAR}-{FRESH_START_MONTH:02d}")
|
||||||
|
|
||||||
existing = session.exec(
|
existing = session.exec(
|
||||||
select(BalanceOverride).where(
|
select(BalanceOverride).where(
|
||||||
@@ -288,6 +288,6 @@ def delete_balance_override(
|
|||||||
)
|
)
|
||||||
).first()
|
).first()
|
||||||
if not existing:
|
if not existing:
|
||||||
raise HTTPException(404, "No override found for this month")
|
raise HTTPException(status_code=404, detail="No override found for this month")
|
||||||
session.delete(existing)
|
session.delete(existing)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from sqlalchemy import and_, or_
|
||||||
from sqlmodel import Session, col, func, select
|
from sqlmodel import Session, col, func, select
|
||||||
|
|
||||||
from app.auth import get_current_user
|
from app.auth import get_current_user
|
||||||
@@ -73,7 +74,6 @@ def list_transactions(
|
|||||||
prev_y, prev_m = get_previous_cycle(cycle_year, cycle_month)
|
prev_y, prev_m = get_previous_cycle(cycle_year, cycle_month)
|
||||||
prev_start, prev_end = get_cycle_range(prev_y, prev_m)
|
prev_start, prev_end = get_cycle_range(prev_y, prev_m)
|
||||||
# Normal transactions in this cycle (not deferred) + deferred from previous cycle
|
# Normal transactions in this cycle (not deferred) + deferred from previous cycle
|
||||||
from sqlalchemy import or_, and_
|
|
||||||
query = query.where(
|
query = query.where(
|
||||||
or_(
|
or_(
|
||||||
and_(
|
and_(
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ from jose import JWTError, jwt
|
|||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
|
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
|
from app.db import get_session
|
||||||
|
from app.models.models import APIToken
|
||||||
from app.timeutil import utcnow
|
from app.timeutil import utcnow
|
||||||
|
|
||||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
|
||||||
@@ -91,9 +93,6 @@ def _validate_token(token: str) -> str:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# Fallback: check API token
|
# Fallback: check API token
|
||||||
from app.db import get_session
|
|
||||||
from app.models.models import APIToken
|
|
||||||
|
|
||||||
token_hash = hash_token(token)
|
token_hash = hash_token(token)
|
||||||
with next(get_session()) as session:
|
with next(get_session()) as session:
|
||||||
api_token = session.exec(
|
api_token = session.exec(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import re
|
|
||||||
import uuid
|
import uuid
|
||||||
|
from http.cookies import SimpleCookie
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
from agent_framework_ag_ui import add_agent_framework_fastapi_endpoint
|
from agent_framework_ag_ui import add_agent_framework_fastapi_endpoint
|
||||||
@@ -105,10 +105,10 @@ async def agent_auth_and_session(request: Request, call_next):
|
|||||||
if auth_header.lower().startswith("bearer "):
|
if auth_header.lower().startswith("bearer "):
|
||||||
token = auth_header.split(" ", 1)[1].strip()
|
token = auth_header.split(" ", 1)[1].strip()
|
||||||
else:
|
else:
|
||||||
cookie_header = request.headers.get("cookie", "")
|
cookies = SimpleCookie()
|
||||||
m = re.search(r"(?:^|;\s*)ws_token=([^;]+)", cookie_header)
|
cookies.load(request.headers.get("cookie", ""))
|
||||||
if m:
|
if "ws_token" in cookies:
|
||||||
token = m.group(1)
|
token = cookies["ws_token"].value
|
||||||
|
|
||||||
if not token:
|
if not token:
|
||||||
return Response(status_code=401, content="Missing auth")
|
return Response(status_code=401, content="Missing auth")
|
||||||
|
|||||||
Reference in New Issue
Block a user