import subprocess import json import os import time from flask import Flask, render_template, request, Response, jsonify, redirect, url_for, session from datetime import timedelta from dotenv import load_dotenv # Load biến môi trường từ file .env load_dotenv() app = Flask(__name__) app.secret_key = os.getenv("SECRET_KEY", "default_secret_key") # Lấy từ .env hoặc đặt giá trị mặc định app.permanent_session_lifetime = timedelta(days=1) # Danh sách tài khoản & mật khẩu USERS = { "admin": "123456", "user1": "password1", "user2": "password2" } # Định nghĩa đường dẫn file JSON chứa danh sách service SERVICES_FILE = os.path.join(os.path.dirname(__file__), "data", "services.json") def load_services(): """Đọc danh sách services từ file JSON""" with open(SERVICES_FILE, "r", encoding="utf-8") as file: return json.load(file) @app.route("/") def home(): """Trang chủ: Hiển thị danh sách service (yêu cầu đăng nhập)""" if "user" not in session: return redirect(url_for("login")) listService = [s for s in load_services() if s.get("status", "active") == "active"] return render_template("index.html", listService=listService) @app.route("/login", methods=["GET", "POST"]) def login(): """Xử lý đăng nhập""" if request.method == "POST": username = request.form.get("username") password = request.form.get("password") if username in USERS and USERS[username] == password: session["user"] = username session.permanent = True return redirect(url_for("home")) else: return render_template("login.html", error="Invalid username or password") return render_template("login.html") @app.route("/logout") def logout(): """Đăng xuất""" session.pop("user", None) return redirect(url_for("login")) def run_shell_command(command_str): """Chạy một lệnh shell và gửi output theo thời gian thực""" process = subprocess.Popen(command_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, executable="/bin/bash") for line in iter(process.stdout.readline, ''): yield f"data: {line.strip()}\n\n" time.sleep(0.1) for line in iter(process.stderr.readline, ''): yield f"data: [] {line.strip()}\n\n" time.sleep(0.1) process.wait() if process.returncode == 0: yield f"data: SUCCESS\n\n" else: yield f"data: ERROR\n\n" def generate_output(command_list): """Chạy command từ JSON, sau đó restart Nginx""" command_str = " ".join(command_list) yield from run_shell_command(command_str) nginx_project_path = os.getenv("NGINX_PROJECT_PATH", "/projects/nginx") nginx_command = f"cd {nginx_project_path} && docker compose down && docker compose up -d" yield f"data: === Restarting Nginx ===\n\n" yield from run_shell_command(nginx_command) @app.route("/run-command", methods=["GET"]) def run_command(): """API chạy command từ frontend""" if "user" not in session: return jsonify({"error": "Unauthorized"}), 401 command_list = request.args.getlist("command[]") if not command_list: return jsonify({"error": "No command provided"}), 400 return Response(generate_output(command_list), mimetype="text/event-stream") if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)