From c82c52910c2e6d94c2c5d43614644250b70512cc Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Sat, 23 Jul 2022 12:37:05 -0400 Subject: [PATCH] Reintroduce sudo feature to lock users out. Remove AW watcher because the dependency is annoying. --- README.md | 17 +++++++++++++++++ antidrift.py | 20 +++++++++++++++++--- antidrift/antidrift_watcher.py | 30 ------------------------------ antidrift/client.py | 2 +- antidrift/daemon.py | 18 +++++++++--------- antidrift/xwindow.py | 11 +++++++---- 6 files changed, 51 insertions(+), 47 deletions(-) delete mode 100644 antidrift/antidrift_watcher.py diff --git a/README.md b/README.md index d101134..6481798 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,20 @@ ExecStart=/home/felixm/dot/bin/antidrift WantedBy=default.target ``` +## Autostart via desktop file + +Create a file `antidrift.desktop` in `/etc/xdg/autostart`. + +Add the following content to the file. + +``` +[Desktop Entry] +Name=AntiDrift +Exec=/home/felixm/dot/bin/antidrift +Terminal=false +Type=Application +StartupNotify=false +``` + +Your window manager will now start antidrift automatically. + diff --git a/antidrift.py b/antidrift.py index 6be73e8..44a2478 100644 --- a/antidrift.py +++ b/antidrift.py @@ -3,6 +3,7 @@ import shutil import sys import os import signal +import subprocess from pathlib import Path import antidrift.client as client from antidrift.config import Config @@ -40,17 +41,30 @@ def check_for_xdotool(): sys.exit(1) +def main_daemon(config): + init_logging(config.daemon_log_file) + add = AntiDriftDaemon(config) + add.run() + + def main() -> None: """ Main routine that dispatches to client or daemon """ config = Config.load(os.path.expanduser("~/.config/antidrift.yaml")) check_for_xdotool() + if client.antidrift_daemon_is_running(): init_logging(config.client_log_file) client.client_mode(config) elif len(sys.argv) == 1: - init_logging(config.daemon_log_file) - add = AntiDriftDaemon(config) - add.run() + if os.geteuid() == 0: + newpid = os.fork() + if newpid == 0: + main_daemon(config) + else: + cmd = ["sudo", "/home/felixm/dot/bin/antidrift"] + subprocess.Popen(cmd) + elif len(sys.argv) == 2 and sys.argv[1] == '--daemon_user': + main_daemon(config) else: print("ad not running") diff --git a/antidrift/antidrift_watcher.py b/antidrift/antidrift_watcher.py deleted file mode 100644 index 092247c..0000000 --- a/antidrift/antidrift_watcher.py +++ /dev/null @@ -1,30 +0,0 @@ -import logging -from datetime import datetime, timedelta, timezone -from dataclasses import dataclass - -from aw_core.models import Event -from aw_client import ActivityWatchClient - - -@dataclass -class Settings: - timeout: int - poll_time: int - - -class AntidriftWatcher: - def __init__(self): - self.settings = Settings(timeout=180, poll_time=5) - self.client = ActivityWatchClient("aw-watcher-antidrift") - self.bucketname = "{}_{}".format( - self.client.client_name, self.client.client_hostname - ) - logging.info("aw-watcher-antidrift started") - eventtype = "antidrift_status" - self.client.create_bucket(self.bucketname, eventtype, queued=False) - - def ping(self, status: str): - data = {"status": status} - now = datetime.now(timezone.utc) - event = Event(timestamp=now, data=data) - inserted_event = self.client.heartbeat(self.bucketname, event, 2.0) diff --git a/antidrift/client.py b/antidrift/client.py index 8880c72..cda5cf3 100644 --- a/antidrift/client.py +++ b/antidrift/client.py @@ -8,8 +8,8 @@ import dbus.service def get_dbus_interface() -> Optional[dbus.Interface]: - bus = dbus.SessionBus() try: + bus = dbus.SessionBus() bus_object = bus.get_object("com.antidrift", "/com/antidrift") interface = dbus.Interface(bus_object, "com.antidrift") return interface diff --git a/antidrift/daemon.py b/antidrift/daemon.py index fb55145..2eeedd7 100644 --- a/antidrift/daemon.py +++ b/antidrift/daemon.py @@ -1,11 +1,11 @@ import logging import os import sys +import pwd import antidrift.xwindow as xwindow from antidrift.config import Config from gi.repository import GLib, Gio from typing import List -from antidrift.antidrift_watcher import AntidriftWatcher import dbus import dbus.service @@ -23,7 +23,14 @@ def reload_callback(m, f, o, event): class AntiDriftDaemon(dbus.service.Object): def __init__(self, config: Config): - bus = dbus.SessionBus() + + user_name = os.environ["SUDO_USER"] + user_uid = pwd.getpwnam(user_name)[2] + euid = os.geteuid() + os.seteuid(user_uid) + bus = dbus.bus.BusConnection(f"unix:path=/run/user/{user_uid}/bus") + os.seteuid(euid) + bus.request_name(BUS_NAME) bus_name = dbus.service.BusName(BUS_NAME, bus=bus) dbus.service.Object.__init__(self, bus_name, OPATH) @@ -32,7 +39,6 @@ class AntiDriftDaemon(dbus.service.Object): self.config.active_blackblocks = self.config.blackblocks self.enforce_count = 0 self.enforce_value = int(config.enforce_delay_ms / config.polling_cycle_ms) - self.antidrift_watcher = AntidriftWatcher() @dbus.service.method(dbus_interface=IFACE, in_signature="as", out_signature="s") @@ -112,21 +118,15 @@ class AntiDriftDaemon(dbus.service.Object): xwindow.notify(f"Minimize {window.name[:30]}.") window.minimize() self.enforce_count = 0 - self.antidrift_watcher.ping("blocked") elif self.enforce_count > 0 and window_is_blocked(config, True): self.enforce_count += 1 - self.antidrift_watcher.ping("blocked") elif self.enforce_count == 0 and window_is_blocked(config): self.enforce_count += 1 delay = int(config.enforce_delay_ms / 1000) xwindow.notify(f"AntiDrift will minimize in {delay}s.") - self.antidrift_watcher.ping("blocked") elif self.enforce_count > 0: xwindow.notify("We are gucci again.") self.enforce_count = 0 - self.antidrift_watcher.ping("okay") - else: - self.antidrift_watcher.ping("okay") def window_is_blocked(config: Config, silent: bool = False) -> bool: diff --git a/antidrift/xwindow.py b/antidrift/xwindow.py index 7289abc..b1d4ccc 100644 --- a/antidrift/xwindow.py +++ b/antidrift/xwindow.py @@ -1,5 +1,6 @@ import os import re +import pwd import subprocess import logging @@ -30,17 +31,19 @@ class XWindow: def quit(self): self._run(["windowquit", self.window]) + def kill(self): + self._run(["windowkill", self.window]) + def notify(message: str) -> None: """ Notify user via the Xorg notify-send command. """ logging.debug(f"{message} - [grey]notify[/grey]") - env = { - **os.environ, - "DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus" - } + env = dict(os.environ) user = env.get("SUDO_USER", None) if user is None: cmd = ["notify-send", message] else: + uid = pwd.getpwnam(user)[2] + env["DBUS_SESSION_BUS_ADDRESS"] = f"unix:path=/run/user/{uid}/bus" cmd = ["runuser", "-m", "-u", user, "notify-send", message] subprocess.run(cmd, env=env)