Files
aditya 9fe3196827 test: re-run all 7 simulations with improved pipeline
All sims re-run after pipeline fixes (better prompts, real syntax
validation, fenced-block extraction fix). Results: 7/7 PASS,
20 files total, all Python files pass compile() syntax check.

Includes run_all_sims.py runner script and rag-basic action config.
2026-03-13 11:56:24 +00:00

361 lines
11 KiB
Python

from flask import Flask, request, jsonify
from config import Config
from database import init_database
from models import db, User
from auth import (
generate_jwt_token,
token_required,
validate_email,
validate_username,
validate_password_strength
)
import traceback
app = Flask(__name__)
app.config.from_object(Config)
# Initialize database
init_database(app)
@app.errorhandler(404)
def not_found(error):
return jsonify({
'error': 'Not found',
'message': 'The requested resource was not found'
}), 404
@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return jsonify({
'error': 'Internal server error',
'message': 'An unexpected error occurred'
}), 500
@app.route('/health', methods=['GET'])
def health_check():
"""Health check endpoint."""
return jsonify({
'status': 'healthy',
'message': 'Application is running'
}), 200
@app.route('/api/register', methods=['POST'])
def register():
"""User registration endpoint."""
try:
data = request.get_json()
if not data:
return jsonify({
'error': 'Invalid input',
'message': 'JSON data is required'
}), 400
username = data.get('username', '').strip()
email = data.get('email', '').strip().lower()
password = data.get('password', '')
# Validate required fields
if not username or not email or not password:
return jsonify({
'error': 'Missing required fields',
'message': 'Username, email, and password are required'
}), 400
# Validate username format
if not validate_username(username):
return jsonify({
'error': 'Invalid username',
'message': 'Username must be 3-80 characters and contain only letters, numbers, and underscores'
}), 400
# Validate email format
if not validate_email(email):
return jsonify({
'error': 'Invalid email',
'message': 'Please provide a valid email address'
}), 400
# Validate password strength
is_valid, password_message = validate_password_strength(password)
if not is_valid:
return jsonify({
'error': 'Weak password',
'message': password_message
}), 400
# Check if user already exists
existing_user = User.query.filter(
(User.username == username) | (User.email == email)
).first()
if existing_user:
if existing_user.username == username:
return jsonify({
'error': 'Username taken',
'message': 'Username already exists'
}), 409
else:
return jsonify({
'error': 'Email taken',
'message': 'Email already registered'
}), 409
# Create new user
new_user = User(
username=username,
email=email,
password=password
)
db.session.add(new_user)
db.session.commit()
# Generate JWT token
token = generate_jwt_token(new_user.id)
return jsonify({
'message': 'User registered successfully',
'user': new_user.to_dict(),
'token': token
}), 201
except Exception as e:
db.session.rollback()
app.logger.error(f"Registration error: {str(e)}")
app.logger.error(traceback.format_exc())
return jsonify({
'error': 'Registration failed',
'message': 'An error occurred during registration'
}), 500
@app.route('/api/login', methods=['POST'])
def login():
"""User login endpoint."""
try:
data = request.get_json()
if not data:
return jsonify({
'error': 'Invalid input',
'message': 'JSON data is required'
}), 400
login_identifier = data.get('username') or data.get('email', '')
password = data.get('password', '')
if not login_identifier or not password:
return jsonify({
'error': 'Missing credentials',
'message': 'Username/email and password are required'
}), 400
login_identifier = login_identifier.strip().lower()
# Find user by username or email
user = User.query.filter(
(User.username == login_identifier) | (User.email == login_identifier)
).first()
if not user or not user.check_password(password):
return jsonify({
'error': 'Invalid credentials',
'message': 'Username/email or password is incorrect'
}), 401
if not user.is_active:
return jsonify({
'error': 'Account disabled',
'message': 'Your account has been disabled'
}), 401
# Generate JWT token
token = generate_jwt_token(user.id)
return jsonify({
'message': 'Login successful',
'user': user.to_dict(),
'token': token
}), 200
except Exception as e:
app.logger.error(f"Login error: {str(e)}")
app.logger.error(traceback.format_exc())
return jsonify({
'error': 'Login failed',
'message': 'An error occurred during login'
}), 500
@app.route('/api/profile', methods=['GET'])
@token_required
def get_profile(current_user):
"""Get current user profile (protected endpoint)."""
return jsonify({
'message': 'Profile retrieved successfully',
'user': current_user.to_dict()
}), 200
@app.route('/api/profile', methods=['PUT'])
@token_required
def update_profile(current_user):
"""Update current user profile (protected endpoint)."""
try:
data = request.get_json()
if not data:
return jsonify({
'error': 'Invalid input',
'message': 'JSON data is required'
}), 400
username = data.get('username')
email = data.get('email')
# Update username if provided
if username is not None:
username = username.strip()
if not validate_username(username):
return jsonify({
'error': 'Invalid username',
'message': 'Username must be 3-80 characters and contain only letters, numbers, and underscores'
}), 400
# Check if username is already taken by another user
existing_user = User.query.filter(
User.username == username,
User.id != current_user.id
).first()
if existing_user:
return jsonify({
'error': 'Username taken',
'message': 'Username already exists'
}), 409
current_user.username = username
# Update email if provided
if email is not None:
email = email.strip().lower()
if not validate_email(email):
return jsonify({
'error': 'Invalid email',
'message': 'Please provide a valid email address'
}), 400
# Check if email is already taken by another user
existing_user = User.query.filter(
User.email == email,
User.id != current_user.id
).first()
if existing_user:
return jsonify({
'error': 'Email taken',
'message': 'Email already registered'
}), 409
current_user.email = email
db.session.commit()
return jsonify({
'message': 'Profile updated successfully',
'user': current_user.to_dict()
}), 200
except Exception as e:
db.session.rollback()
app.logger.error(f"Profile update error: {str(e)}")
app.logger.error(traceback.format_exc())
return jsonify({
'error': 'Update failed',
'message': 'An error occurred while updating profile'
}), 500
@app.route('/api/change-password', methods=['POST'])
@token_required
def change_password(current_user):
"""Change user password (protected endpoint)."""
try:
data = request.get_json()
if not data:
return jsonify({
'error': 'Invalid input',
'message': 'JSON data is required'
}), 400
current_password = data.get('current_password', '')
new_password = data.get('new_password', '')
if not current_password or not new_password:
return jsonify({
'error': 'Missing password fields',
'message': 'Current password and new password are required'
}), 400
# Verify current password
if not current_user.check_password(current_password):
return jsonify({
'error': 'Invalid current password',
'message': 'Current password is incorrect'
}), 401
# Validate new password strength
is_valid, password_message = validate_password_strength(new_password)
if not is_valid:
return jsonify({
'error': 'Weak password',
'message': password_message
}), 400
# Check if new password is different from current
if current_user.check_password(new_password):
return jsonify({
'error': 'Same password',
'message': 'New password must be different from current password'
}), 400
# Update password
current_user.set_password(new_password)
db.session.commit()
return jsonify({
'message': 'Password changed successfully'
}), 200
except Exception as e:
db.session.rollback()
app.logger.error(f"Password change error: {str(e)}")
app.logger.error(traceback.format_exc())
return jsonify({
'error': 'Password change failed',
'message': 'An error occurred while changing password'
}), 500
@app.route('/api/users', methods=['GET'])
@token_required
def get_users(current_user):
"""Get all users (protected endpoint)."""
try:
users = User.query.filter_by(is_active=True).all()
users_data = [user.to_dict() for user in users]
return jsonify({
'message': 'Users retrieved successfully',
'users': users_data,
'count': len(users_data)
}), 200
except Exception as e:
app.logger.error(f"Get users error: {str(e)}")
app.logger.error(traceback.format_exc())
return jsonify({
'error': 'Failed to retrieve users',
'message': 'An error occurred while fetching users'
}), 500
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)