This commit is contained in:
5t4l1n
2025-07-25 23:58:20 +05:30
parent b70e81d201
commit 4d8061616d
112 changed files with 14445 additions and 59 deletions
+70 -51
View File
@@ -1,71 +1,90 @@
from flask import Blueprint, request, jsonify, current_app
import jwt
from datetime import datetime, timedelta
import secrets
bp = Blueprint('auth', __name__)
bp = Blueprint("auth", __name__)
@bp.route('/nonce', methods=['POST'])
# Store nonces temporarily (in production, use Redis or database)
nonces = {}
@bp.route("/nonce", methods=["POST"])
def get_nonce():
"""Generate nonce for wallet signature"""
data = request.get_json()
wallet_address = data.get('wallet_address')
wallet_address = data.get("wallet_address")
if not wallet_address:
return jsonify({"error": "Wallet address required"}), 400
web3_service = current_app.config['WEB3_SERVICE']
nonce = web3_service.generate_nonce()
return jsonify({"error": "wallet_address is required"}), 400
# Generate nonce
nonce = secrets.token_hex(16)
message = f"Sign this message to authenticate with OpenLearnX: {nonce}"
return jsonify({
"nonce": nonce,
"message": message
})
# Store nonce for this wallet address
nonces[wallet_address.lower()] = nonce
return jsonify({"nonce": nonce, "message": message})
@bp.route('/verify', methods=['POST'])
async def verify_signature():
"""Verify MetaMask signature and create session"""
@bp.route("/verify", methods=["POST"])
def verify_signature():
data = request.get_json()
wallet_address = data.get('wallet_address')
signature = data.get('signature')
message = data.get('message')
wallet_address = data.get("wallet_address", "").lower()
signature = data.get("signature")
message = data.get("message")
if not all([wallet_address, signature, message]):
return jsonify({"error": "Missing required fields"}), 400
web3_service = current_app.config['WEB3_SERVICE']
mongo_service = current_app.config['MONGO_SERVICE']
# Verify nonce
stored_nonce = nonces.get(wallet_address)
if not stored_nonce or stored_nonce not in message:
return jsonify({"error": "Invalid nonce"}), 400
# Verify signature
if not web3_service.verify_signature(wallet_address, message, signature):
return jsonify({"error": "Invalid signature"}), 401
# Create or get user
user = await mongo_service.create_user(wallet_address)
await mongo_service.update_user_login(wallet_address)
# Create JWT token
token_payload = {
'user_id': str(user['_id']),
'wallet_address': wallet_address,
'exp': datetime.utcnow() + timedelta(days=7)
}
token = jwt.encode(
token_payload,
current_app.config['SECRET_KEY'],
algorithm='HS256'
)
return jsonify({
"success": True,
"token": token,
"user": {
"id": str(user['_id']),
"wallet_address": user['wallet_address'],
"created_at": user['created_at'].isoformat(),
"total_tests": user.get('total_tests', 0),
"certificates": len(user.get('certificates', []))
try:
web3_service = current_app.config["WEB3_SERVICE"]
# Verify signature
if not web3_service.verify_signature(wallet_address, message, signature):
return jsonify({"error": "Invalid signature"}), 401
# For now, create a mock user without database operations
# This bypasses the async MongoDB issues entirely
user = {
"_id": f"user_{wallet_address}",
"wallet_address": wallet_address,
"created_at": datetime.utcnow(),
"total_tests": 0,
"certificates": []
}
})
# Create JWT token
token_payload = {
"user_id": str(user["_id"]),
"wallet_address": wallet_address,
"exp": datetime.utcnow() + timedelta(days=7)
}
token = jwt.encode(
token_payload,
current_app.config["SECRET_KEY"],
algorithm="HS256"
)
# Clean up nonce
if wallet_address in nonces:
del nonces[wallet_address]
return jsonify({
"success": True,
"token": token,
"user": {
"id": str(user["_id"]),
"wallet_address": user["wallet_address"],
"total_tests": user.get("total_tests", 0),
"certificates": len(user.get("certificates", []))
}
})
except Exception as e:
print(f"Authentication error: {str(e)}")
return jsonify({"error": "Authentication failed"}), 500
+88
View File
@@ -0,0 +1,88 @@
from flask import Blueprint, jsonify, request, current_app
import requests
from bson import ObjectId
from datetime import datetime
bp = Blueprint('coding', __name__)
PISTON_API_URL = "https://emkc.org/api/v2/piston/execute"
@bp.route("/problems", methods=["GET"])
async def get_problems():
mongo = current_app.config['MONGO_SERVICE']
problems = await mongo.db.coding_problems.find().to_list(100)
for p in problems:
p['_id'] = str(p['_id'])
return jsonify(problems)
@bp.route("/problems/<problem_id>", methods=["GET"])
async def get_problem(problem_id):
mongo = current_app.config['MONGO_SERVICE']
prob = await mongo.db.coding_problems.find_one({"_id": ObjectId(problem_id)})
if not prob:
return jsonify({"error": "Problem not found"}), 404
prob['_id'] = str(prob['_id'])
return jsonify(prob)
@bp.route("/run", methods=["POST"])
async def run_code():
data = request.json
problem_id = data.get("problem_id")
code = data.get("code")
language = data.get("language")
mongo = current_app.config['MONGO_SERVICE']
problem = await mongo.db.coding_problems.find_one({"_id": ObjectId(problem_id)})
if not problem:
return jsonify({"error": "Problem not found"}), 404
# Concatenate all test case inputs
input_data = '\n'.join([tc['input'] for tc in problem['test_cases']])
try:
resp = requests.post(
PISTON_API_URL,
json={
"language": language,
"source": code,
"input": input_data
},
timeout=10,
)
resp.raise_for_status()
result = resp.json()
except Exception as e:
return jsonify({"error": str(e)}), 500
# Compare output against expected (simple line-by-line check)
output_lines = result.get("output", "").strip().split('\n')
expected_outputs = [tc['expected_output'].strip() for tc in problem['test_cases']]
correct = output_lines == expected_outputs
return jsonify({
"output": result.get("output"),
"error": result.get("stderr"),
"runtime": result.get("stats", {}).get("duration"),
"correct": correct,
})
@bp.route("/submit", methods=["POST"])
async def submit_solution():
# Same as run_code, but can mark problem as solved
user = await get_authenticated_user()
if not user:
return jsonify({"error": "Unauthorized"}), 401
# Run the code first
result = await run_code()
jres = result.get_json()
if jres.get("correct"):
mongo = current_app.config['MONGO_SERVICE']
# Record that user solved problem
await mongo.db.user_solutions.update_one(
{"user_id": user['_id'], "problem_id": jres.get('problem_id')},
{"$set": {"solved": True, "solved_at": datetime.utcnow()}},
upsert=True
)
return jsonify(jres)
``
+43
View File
@@ -0,0 +1,43 @@
from flask import Blueprint, jsonify, current_app
import asyncio
from bson import ObjectId
bp = Blueprint('courses', __name__)
# Remove trailing slash from route definition
@bp.route("/", methods=["GET"])
@bp.route("", methods=["GET"]) # Add this line to handle both cases
def list_courses():
try:
# Your existing course logic here
# Mock data for now since you're having DB async issues
courses = [
{
"id": "python-course",
"title": "Python Programming Mastery",
"subject": "Programming",
"description": "Learn Python from basics to advanced concepts",
"difficulty": "Beginner to Advanced",
"progress": 0
},
{
"id": "java-course",
"title": "Java Development Bootcamp",
"subject": "Programming",
"description": "Master Java programming with object-oriented concepts",
"difficulty": "Intermediate",
"progress": 0
},
{
"id": "ethical-hacking-course",
"title": "Ethical Hacking & Cybersecurity",
"subject": "Cybersecurity",
"description": "Learn ethical hacking techniques and penetration testing",
"difficulty": "Advanced",
"progress": 0
}
]
return jsonify(courses)
except Exception as e:
print(f"Error in list_courses: {e}")
return jsonify({"error": "Failed to fetch courses"}), 500
+32
View File
@@ -0,0 +1,32 @@
from flask import Blueprint, jsonify
bp = Blueprint('quizzes', __name__)
# Handle both with and without trailing slash
@bp.route("/", methods=["GET"])
@bp.route("", methods=["GET"]) # Add this line
def list_quizzes():
quizzes = [
{
"id": "python-quiz",
"title": "Python Fundamentals Quiz",
"topic": "Programming",
"difficulty": "Easy",
"recent_performance": 85
},
{
"id": "java-quiz",
"title": "Java OOP Concepts Quiz",
"topic": "Programming",
"difficulty": "Medium",
"recent_performance": 78
},
{
"id": "security-quiz",
"title": "Cybersecurity Basics Quiz",
"topic": "Security",
"difficulty": "Hard",
"recent_performance": 72
}
]
return jsonify(quizzes)