# routes/admin_routes.py - Admin Dashboard Routes from flask import Blueprint, request, jsonify, session, send_from_directory from db import get_db from auth import admin_required admin_bp = Blueprint('admin', __name__) @admin_bp.route('/admin') @admin_required def admin_page(): """Serve admin dashboard page.""" return send_from_directory('templates', 'admin.html') @admin_bp.route('/api/admin/users', methods=['GET']) @admin_required def list_users(): """List all users.""" db = get_db() cursor = db.cursor() cursor.execute(''' SELECT id, username, role, is_active, created_at, last_login FROM users ORDER BY created_at DESC ''') users = [] for row in cursor.fetchall(): users.append({ 'id': row['id'], 'username': row['username'], 'role': row['role'], 'is_active': bool(row['is_active']), 'created_at': row['created_at'], 'last_login': row['last_login'] }) return jsonify({'users': users}) @admin_bp.route('/api/admin/users', methods=['POST']) @admin_required def create_user(): """Create a new user.""" data = request.json username = data.get('username', '').strip() password = data.get('password', '') role = data.get('role', 'user') if not username or not password: return jsonify({'error': 'Username and password are required'}), 400 if len(username) < 3: return jsonify({'error': 'Username must be at least 3 characters'}), 400 if len(password) < 4: return jsonify({'error': 'Password must be at least 4 characters'}), 400 if role not in ('user', 'admin'): return jsonify({'error': 'Role must be "user" or "admin"'}), 400 db = get_db() cursor = db.cursor() try: cursor.execute(''' INSERT INTO users (username, password, role, is_active) VALUES (?, ?, ?, 1) ''', (username, password, role)) db.commit() print(f"✅ New user created: {username} (role: {role})") return jsonify({ 'success': True, 'user_id': cursor.lastrowid, 'message': f'User "{username}" created successfully' }) except Exception as e: if 'UNIQUE constraint' in str(e): return jsonify({'error': f'Username "{username}" already exists'}), 400 return jsonify({'error': str(e)}), 500 @admin_bp.route('/api/admin/users/', methods=['PUT']) @admin_required def update_user(user_id): """Update a user.""" data = request.json db = get_db() cursor = db.cursor() cursor.execute('SELECT id, username FROM users WHERE id = ?', (user_id,)) user = cursor.fetchone() if not user: return jsonify({'error': 'User not found'}), 404 # Build update query dynamically updates = [] params = [] if 'username' in data: username = data['username'].strip() if len(username) < 3: return jsonify({'error': 'Username must be at least 3 characters'}), 400 updates.append('username = ?') params.append(username) if 'password' in data and data['password']: password = data['password'] if len(password) < 4: return jsonify({'error': 'Password must be at least 4 characters'}), 400 updates.append('password = ?') params.append(password) if 'role' in data: role = data['role'] if role not in ('user', 'admin'): return jsonify({'error': 'Role must be "user" or "admin"'}), 400 # Prevent demoting self if user_id == session.get('user_id') and role != 'admin': return jsonify({'error': 'Cannot change your own role'}), 400 updates.append('role = ?') params.append(role) if 'is_active' in data: # Prevent deactivating self if user_id == session.get('user_id') and not data['is_active']: return jsonify({'error': 'Cannot deactivate your own account'}), 400 updates.append('is_active = ?') params.append(1 if data['is_active'] else 0) if not updates: return jsonify({'error': 'No fields to update'}), 400 params.append(user_id) try: cursor.execute(f"UPDATE users SET {', '.join(updates)} WHERE id = ?", params) db.commit() return jsonify({'success': True, 'message': 'User updated successfully'}) except Exception as e: if 'UNIQUE constraint' in str(e): return jsonify({'error': 'Username already exists'}), 400 return jsonify({'error': str(e)}), 500 @admin_bp.route('/api/admin/users/', methods=['DELETE']) @admin_required def delete_user(user_id): """Delete a user.""" # Prevent deleting self if user_id == session.get('user_id'): return jsonify({'error': 'Cannot delete your own account'}), 400 db = get_db() cursor = db.cursor() cursor.execute('SELECT id, username FROM users WHERE id = ?', (user_id,)) user = cursor.fetchone() if not user: return jsonify({'error': 'User not found'}), 404 cursor.execute('DELETE FROM users WHERE id = ?', (user_id,)) db.commit() print(f"🗑️ User deleted: {user['username']}") return jsonify({'success': True, 'message': f'User "{user["username"]}" deleted'})