mirror of
https://github.com/th30d4y/OpenLearnX.git
synced 2026-05-26 19:26:33 +00:00
backend
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
from flask import Blueprint, request, jsonify, current_app
|
||||
import jwt
|
||||
from datetime import datetime, timedelta
|
||||
import uuid
|
||||
|
||||
bp = Blueprint('auth', __name__)
|
||||
|
||||
@bp.route('/nonce', methods=['POST'])
|
||||
async def get_nonce():
|
||||
"""Generate nonce for wallet signature"""
|
||||
data = request.get_json()
|
||||
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()
|
||||
|
||||
# Store nonce temporarily (in production, use Redis)
|
||||
message = f"Sign this message to authenticate with OpenLearnX: {nonce}"
|
||||
|
||||
return jsonify({
|
||||
"nonce": nonce,
|
||||
"message": message
|
||||
})
|
||||
|
||||
@bp.route('/verify', methods=['POST'])
|
||||
async def verify_signature():
|
||||
"""Verify MetaMask signature and create session"""
|
||||
data = request.get_json()
|
||||
wallet_address = data.get('wallet_address')
|
||||
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 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', []))
|
||||
}
|
||||
})
|
||||
|
||||
@bp.route('/profile', methods=['GET'])
|
||||
async def get_profile():
|
||||
"""Get user profile"""
|
||||
token = request.headers.get('Authorization', '').replace('Bearer ', '')
|
||||
|
||||
if not token:
|
||||
return jsonify({"error": "Token required"}), 401
|
||||
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token,
|
||||
current_app.config['SECRET_KEY'],
|
||||
algorithms=['HS256']
|
||||
)
|
||||
user_id = payload['user_id']
|
||||
|
||||
mongo_service = current_app.config['MONGO_SERVICE']
|
||||
analytics = await mongo_service.get_user_analytics(user_id)
|
||||
|
||||
return jsonify(analytics)
|
||||
|
||||
except jwt.ExpiredSignatureError:
|
||||
return jsonify({"error": "Token expired"}), 401
|
||||
except jwt.InvalidTokenError:
|
||||
return jsonify({"error": "Invalid token"}), 401
|
||||
Reference in New Issue
Block a user