fix(agent): resolve missing imports — jose, auth config, AUTH_SECRET_KEY
- Added python-jose[cryptography] to requirements-agent.txt - Made sqlalchemy.orm.Session and TokenBlacklist imports lazy in jwt.py so decode_token works without pulling ORM models into agent image - Added src/core/auth/__init__.py, config.py, jwt.py to agent Dockerfile COPY - Added AUTH_SECRET_KEY env var to agent compose (reads from JWT_SECRET)
This commit is contained in:
@@ -37,3 +37,7 @@ psycopg>=3.1
|
||||
# Retry/utility
|
||||
tenacity>=8.0.0
|
||||
requests>=2.32.0
|
||||
|
||||
# JWT token validation (used by src.core.auth.jwt.decode_token)
|
||||
python-jose[cryptography]
|
||||
|
||||
|
||||
@@ -16,9 +16,7 @@ import hashlib
|
||||
import uuid
|
||||
|
||||
from jose import jwt
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ...models.auth import TokenBlacklist
|
||||
from ..logger import belief_scope
|
||||
from .config import auth_config
|
||||
|
||||
@@ -38,20 +36,18 @@ def create_access_token(data: dict, expires_delta: timedelta | None = None) -> s
|
||||
if expires_delta:
|
||||
expire = now + expires_delta
|
||||
else:
|
||||
expire = now + timedelta(
|
||||
minutes=auth_config.ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
)
|
||||
expire = now + timedelta(minutes=auth_config.ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
|
||||
to_encode.update({
|
||||
"exp": expire,
|
||||
"iat": now,
|
||||
"jti": str(uuid.uuid4()),
|
||||
"aud": auth_config.JWT_AUDIENCE,
|
||||
"iss": auth_config.JWT_ISSUER,
|
||||
})
|
||||
encoded_jwt = jwt.encode(
|
||||
to_encode, auth_config.SECRET_KEY, algorithm=auth_config.ALGORITHM
|
||||
to_encode.update(
|
||||
{
|
||||
"exp": expire,
|
||||
"iat": now,
|
||||
"jti": str(uuid.uuid4()),
|
||||
"aud": auth_config.JWT_AUDIENCE,
|
||||
"iss": auth_config.JWT_ISSUER,
|
||||
}
|
||||
)
|
||||
encoded_jwt = jwt.encode(to_encode, auth_config.SECRET_KEY, algorithm=auth_config.ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
|
||||
@@ -100,6 +96,7 @@ def decode_token(token: str) -> dict:
|
||||
def _hash_token(token: str) -> str:
|
||||
return hashlib.sha256(token.encode()).hexdigest()
|
||||
|
||||
|
||||
# #endregion Auth.Jwt._HashToken
|
||||
|
||||
|
||||
@@ -108,11 +105,15 @@ def _hash_token(token: str) -> str:
|
||||
# @PRE db is a valid SQLAlchemy session.
|
||||
# @POST Expired blacklist rows are removed.
|
||||
# @SIDE_EFFECT Mutates token_blacklist table.
|
||||
def _prune_blacklist(db: Session) -> None:
|
||||
def _prune_blacklist(db: "Session") -> None:
|
||||
from sqlalchemy.orm import Session # noqa: F811
|
||||
from ...models.auth import TokenBlacklist
|
||||
|
||||
now = datetime.now(UTC)
|
||||
db.query(TokenBlacklist).filter(TokenBlacklist.expires_at < now).delete()
|
||||
db.commit()
|
||||
|
||||
|
||||
# #endregion Auth.Jwt._PruneBlacklist
|
||||
|
||||
|
||||
@@ -125,7 +126,10 @@ def _prune_blacklist(db: Session) -> None:
|
||||
# @RELATION DEPENDS_ON -> [TokenBlacklist]
|
||||
# @RELATION CALLS -> [Auth.Jwt._HashToken]
|
||||
# @TEST_EDGE: already_expired -> skips blacklisting
|
||||
def blacklist_token(token: str, db: Session) -> None:
|
||||
def blacklist_token(token: str, db: "Session") -> None:
|
||||
from sqlalchemy.orm import Session # noqa: F811
|
||||
from ...models.auth import TokenBlacklist
|
||||
|
||||
with belief_scope("blacklist_token"):
|
||||
_prune_blacklist(db)
|
||||
try:
|
||||
@@ -165,7 +169,10 @@ def blacklist_token(token: str, db: Session) -> None:
|
||||
# @PRE db is a valid SQLAlchemy session.
|
||||
# @POST Returns True if token is blacklisted, False otherwise.
|
||||
# @RELATION DEPENDS_ON -> [TokenBlacklist]
|
||||
def is_token_blacklisted(token: str, db: Session) -> bool:
|
||||
def is_token_blacklisted(token: str, db: "Session") -> bool:
|
||||
from sqlalchemy.orm import Session # noqa: F811
|
||||
from ...models.auth import TokenBlacklist
|
||||
|
||||
with belief_scope("is_token_blacklisted"):
|
||||
try:
|
||||
payload = decode_token(token)
|
||||
|
||||
2
build.sh
2
build.sh
@@ -307,6 +307,7 @@ services:
|
||||
LLM_MODEL: \${LLM_MODEL:-gpt-4o}
|
||||
FASTAPI_URL: http://backend:8000
|
||||
JWT_SECRET: \${JWT_SECRET:-super-secret-key}
|
||||
AUTH_SECRET_KEY: \${JWT_SECRET:-super-secret-key}
|
||||
SERVICE_JWT: \${SERVICE_JWT:-agent-service-secret}
|
||||
DATABASE_URL: postgresql+psycopg2://\${POSTGRES_USER:-postgres}:\${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD}@\${POSTGRES_HOST:?Set POSTGRES_HOST}:\${POSTGRES_PORT:-5432}/\${POSTGRES_DB:-ss_tools}
|
||||
GRADIO_SERVER_PORT: 7860
|
||||
@@ -611,6 +612,7 @@ services:
|
||||
LLM_MODEL: \${LLM_MODEL:-gpt-4o}
|
||||
FASTAPI_URL: http://backend:8000
|
||||
JWT_SECRET: \${JWT_SECRET:-super-secret-key}
|
||||
AUTH_SECRET_KEY: \${JWT_SECRET:-super-secret-key}
|
||||
SERVICE_JWT: \${SERVICE_JWT:-agent-service-secret}
|
||||
DATABASE_URL: postgresql+psycopg2://\${POSTGRES_USER:-postgres}:\${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD}@\${POSTGRES_HOST:?Set POSTGRES_HOST}:\${POSTGRES_PORT:-5432}/\${POSTGRES_DB:-ss_tools}
|
||||
GRADIO_SERVER_PORT: 7860
|
||||
|
||||
@@ -104,6 +104,7 @@ services:
|
||||
LLM_MODEL: ${LLM_MODEL:-gpt-4o}
|
||||
FASTAPI_URL: http://backend:8000
|
||||
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET must be set — crash-early, no default fallback}
|
||||
AUTH_SECRET_KEY: ${JWT_SECRET:?JWT_SECRET must be set — crash-early, no default fallback}
|
||||
SERVICE_JWT: ${SERVICE_JWT:-agent-service-secret}
|
||||
DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:?Set POSTGRES_HOST in .env.enterprise-clean}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools}
|
||||
GRADIO_SERVER_PORT: 7860
|
||||
|
||||
@@ -60,6 +60,7 @@ services:
|
||||
LLM_MODEL: ${LLM_MODEL:-gpt-4o}
|
||||
FASTAPI_URL: http://backend:8000
|
||||
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET must be set — crash-early, no default fallback}
|
||||
AUTH_SECRET_KEY: ${JWT_SECRET:?JWT_SECRET must be set — crash-early, no default fallback}
|
||||
SERVICE_JWT: ${SERVICE_JWT:-agent-service-secret}
|
||||
DATABASE_URL: postgresql+psycopg2://postgres:postgres@db:5432/ss_tools
|
||||
GRADIO_SERVER_PORT: 7860
|
||||
|
||||
@@ -45,6 +45,9 @@ COPY backend/src/core/__init__.py /app/backend/src/core/__init__.py
|
||||
COPY backend/src/core/cot_logger.py /app/backend/src/core/cot_logger.py
|
||||
COPY backend/src/core/logger.py /app/backend/src/core/logger.py
|
||||
COPY backend/src/core/ws_log_handler.py /app/backend/src/core/ws_log_handler.py
|
||||
COPY backend/src/core/auth/__init__.py /app/backend/src/core/auth/__init__.py
|
||||
COPY backend/src/core/auth/config.py /app/backend/src/core/auth/config.py
|
||||
COPY backend/src/core/auth/jwt.py /app/backend/src/core/auth/jwt.py
|
||||
COPY backend/src/agent/ /app/backend/src/agent/
|
||||
|
||||
# Gradio server
|
||||
|
||||
Reference in New Issue
Block a user