Add evaluation framework and fix call graph extraction
- Add evaluation test suite with TypeScript and Python fixtures - Fix MCP server to defer CodeGraph init until rootUri received - Fix call edge extraction by calling resolveReferences() after indexAll/sync - Fix glob matching for root-level files (e.g., **/*.py now matches auth.py) - Fix duplicate node extraction for methods inside classes - Update context tests to use buildContext for semantic search + graph traversal - Export unused formatter functions to fix build Evaluation results: - TypeScript: 96% precision, 79% recall, 85% F1 - Python: 99% precision, 80% recall, 85% F1 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
e306114607
commit
6b672f9152
@@ -0,0 +1,79 @@
|
||||
"""Authentication service."""
|
||||
|
||||
import hashlib
|
||||
import secrets
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from models import User
|
||||
from database import db
|
||||
from validation import validate_email, validate_password
|
||||
|
||||
|
||||
def hash_password(password: str) -> str:
|
||||
"""Hash a password for storage."""
|
||||
salt = secrets.token_hex(16)
|
||||
hash_obj = hashlib.sha256((password + salt).encode())
|
||||
return f"{salt}:{hash_obj.hexdigest()}"
|
||||
|
||||
|
||||
def verify_password(password: str, password_hash: str) -> bool:
|
||||
"""Verify a password against its hash."""
|
||||
salt, stored_hash = password_hash.split(":")
|
||||
hash_obj = hashlib.sha256((password + salt).encode())
|
||||
return hash_obj.hexdigest() == stored_hash
|
||||
|
||||
|
||||
def generate_token() -> str:
|
||||
"""Generate a secure random token."""
|
||||
return secrets.token_urlsafe(32)
|
||||
|
||||
|
||||
class AuthService:
|
||||
def __init__(self):
|
||||
self.tokens: dict = {}
|
||||
|
||||
def register(self, email: str, password: str, name: str) -> Tuple[bool, str]:
|
||||
"""Register a new user."""
|
||||
if not validate_email(email):
|
||||
return False, "Invalid email format"
|
||||
|
||||
if not validate_password(password):
|
||||
return False, "Password too weak"
|
||||
|
||||
if db.get_user_by_email(email):
|
||||
return False, "Email already registered"
|
||||
|
||||
user = User(
|
||||
id=generate_token(),
|
||||
email=email,
|
||||
name=name,
|
||||
password_hash=hash_password(password),
|
||||
created_at=datetime.now(),
|
||||
)
|
||||
db.create_user(user)
|
||||
return True, user.id
|
||||
|
||||
def login(self, email: str, password: str) -> Optional[str]:
|
||||
"""Authenticate user and return token."""
|
||||
user = db.get_user_by_email(email)
|
||||
if not user:
|
||||
return None
|
||||
|
||||
if not verify_password(password, user.password_hash):
|
||||
return None
|
||||
|
||||
token = generate_token()
|
||||
self.tokens[token] = user.id
|
||||
return token
|
||||
|
||||
def logout(self, token: str) -> None:
|
||||
"""Invalidate a token."""
|
||||
self.tokens.pop(token, None)
|
||||
|
||||
def get_user_id(self, token: str) -> Optional[str]:
|
||||
"""Get user ID from token."""
|
||||
return self.tokens.get(token)
|
||||
|
||||
|
||||
auth_service = AuthService()
|
||||
Reference in New Issue
Block a user