fix: prevent root-owned database files when running with sudo

When start.sh runs via sudo, chown instance/ and data/ back to the
invoking user so the SQLite DB stays accessible without sudo. Also
adds a clear error message in get_connection() when the DB can't be
opened due to permissions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-03-02 09:59:41 +00:00
parent bad637591a
commit c35131462e
2 changed files with 38 additions and 21 deletions

View File

@@ -78,6 +78,15 @@ done
export INTERCEPT_HOST="$HOST"
export INTERCEPT_PORT="$PORT"
# ── Fix ownership of user data dirs when run via sudo ────────────────────────
if [[ "$(id -u)" -eq 0 && -n "${SUDO_USER:-}" ]]; then
for dir in instance data; do
if [[ -d "$SCRIPT_DIR/$dir" ]]; then
chown -R "$SUDO_USER" "$SCRIPT_DIR/$dir"
fi
done
fi
# ── Dependency check (delegate to intercept.py) ─────────────────────────────
if [[ "$CHECK_DEPS" -eq 1 ]]; then
exec "$PYTHON" intercept.py --check-deps

View File

@@ -35,10 +35,18 @@ def get_connection() -> sqlite3.Connection:
"""Get a thread-local database connection."""
if not hasattr(_local, 'connection') or _local.connection is None:
db_path = get_db_path()
_local.connection = sqlite3.connect(str(db_path), check_same_thread=False)
_local.connection.row_factory = sqlite3.Row
# Enable foreign keys
_local.connection.execute('PRAGMA foreign_keys = ON')
try:
_local.connection = sqlite3.connect(str(db_path), check_same_thread=False)
_local.connection.row_factory = sqlite3.Row
# Enable foreign keys
_local.connection.execute('PRAGMA foreign_keys = ON')
except sqlite3.OperationalError as e:
logger.error(
f"Cannot open database at {db_path}: {e}. "
f"If the file is owned by root, fix with: "
f"sudo chown -R $(whoami) {DB_DIR}"
)
raise
return _local.connection
@@ -550,12 +558,12 @@ def init_db() -> None:
INSERT OR IGNORE INTO tracked_satellites (norad_id, name, tle_line1, tle_line2, enabled, builtin)
VALUES ('25544', 'ISS (ZARYA)', NULL, NULL, 1, 1)
''')
conn.execute('''
INSERT OR IGNORE INTO tracked_satellites (norad_id, name, tle_line1, tle_line2, enabled, builtin)
VALUES ('40069', 'METEOR-M2', NULL, NULL, 1, 1)
''')
logger.info("Database initialized successfully")
conn.execute('''
INSERT OR IGNORE INTO tracked_satellites (norad_id, name, tle_line1, tle_line2, enabled, builtin)
VALUES ('40069', 'METEOR-M2', NULL, NULL, 1, 1)
''')
logger.info("Database initialized successfully")
def close_db() -> None:
@@ -2285,10 +2293,10 @@ def update_tracked_satellite(norad_id: str, enabled: bool) -> bool:
return cursor.rowcount > 0
def remove_tracked_satellite(norad_id: str) -> tuple[bool, str]:
"""Delete a tracked satellite by NORAD ID. Refuses to delete builtins."""
with get_db() as conn:
row = conn.execute(
def remove_tracked_satellite(norad_id: str) -> tuple[bool, str]:
"""Delete a tracked satellite by NORAD ID. Refuses to delete builtins."""
with get_db() as conn:
row = conn.execute(
'SELECT builtin FROM tracked_satellites WHERE norad_id = ?',
(str(norad_id),),
).fetchone()
@@ -2296,10 +2304,10 @@ def remove_tracked_satellite(norad_id: str) -> tuple[bool, str]:
return False, 'Satellite not found'
if row[0]:
return False, 'Cannot remove builtin satellite'
conn.execute(
'DELETE FROM tracked_satellites WHERE norad_id = ?',
(str(norad_id),),
)
return True, 'Removed'
conn.execute(
'DELETE FROM tracked_satellites WHERE norad_id = ?',
(str(norad_id),),
)
return True, 'Removed'