Update flask_server.py

This commit is contained in:
MacRimi
2025-11-04 09:46:11 +01:00
parent c0ec74fb12
commit 37f6cd96a4

View File

@@ -88,6 +88,210 @@ def require_auth(f):
return decorated_function
# Authentication endpoints
@app.route('/api/auth/status', methods=['GET'])
def auth_status():
"""Check if authentication is enabled and if current session is valid"""
try:
auth_config = load_auth_config()
is_enabled = auth_config.get("auth_enabled", False)
# Check if user has valid token
is_authenticated = False
if is_enabled:
auth_header = request.headers.get('Authorization')
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ')[1]
try:
payload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])
if time.time() <= payload.get('exp', 0):
is_authenticated = True
except:
pass
return jsonify({
"auth_enabled": is_enabled,
"authenticated": is_authenticated or not is_enabled
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/auth/setup', methods=['POST'])
def auth_setup():
"""Setup authentication for the first time"""
try:
data = request.get_json()
username = data.get('username', '').strip()
password = data.get('password', '').strip()
if not username or not password:
return jsonify({"error": "Username and password are required"}), 400
if len(password) < 6:
return jsonify({"error": "Password must be at least 6 characters"}), 400
# Hash password and save config
password_hash = hash_password(password)
auth_config = {
"auth_enabled": True,
"username": username,
"password_hash": password_hash,
"created_at": datetime.now().isoformat()
}
save_auth_config(auth_config)
# Generate JWT token
token = jwt.encode({
'username': username,
'exp': time.time() + SESSION_TIMEOUT
}, JWT_SECRET, algorithm='HS256')
return jsonify({
"success": True,
"token": token
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/auth/skip', methods=['POST'])
def auth_skip():
"""Skip authentication setup"""
try:
auth_config = {
"auth_enabled": False,
"skipped": True,
"skipped_at": datetime.now().isoformat()
}
save_auth_config(auth_config)
return jsonify({"success": True})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/auth/login', methods=['POST'])
def auth_login():
"""Login with username and password"""
try:
data = request.get_json()
username = data.get('username', '').strip()
password = data.get('password', '').strip()
if not username or not password:
return jsonify({"error": "Username and password are required"}), 400
# Load auth config
auth_config = load_auth_config()
if not auth_config.get("auth_enabled", False):
return jsonify({"error": "Authentication is not enabled"}), 400
# Verify credentials
stored_username = auth_config.get("username", "")
stored_password_hash = auth_config.get("password_hash", "")
if username != stored_username or hash_password(password) != stored_password_hash:
return jsonify({"error": "Invalid username or password"}), 401
# Generate JWT token
token = jwt.encode({
'username': username,
'exp': time.time() + SESSION_TIMEOUT
}, JWT_SECRET, algorithm='HS256')
return jsonify({
"success": True,
"token": token
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/auth/refresh', methods=['POST'])
def auth_refresh():
"""Refresh JWT token"""
try:
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({"error": "No token provided"}), 401
token = auth_header.split(' ')[1]
try:
# Verify current token
payload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])
username = payload.get('username')
# Generate new token
new_token = jwt.encode({
'username': username,
'exp': time.time() + SESSION_TIMEOUT
}, JWT_SECRET, algorithm='HS256')
return jsonify({
"success": True,
"token": new_token
})
except jwt.InvalidTokenError:
return jsonify({"error": "Invalid token"}), 401
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/auth/logout', methods=['POST'])
@require_auth
def auth_logout():
"""Logout (client should delete token)"""
return jsonify({"success": True})
@app.route('/api/auth/disable', methods=['POST'])
@require_auth
def auth_disable():
"""Disable authentication"""
try:
auth_config = {
"auth_enabled": False,
"disabled_at": datetime.now().isoformat()
}
save_auth_config(auth_config)
return jsonify({"success": True})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/api/auth/change-password', methods=['POST'])
@require_auth
def auth_change_password():
"""Change password"""
try:
data = request.get_json()
current_password = data.get('current_password', '').strip()
new_password = data.get('new_password', '').strip()
if not current_password or not new_password:
return jsonify({"error": "Current and new password are required"}), 400
if len(new_password) < 6:
return jsonify({"error": "New password must be at least 6 characters"}), 400
# Load auth config
auth_config = load_auth_config()
# Verify current password
stored_password_hash = auth_config.get("password_hash", "")
if hash_password(current_password) != stored_password_hash:
return jsonify({"error": "Current password is incorrect"}), 401
# Update password
auth_config["password_hash"] = hash_password(new_password)
auth_config["updated_at"] = datetime.now().isoformat()
save_auth_config(auth_config)
return jsonify({"success": True})
except Exception as e:
return jsonify({"error": str(e)}), 500
app = Flask(__name__)
CORS(app) # Enable CORS for Next.js frontend