fix: 收紧 GUI 安全边界
This commit is contained in:
+39
-27
@@ -16,6 +16,7 @@ import traceback
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from calendar import monthrange
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from typing import Any
|
||||
@@ -178,11 +179,22 @@ def connect() -> sqlite3.Connection:
|
||||
return conn
|
||||
|
||||
|
||||
@contextmanager
|
||||
def db_connect():
|
||||
with db_lock:
|
||||
conn = connect()
|
||||
try:
|
||||
with conn:
|
||||
yield conn
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def init_db() -> None:
|
||||
db_dir = os.path.dirname(DB_PATH)
|
||||
if db_dir:
|
||||
os.makedirs(db_dir, exist_ok=True)
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.executescript(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS job_schedules (
|
||||
@@ -322,7 +334,7 @@ def row_to_one_time_job(row: sqlite3.Row) -> dict[str, Any]:
|
||||
|
||||
|
||||
def fetch_job(schedule_id: int) -> dict[str, Any]:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM job_schedules WHERE id=?", (schedule_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -331,13 +343,13 @@ def fetch_job(schedule_id: int) -> dict[str, Any]:
|
||||
|
||||
def list_jobs() -> list[dict[str, Any]]:
|
||||
refresh_running_jobs()
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
rows = conn.execute("SELECT * FROM job_schedules ORDER BY id DESC").fetchall()
|
||||
return [row_to_job(row) for row in rows]
|
||||
|
||||
|
||||
def fetch_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM one_time_jobs WHERE id=?", (job_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -346,7 +358,7 @@ def fetch_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
|
||||
def list_one_time_jobs() -> list[dict[str, Any]]:
|
||||
refresh_one_time_jobs()
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
rows = conn.execute("SELECT * FROM one_time_jobs ORDER BY updated_at DESC, id DESC").fetchall()
|
||||
return [row_to_one_time_job(row) for row in rows]
|
||||
|
||||
@@ -383,7 +395,7 @@ def create_job(payload: dict[str, Any]) -> dict[str, Any]:
|
||||
interval_seconds = legacy_interval_seconds(schedule_kind)
|
||||
|
||||
now = iso(utcnow())
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
cur = conn.execute(
|
||||
"""
|
||||
INSERT INTO job_schedules
|
||||
@@ -423,7 +435,7 @@ def create_one_time_job(payload: dict[str, Any]) -> dict[str, Any]:
|
||||
raise ApiError(400, "src and dst are required")
|
||||
|
||||
now = iso(utcnow())
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
cur = conn.execute(
|
||||
"""
|
||||
INSERT INTO one_time_jobs
|
||||
@@ -452,7 +464,7 @@ def legacy_interval_seconds(schedule_kind: str) -> int:
|
||||
|
||||
|
||||
def delete_job(schedule_id: int) -> None:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
cur = conn.execute("DELETE FROM job_schedules WHERE id=?", (schedule_id,))
|
||||
if cur.rowcount == 0:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -461,7 +473,7 @@ def delete_job(schedule_id: int) -> None:
|
||||
def manual_run(schedule_id: int) -> dict[str, Any]:
|
||||
with scheduler_lock:
|
||||
refresh_running_jobs()
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM job_schedules WHERE id=?", (schedule_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -472,7 +484,7 @@ def manual_run(schedule_id: int) -> dict[str, Any]:
|
||||
|
||||
|
||||
def stop_job(schedule_id: int) -> dict[str, Any]:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM job_schedules WHERE id=?", (schedule_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -485,7 +497,7 @@ def stop_job(schedule_id: int) -> dict[str, Any]:
|
||||
now = iso(now_dt)
|
||||
next_run_at = compute_row_next_run_at(row, now_dt)
|
||||
snapshot = json.dumps({"finished": True, "error": "stopped", "jobid": jobid}, separators=(",", ":"))
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE job_schedules
|
||||
@@ -512,7 +524,7 @@ def stop_job(schedule_id: int) -> dict[str, Any]:
|
||||
|
||||
|
||||
def manual_run_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM one_time_jobs WHERE id=?", (job_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -523,7 +535,7 @@ def manual_run_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
|
||||
|
||||
def stop_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM one_time_jobs WHERE id=?", (job_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -534,7 +546,7 @@ def stop_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
rc_post("job/stop", {"jobid": jobid})
|
||||
now = iso(utcnow())
|
||||
snapshot = json.dumps({"finished": True, "error": "stopped", "jobid": jobid}, separators=(",", ":"))
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE one_time_jobs
|
||||
@@ -551,7 +563,7 @@ def stop_one_time_job(job_id: int) -> dict[str, Any]:
|
||||
|
||||
|
||||
def delete_one_time_job(job_id: int) -> None:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
cur = conn.execute("DELETE FROM one_time_jobs WHERE id=?", (job_id,))
|
||||
if cur.rowcount == 0:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -619,7 +631,7 @@ def start_schedule(row: sqlite3.Row, trigger: str) -> None:
|
||||
error = str(exc)
|
||||
next_run_at = compute_row_next_run_at(row, now_dt)
|
||||
snapshot = json.dumps({"finished": True, "error": error}, separators=(",", ":"))
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO job_runs
|
||||
@@ -647,7 +659,7 @@ def start_schedule(row: sqlite3.Row, trigger: str) -> None:
|
||||
|
||||
snapshot = json.dumps({"finished": False, "jobid": jobid}, separators=(",", ":"))
|
||||
next_run_at = compute_row_next_run_at(row, now_dt)
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO job_runs
|
||||
@@ -675,7 +687,7 @@ def start_schedule(row: sqlite3.Row, trigger: str) -> None:
|
||||
|
||||
|
||||
def start_one_time_job(job_id: int) -> None:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
row = conn.execute("SELECT * FROM one_time_jobs WHERE id=?", (job_id,)).fetchone()
|
||||
if row is None:
|
||||
raise ApiError(404, "job not found")
|
||||
@@ -699,7 +711,7 @@ def start_one_time_job(job_id: int) -> None:
|
||||
except Exception as exc:
|
||||
error = str(exc)
|
||||
snapshot = json.dumps({"finished": True, "error": error}, separators=(",", ":"))
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE one_time_jobs
|
||||
@@ -717,7 +729,7 @@ def start_one_time_job(job_id: int) -> None:
|
||||
return
|
||||
|
||||
snapshot = json.dumps({"finished": False, "jobid": jobid}, separators=(",", ":"))
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE one_time_jobs
|
||||
@@ -762,7 +774,7 @@ def status_with_stats(kind: str, row: sqlite3.Row, jobid: int) -> dict[str, Any]
|
||||
|
||||
|
||||
def refresh_running_jobs() -> None:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
rows = conn.execute("SELECT * FROM job_schedules WHERE current_jobid IS NOT NULL").fetchall()
|
||||
|
||||
for row in rows:
|
||||
@@ -776,7 +788,7 @@ def refresh_running_jobs() -> None:
|
||||
|
||||
|
||||
def refresh_one_time_jobs() -> None:
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
rows = conn.execute("SELECT * FROM one_time_jobs WHERE status='running' AND jobid IS NOT NULL").fetchall()
|
||||
|
||||
for row in rows:
|
||||
@@ -797,7 +809,7 @@ def apply_status(row: sqlite3.Row, status: dict[str, Any]) -> None:
|
||||
name = status_name(status)
|
||||
|
||||
if name == "running":
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE job_schedules
|
||||
@@ -821,7 +833,7 @@ def apply_status(row: sqlite3.Row, status: dict[str, Any]) -> None:
|
||||
|
||||
error = status.get("error")
|
||||
next_run_at = compute_row_next_run_at(row, now_dt)
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE job_schedules
|
||||
@@ -854,7 +866,7 @@ def apply_one_time_status(row: sqlite3.Row, status: dict[str, Any]) -> None:
|
||||
name = status_name(status)
|
||||
|
||||
if name == "running":
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE one_time_jobs
|
||||
@@ -869,7 +881,7 @@ def apply_one_time_status(row: sqlite3.Row, status: dict[str, Any]) -> None:
|
||||
return
|
||||
|
||||
error = status.get("error")
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE one_time_jobs
|
||||
@@ -887,7 +899,7 @@ def apply_one_time_status(row: sqlite3.Row, status: dict[str, Any]) -> None:
|
||||
def run_due_jobs() -> None:
|
||||
with scheduler_lock:
|
||||
now = iso(utcnow())
|
||||
with db_lock, connect() as conn:
|
||||
with db_connect() as conn:
|
||||
rows = conn.execute(
|
||||
"""
|
||||
SELECT * FROM job_schedules
|
||||
|
||||
Reference in New Issue
Block a user