Files
hsa/Html/apps/views/vscode.py
2025-09-11 13:23:11 +00:00

121 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# myapp/views/vscode.py
import os, uuid, json
from flask import Blueprint, current_app, session, redirect, url_for, render_template, request, jsonify
from ..services.backboard_service import realtime_response
import subprocess
bp = Blueprint("vscode", __name__)
@bp.route("/desktop/<user_uuid>/<course_id>/<chapter_name>/<lesson_name>")
def desktop(user_uuid, course_id, chapter_name, lesson_name):
username2uuid = current_app.extensions["username2uuid"]
uuid2username = current_app.extensions["uuid2username"]
userid_recorder = current_app.extensions["userid_recorder"]
# session 中放 uuid访客也能进则给一个
if "user_uuid" not in session:
user_uuid = "user_" + str(uuid.uuid4())
session["user_uuid"] = user_uuid
uuid2username[user_uuid] = "guest"+str(uuid.uuid4())[0:5]
username2uuid[uuid2username[user_uuid]] = user_uuid
# 全局映射
user_id = uuid2username[user_uuid]
userid_recorder[f"{user_id}&{course_id}"] = session["user_uuid"]
# 按课程/章节创建工作目录
base_root = current_app.config["STUDENT_WORKSPACE_ROOT"]
user_home = os.path.join("/home", user_id)
try:
subprocess.run(["sudo", "useradd", "-m", "-d", user_home, user_id]) # 创建用户
subprocess.run(["sudo", "chown", "-R", user_id, user_home]) # 设置目录权限为新用户
except subprocess.CalledProcessError as e:
print(f"Error creating user {user_id}: {e}")
path_dir = os.path.join("/home", user_id, course_id, chapter_name, lesson_name)
try:
# 使用 sudo 执行 mkdir 命令来创建目录
subprocess.run(["sudo", "-u", user_id, "mkdir", "-p", path_dir], check=True)
print(f"Directory {path_dir} created successfully for user {user_id}")
except subprocess.CalledProcessError as e:
print(f"Error creating directory {path_dir} details {str(e)}")
code_server_port = 10000 + int(uuid.uuid4().int % 10000)
try:
subprocess.Popen([
"sudo", "-u", user_id,
"code-server", "--bind-addr", f"0.0.0.0:{code_server_port}",
"--auth", "none", path_dir,
"--extensions-dir", "/share/extension/"
])
except subprocess.CalledProcessError as e:
print(f"Error start code-server at {code_server_port} with path{path_dir} {e}")
caddy_conf = f"""
handle_path /vsc{user_uuid}/* {{
reverse_proxy localhost:{code_server_port}
}}
"""
caddy_config_path = "/etc/caddy/Caddyfile"
with open(caddy_config_path, "r") as f:
lines = f.readlines()
insert_position = len(lines) - 2 if len(lines) >= 2 else len(lines)
lines.insert(insert_position, caddy_conf)
with open(caddy_config_path, "w") as f:
f.writelines(lines)
try:
subprocess.run(["sudo", "caddy", "reload", "--config", "/etc/caddy/Caddyfile"])
except subprocess.CalledProcessError as e:
print(f"Error reload caddy {e}")
cfg = current_app.config["VSCODE_WEB_PATH"]
path_for_vscode = path_dir
config_path = os.path.join(path_dir, ".config")
tmpd = {
"user_uuid": session["user_uuid"],
"course_id": course_id,
"chapter_name": chapter_name,
"lesson_name": lesson_name,
"path": path_for_vscode
}
config_json = json.dumps(tmpd, ensure_ascii=False)
# 使用 sudo 和 tee 命令将 JSON 数据写入文件
subprocess.run(
["sudo", "-u", user_id, "bash", "-c", f"echo '{config_json}' | tee {config_path} > /dev/null"],
check=True
)
# 确保文件的所有权归 user_id
subprocess.run(
["sudo", "chown", f"{user_id}:{user_id}", config_path],
check=True
)
return render_template(
"desktop.html",
vscode_web_url=current_app.config["VSCODE_WEB_URL"]+f"/vsc{user_uuid}",
user_uuid=session["user_uuid"], course_id=course_id, chapter_name=chapter_name, lesson_name=lesson_name,
workspace_path=path_for_vscode,
)
@bp.route("/desktop_nouser/<course_id>/<chapter_name>/<lesson_name>")
def desktop_nouser(course_id, chapter_name, lesson_name):
if "user_uuid" not in session:
return redirect(url_for("auth.login")) # 如果你有 auth 蓝图
user_uuid = session["user_uuid"]
return redirect(url_for("vscode.desktop", user_uuid=user_uuid, course_id=course_id, chapter_name=chapter_name, lesson_name=lesson_name))
@bp.route("/vscode_data", methods=["POST"])
def vscode_data():
# data = request.get_json(force=True)
# config = data.get("config") or {}
# realtime_response(config, data) # 调用服务层逻辑
# return jsonify({"status": "success", "received": data})
return jsonify({"status": "success", "received": "success"})