Spaces:
Sleeping
Sleeping
| import os | |
| from datetime import datetime, timedelta | |
| from flask import Flask, request, jsonify | |
| import jwt | |
| from supabase import create_client, Client | |
| app = Flask(__name__) | |
| # ββ Configuration ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| SUPABASE_URL = os.getenv('SUPABASE_URL', 'https://hzvpbysektyrztlpvbhu.supabase.co') | |
| SUPABASE_KEY = os.getenv('SUPABASE_KEY', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imh6dnBieXNla3R5cnp0bHB2Ymh1Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njg5NjY3MDIsImV4cCI6MjA4NDU0MjcwMn0.lIAECydBZjNQOLNG748KmCdWOfTMfUIIW2yd_6xCEQw') | |
| supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) | |
| SECRET_KEY = os.getenv('SECRET_KEY', 'aymmm-change-this-in-production') | |
| # ββ Health check βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def home(): | |
| return jsonify({ | |
| "status": "running", | |
| "message": "Custom JWT + Supabase demo (UUID-based profile fetch)", | |
| "endpoints": { | |
| "POST /signup": "Create user profile", | |
| "POST /login": "Authenticate and get JWT", | |
| "GET /profile": "Get profile (requires Bearer token)" | |
| } | |
| }) | |
| # ββ Signup βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def signup(): | |
| data = request.get_json() | |
| required = ['name', 'email', 'password', 'department'] | |
| if not data or not all(k in data for k in required): | |
| return jsonify({'message': 'Missing required fields'}), 400 | |
| email = data['email'].strip().lower() | |
| name = data['name'].strip() | |
| department = data['department'].strip() | |
| password = data['password'] # plain text β demo only | |
| # Check if email exists | |
| existing = supabase.table('profiles') \ | |
| .select('email') \ | |
| .eq('email', email) \ | |
| .execute() | |
| if existing.data: | |
| return jsonify({'message': 'User already exists'}), 409 | |
| # Insert new profile | |
| insert_data = { | |
| 'name': name, | |
| 'email': email, | |
| 'department': department | |
| # password NOT stored β add hashing later | |
| } | |
| result = supabase.table('profiles').insert(insert_data).execute() | |
| if not result.data: | |
| return jsonify({'message': 'Failed to create user'}), 500 | |
| return jsonify({'message': 'User created successfully'}), 201 | |
| # ββ Login ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def login(): | |
| data = request.get_json() | |
| if not data or 'email' not in data or 'password' not in data: | |
| return jsonify({'message': 'Missing email or password'}), 400 | |
| email = data['email'].strip().lower() | |
| password = data['password'] | |
| user_response = supabase.table('profiles') \ | |
| .select('id, name, email, department') \ | |
| .eq('email', email) \ | |
| .maybe_single() \ | |
| .execute() | |
| if user_response.data is None: | |
| return jsonify({'message': 'User not found'}), 404 | |
| user = user_response.data | |
| # TODO: Replace with real password verification (bcrypt, etc.) | |
| # Right now: insecure β any password works if email exists | |
| payload = { | |
| 'sub': email, | |
| 'uid': str(user['id']), | |
| 'name': user['name'], | |
| 'department': user['department'], | |
| 'iat': datetime.utcnow(), | |
| 'exp': datetime.utcnow() + timedelta(minutes=60) | |
| } | |
| token = jwt.encode(payload, SECRET_KEY, algorithm='HS256') | |
| return jsonify({'token': token}) | |
| # ββ Profile ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def profile(): | |
| auth_header = request.headers.get('Authorization') | |
| if not auth_header or not auth_header.startswith('Bearer '): | |
| return jsonify({'message': 'Missing or invalid Authorization header'}), 401 | |
| token = auth_header.split(' ')[1] | |
| try: | |
| decoded = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) | |
| user_id = decoded.get('uid') | |
| if not user_id: | |
| return jsonify({'message': 'Token missing user identifier'}), 401 | |
| user_response = supabase.table('profiles') \ | |
| .select('name, email, department') \ | |
| .eq('id', user_id) \ | |
| .maybe_single() \ | |
| .execute() | |
| if user_response.data is None: | |
| return jsonify({'message': 'User not found'}), 404 | |
| user = user_response.data | |
| return jsonify({ | |
| 'name': user['name'], | |
| 'email': user['email'], | |
| 'department': user['department'] | |
| }) | |
| except jwt.ExpiredSignatureError: | |
| return jsonify({'message': 'Token has expired'}), 401 | |
| except jwt.InvalidTokenError: | |
| return jsonify({'message': 'Invalid token'}), 401 | |
| except Exception as e: | |
| return jsonify({'message': f'Server error: {str(e)}'}), 500 | |
| if __name__ == '__main__': | |
| port = int(os.environ.get('PORT', 7860)) | |
| app.run(host='0.0.0.0', port=port, debug=False) |