Skip to content

guardian_daemon

Modules:

  • config

    Configuration management for the Guardian Daemon.

  • enforcer

    Enforcement module for guardian-daemon.

  • ipc

    IPC server for admin commands of the Guardian Daemon.

  • logging

    Guardian logging setup module.

  • models

    SQLAlchemy models for guardian_daemon.

  • net_client

    API/WebSocket hub client for guardian-daemon.

  • policy

    Policy loader for guardian-daemon.

  • sessions

    Session tracking for guardian-daemon.

  • storage

    Central SQLAlchemy interface for guardian-daemon.

  • systemd_manager

    Systemd manager for guardian-daemon.

  • user_manager

    User manager for guardian-daemon.

config

Configuration management for the Guardian Daemon.

Classes:

  • Config

    Handles loading, merging, and validating the daemon's configuration.

  • ConfigError

    Custom exception for configuration errors.

Config

Config(config_path=None)

Handles loading, merging, and validating the daemon's configuration.

Configuration Loading Priority (highest to lowest): 1. Explicitly provided path via config_path parameter 2. Environment variable GUARDIAN_DAEMON_CONFIG 3. System-wide config at /etc/guardian/daemon/config.yaml 4. Local config (development) in project directory

The configuration system uses a two-layer approach: - Default configuration (always loaded from default-config.yaml) - User configuration (merged on top of defaults)

This ensures that all required keys exist even if the user config is minimal or missing.

Example

config = Config("/etc/guardian/daemon/config.yaml") db_path = config.get("db_path") users = config["users"]

Parameters:

  • config_path

    Optional explicit path to configuration file. If not provided, searches in priority order: 1. GUARDIAN_DAEMON_CONFIG env var 2. /etc/guardian/daemon/config.yaml 3. Local config.yaml (development)

Raises:

Methods:

  • get

    Gets a configuration value.

get

get(key, default=None)

Gets a configuration value.

Parameters:

  • key

    Configuration key to retrieve

  • default

    Default value if key not found

Returns:

  • The configuration value or default

ConfigError

Bases: Exception

Custom exception for configuration errors.

enforcer

Enforcement module for guardian-daemon. Checks quota and curfew, enforces limits by terminating sessions and blocking logins.

Classes:

  • Enforcer

    Enforcement logic for quota and curfew. Handles session termination and user notifications.

Enforcer

Enforcer(policy: Policy, tracker: SessionTracker)

Enforcement logic for quota and curfew. Handles session termination and user notifications.

Methods:

  • enforce_user

    Checks quota and curfew for a user and enforces actions if necessary.

  • handle_grace_period

    Handles the grace period by notifying the user every minute until time is up.

  • notify_user

    Sends a desktop notification to all matching agents of the given user (via D-Bus).

  • terminate_session

    Terminates all running desktop sessions of the user (via systemd loginctl).

enforce_user async

enforce_user(username)

Checks quota and curfew for a user and enforces actions if necessary.

Uses intelligent throttling to avoid redundant enforcement checks: - Skips check if user is already in grace period - Skips check if last check was recent and time hasn't changed much

handle_grace_period async

handle_grace_period(username)

Handles the grace period by notifying the user every minute until time is up.

notify_user async

notify_user(username, message, category='info')

Sends a desktop notification to all matching agents of the given user (via D-Bus). Implements a debounce mechanism to avoid sending too many similar notifications.

terminate_session async

terminate_session(username)

Terminates all running desktop sessions of the user (via systemd loginctl). Only sessions with a desktop environment (not systemd-user/service) are targeted.

ipc

IPC server for admin commands of the Guardian Daemon.

Classes:

GuardianIPCServer

GuardianIPCServer(
    config, tracker: SessionTracker, policy: Policy
)

IPC server for admin commands of the Guardian Daemon. Provides a socket interface for status and control commands.

Security: Enforces request size limits and proper authentication.

Parameters:

  • config

    (dict) –

    Configuration data

  • tracker

    (SessionTracker) –

    The main session tracker instance.

  • policy

    (Policy) –

    The main policy instance.

Methods:

close

close()

Closes the IPC socket and removes the socket file.

handle_add_user

handle_add_user(username)

Add a new user to the database with default settings.

Parameters:

  • username
    (str) –

    Username to add

handle_connection async

handle_connection(reader, writer)

Handles an incoming client connection. Enforces authentication, request size limits, and rate limiting.

handle_describe_commands

handle_describe_commands(_)

Returns a description of all available IPC commands and their parameters as JSON. This is used by the CLI for automatic command discovery.

handle_get_curfew

handle_get_curfew(kid)

Returns the current curfew times of a kid.

Parameters:

  • kid
    (str) –

    Username

handle_get_quota async

handle_get_quota(kid)

Returns the current quota status of a kid. All time values are in minutes in the returned JSON.

Parameters:

  • kid
    (str) –

    Username

Returns:

  • str

    JSON string with quota information (used, limit, remaining in minutes)

handle_list_kids

handle_list_kids(_)

Returns the list of all kids (users).

handle_list_timers

handle_list_timers(_)

Lists all active Guardian timers.

handle_reload_timers

handle_reload_timers(_)

Reloads the timer configuration.

handle_reset_quota async

handle_reset_quota(_)

Resets the daily quota for all users (deletes sessions since last reset).

handle_setup_user

handle_setup_user(username)

Sets up a user with Guardian (adds to groups, creates systemd services, etc).

Parameters:

  • username
    (str) –

    Username of the user to set up

handle_sync_users_from_config

handle_sync_users_from_config(_)

Reset user settings in the database to match the configuration file. This also imports new users from the config to the database.

handle_unlock_all async

handle_unlock_all(_)

Emergency unlock all managed user accounts.

Returns:

  • JSON response with count of unlocked users and details

handle_unlock_user async

handle_unlock_user(username)

Unlock a specific user's account to allow login.

Parameters:

  • username

    Username to unlock

Returns:

  • JSON response with success status or error message

handle_update_user

handle_update_user(args)

Update a specific setting for a user.

Parameters:

  • args
    (str) –

    Format should be "username setting_key setting_value"

start async

start()

Starts the IPC server.

logging

Guardian logging setup module. Configures log level, format, and target based on the application config.

Functions:

  • get_logger

    Returns a configured structlog logger instance.

  • setup_logging

    Sets up structlog and stdlib logging according to the provided config.

get_logger

get_logger(name)

Returns a configured structlog logger instance.

setup_logging

setup_logging(config)

Sets up structlog and stdlib logging according to the provided config. This function should only be called once at application startup.

models

SQLAlchemy models for guardian_daemon.

Key design decisions: - Session.id is an autoincrement primary key (not using logind session_id as PK) - logind_session_id is stored but is transient and can be reused by the system - Unique constraint on (username, date, start_time) to prevent duplicate sessions

Classes:

  • Base

    Base class for all models.

  • History

    Historical session summaries by user and date.

  • Meta

    Metadata key-value storage.

  • Session

    Represents a user session.

  • UserSettings

    User settings and configuration.

Base

Bases: DeclarativeBase

Base class for all models.

History

Bases: Base

Historical session summaries by user and date.

Meta

Bases: Base

Metadata key-value storage.

Session

Bases: Base

Represents a user session.

Note: The id is an autoincrement value, NOT the logind session ID. The logind_session_id is stored separately as it's transient and can be reused by the system for different users on different days.

UserSettings

Bases: Base

User settings and configuration.

net_client

API/WebSocket hub client for guardian-daemon.

NOTE: This module is not yet implemented. Only stub placeholder exists. The network client is planned for Phase 1 of the project roadmap.

Planned functionality: - HTTP client for guardian-hub API - WebSocket connection for real-time updates - Policy synchronization from hub - Usage data upload to hub - Heartbeat mechanism - Offline queue for when hub is unavailable

policy

Policy loader for guardian-daemon. Loads and validates settings from a YAML configuration file.

Classes:

Policy

Policy(
    config_path: Optional[str] = None,
    db_path: Optional[str] = None,
)

Parameters:

  • config_path

    (str, default: None ) –

    Path to the YAML configuration file.

  • db_path

    (str, default: None ) –

    Path to the SQLite database.

Methods:

  • add_user

    Adds a user to the policy with default settings.

  • get_all_usernames

    Returns a list of all usernames in the policy.

  • get_default

    Return a default value from the policy.

  • get_grace_time

    Returns the grace time in minutes for a user.

  • get_monitored_users

    Get list of all monitored users (excluding those with monitored: False).

  • get_timezone

    Returns the configured timezone or the default timezone.

  • get_user_curfew

    Get curfew settings for a user.

  • get_user_policy

    Return the policy settings for a specific user.

  • get_user_quota

    Get daily and weekly quota for a user.

  • has_curfew

    Check if a user has curfew settings.

  • has_quota

    Check if a user has quota settings and is not quota_exempt.

  • reload

    Reload the policy configuration and synchronize with the database.

add_user

add_user(username: str) -> bool

Adds a user to the policy with default settings.

Parameters:

  • username
    (str) –

    Username to add

Returns:

  • bool ( bool ) –

    True if the user was added, False otherwise

get_all_usernames

get_all_usernames() -> list

Returns a list of all usernames in the policy.

Returns:

  • list ( list ) –

    List of usernames

get_default

get_default(key: str) -> Any

Return a default value from the policy.

Parameters:

  • key
    (str) –

    Name of the default key

Returns:

  • Any ( Any ) –

    The default value or None

get_grace_time

get_grace_time(username: str) -> int

Returns the grace time in minutes for a user. This is the time allowed after quota is exhausted before terminating the session.

Parameters:

  • username
    (str) –

    Username to get grace time for

Returns:

  • int ( int ) –

    Grace time in minutes (defaults to 5)

get_monitored_users

get_monitored_users() -> list[str]

Get list of all monitored users (excluding those with monitored: False).

get_timezone

get_timezone() -> str

Returns the configured timezone or the default timezone.

Returns:

  • str ( str ) –

    Timezone string

get_user_curfew

get_user_curfew(
    username: str, is_weekend: bool
) -> Optional[dict[str, str]]

Get curfew settings for a user.

get_user_policy

get_user_policy(username: str) -> Optional[Dict[str, Any]]

Return the policy settings for a specific user.

Parameters:

  • username
    (str) –

    Username

Returns:

  • Optional[Dict[str, Any]]

    dict | None: The user's settings or None if not present.

get_user_quota

get_user_quota(username: str) -> tuple[int, int]

Get daily and weekly quota for a user.

has_curfew

has_curfew(username: str) -> bool

Check if a user has curfew settings.

has_quota

has_quota(username: str) -> bool

Check if a user has quota settings and is not quota_exempt.

reload

reload()

Reload the policy configuration and synchronize with the database.

sessions

Session tracking for guardian-daemon. Monitors logins/logouts via systemd-logind (DBus), measures usage time and checks quota/curfew. Stores data in SQLite.

Classes:

Functions:

  • get_boot_id

    Get the system boot ID to make session IDs unique across reboots.

  • make_unique_session_id

    Create a unique session ID that persists across daemon restarts but changes across reboots.

GuardianDaemonInterface

GuardianDaemonInterface(session_tracker)

Bases: ServiceInterface

Methods:

  • LockEvent

    Receives lock/unlock events from agents and forwards to SessionTracker.

LockEvent async

LockEvent(
    session_id: s, username: s, locked: b, timestamp: d
)

Receives lock/unlock events from agents and forwards to SessionTracker.

SessionTracker

SessionTracker(
    policy: Policy, config: dict, user_manager: UserManager
)

Monitors and stores user sessions, checks quota and curfew. Connects to systemd-logind via DBus.

Parameters:

  • policy

    (Policy) –

    Policy instance

  • config

    (dict) –

    Parsed configuration

  • user_manager

    (UserManager) –

    User manager instance for setting up user sessions

Methods:

  • check_curfew

    Check if a user is allowed to log in at the current time based on curfew settings.

  • check_daily_reset_on_startup

    Check if we need to perform a daily reset on daemon startup or system wake.

  • check_quota

    Check if a user is within their quota limits.

  • check_usage_summarize

    Check if we need to summarize usage and add to history.

  • discover_agent_names_for_user

    Scans the D-Bus for all available agent service names for a given user

  • get_active_users

    Return a list of currently active usernames.

  • get_agent_names_for_user

    Return the cached list of D-Bus agent names for a user, or empty list if not found.

  • get_agent_paths_for_user

    Returns a list of D-Bus object paths for agents belonging to the given user.

  • get_remaining_time

    Returns the remaining allowed time for the given user today.

  • get_total_time

    Returns the total allowed time (in minutes) for the given user today.

  • get_user_sessions

    Returns a list of active session details for the given user.

  • handle_login

    Register a new session on login for child accounts.

  • handle_logout

    End a session on logout and save it in the database for child accounts.

  • pause_user_time

    Pause time tracking for a user when a lock event is received for an unknown session.

  • perform_daily_reset

    Perform daily reset: summarize sessions, create history entries,

  • periodic_session_update

    Periodically update all active sessions in the database with current duration.

  • receive_lock_event

    Called via D-Bus/IPC from agent to record lock/unlock events for a session.

  • refresh_agent_name_mapping

    Refresh the mapping of usernames to their current D-Bus agent names using discover_agent_names_for_user().

  • run

    Start session tracking, connect to systemd-logind via DBus, and listen for KDE lock events.

check_curfew async

check_curfew(
    username: str, current_time, is_weekend: bool
) -> bool

Check if a user is allowed to log in at the current time based on curfew settings.

Parameters:

  • username
    (str) –

    Username

  • current_time

    Current time to check (datetime.time)

  • is_weekend
    (bool) –

    Whether it's a weekend day

Returns:

  • bool ( bool ) –

    True if allowed, False if curfew is in effect

check_daily_reset_on_startup async

check_daily_reset_on_startup()

Check if we need to perform a daily reset on daemon startup or system wake. This is based on the date comparison between today and the last reset date.

check_quota async

check_quota(username: str) -> bool

Check if a user is within their quota limits.

Parameters:

  • username
    (str) –

    Username

Returns:

  • bool ( bool ) –

    True if within quota, False if exceeded

check_usage_summarize async

check_usage_summarize(
    username, used_time, quota_reached=False
)

Check if we need to summarize usage and add to history. This should be called when: 1. The user reaches their daily quota 2. The user logs out and it's their last session of the day

Parameters:

  • username
    (str) –

    Username to check

  • used_time
    (float) –

    Used time in seconds

  • quota_reached
    (bool, default: False ) –

    Whether the quota was reached

discover_agent_names_for_user async

discover_agent_names_for_user(username: str)

Scans the D-Bus for all available agent service names for a given user and updates the internal map.

get_active_users async

get_active_users() -> list

Return a list of currently active usernames.

get_agent_names_for_user

get_agent_names_for_user(username: str) -> list

Return the cached list of D-Bus agent names for a user, or empty list if not found. Converts from set to list if necessary.

get_agent_paths_for_user

get_agent_paths_for_user(username: str)

Returns a list of D-Bus object paths for agents belonging to the given user. This should be tracked in active_sessions as 'agent_path' if available, otherwise default to /org/guardian/Agent or numbered agents.

get_remaining_time async

get_remaining_time(username: str) -> float

Returns the remaining allowed time for the given user today. All calculations use minutes as the base unit to match the API contract.

Returns:

  • float ( float ) –

    Remaining screen time in minutes

get_total_time async

get_total_time(username: str) -> float

Returns the total allowed time (in minutes) for the given user today.

Returns:

  • float ( float ) –

    Total allowed screen time in minutes

get_user_sessions

get_user_sessions(username: str)

Returns a list of active session details for the given user. Each item is a dict with session_id, service, desktop, start_time, etc.

handle_login async

handle_login(session_id, uid, username, props)

Register a new session on login for child accounts. Skips systemd-user sessions. Also ensure user account is set up: PAM time rules, systemd user service, and agent.

Parameters:

  • session_id
    (str) –

    Session ID

  • uid
    (int) –

    User ID

  • username
    (str) –

    Username

handle_logout async

handle_logout(session_id)

End a session on logout and save it in the database for child accounts.

Parameters:

  • session_id
    (str) –

    Logind session ID (will be mapped to unique session ID)

pause_user_time

pause_user_time(username, timestamp)

Pause time tracking for a user when a lock event is received for an unknown session.

perform_daily_reset async

perform_daily_reset(force=False)

Perform daily reset: summarize sessions, create history entries, clean up sessions table, and reset quotas.

This should be called when: 1. The system is first booted/unlocked for the day (normal reset) 2. The daily quota is reached 3. The configured reset_time is reached 4. Manually via reset-quota command (force=True)

When force=True, resets today's quota to zero by archiving current sessions.

periodic_session_update async

periodic_session_update(interval: int = 60)

Periodically update all active sessions in the database with current duration. This is critical for preserving session time across daemon restarts. Includes robust D-Bus connection handling with automatic reconnection.

receive_lock_event async

receive_lock_event(
    session_id: str,
    username: str,
    locked: bool,
    timestamp: float,
)

Called via D-Bus/IPC from agent to record lock/unlock events for a session. Also updates session progress in the database.

Parameters:

  • session_id
    (str) –

    Logind session ID from the agent (will be mapped to unique ID)

refresh_agent_name_mapping async

refresh_agent_name_mapping()

Refresh the mapping of usernames to their current D-Bus agent names using discover_agent_names_for_user(). Stores the mapping in self.agent_name_map: {username: {dbus_name, ...}}

run async

run()

Start session tracking, connect to systemd-logind via DBus, and listen for KDE lock events. Also checks for already logged-in child sessions on startup. Periodically updates session progress in the database.

get_boot_id

get_boot_id() -> str

Get the system boot ID to make session IDs unique across reboots.

Returns:

  • str ( str ) –

    Boot ID or empty string if not available

make_unique_session_id

make_unique_session_id(
    logind_session_id: str, boot_id: str = None
) -> str

Create a unique session ID that persists across daemon restarts but changes across reboots.

Parameters:

  • logind_session_id

    (str) –

    The session ID from logind (e.g., "4", "5")

  • boot_id

    (str, default: None ) –

    Optional boot ID (will fetch if not provided)

Returns:

  • str ( str ) –

    Unique session ID in format "bootid_sessionid" or just sessionid if no boot_id

storage

Central SQLAlchemy interface for guardian-daemon. Provides functions for session handling using SQLAlchemy ORM.

Classes:

  • Storage

    Central SQLAlchemy interface for session and settings storage in Guardian Daemon.

Storage

Storage(db_path: str)

Central SQLAlchemy interface for session and settings storage in Guardian Daemon.

Key design changes: - Uses SQLAlchemy ORM instead of raw SQL - Session.id is autoincrement (not using logind session_id as primary key) - logind_session_id is stored separately as it's transient - Date field tracks which day the session belongs to

Parameters:

  • db_path

    (str) –

    Path to SQLite database.

Methods:

add_session async

add_session(
    session_id: str,
    username: str,
    uid: int,
    start_time: float,
    end_time: float,
    duration_seconds: float,
    desktop: Optional[str] = None,
    service: Optional[str] = None,
)

Adds a new session to the database.

Parameters:

  • session_id
    (str) –

    Logind session ID (transient identifier)

  • username
    (str) –

    Username

  • uid
    (int) –

    User ID

  • start_time
    (float) –

    Start time (EPOCH)

  • end_time
    (float) –

    End time (EPOCH, 0 if still active)

  • duration_seconds
    (float) –

    Session duration in seconds

  • desktop
    (str, default: None ) –

    Desktop environment

  • service
    (str, default: None ) –

    Service (e.g. sddm)

add_session_time async

add_session_time(
    username: str, start_time: datetime, end_time: datetime
)

Add a usage time entry for a user.

Parameters:

  • username
    (str) –

    Username

  • start_time
    (datetime) –

    Start time

  • end_time
    (datetime) –

    End time

clean_old_sessions

clean_old_sessions(username: str, before_date: str = None)

Remove old session records for a user after they've been summarized to history.

Parameters:

  • username
    (str) –

    Username to clean sessions for

  • before_date
    (str, default: None ) –

    Remove sessions before this date (YYYY-MM-DD) If not provided, removes all sessions

cleanup_stale_sessions async

cleanup_stale_sessions(max_age_hours: int)

Remove sessions older than the specified age.

Parameters:

  • max_age_hours
    (int) –

    Maximum age in hours to keep sessions

close

close()

Close the database connection.

delete_sessions_since

delete_sessions_since(since: float)

Delete all sessions from the database since the given timestamp.

Parameters:

  • since
    (float) –

    Start timestamp (Unix timestamp)

end_session async

end_session(
    username: str, session_id: str, end_time: datetime
)

End a session for a user.

Parameters:

  • username
    (str) –

    Username

  • session_id
    (str) –

    Logind session ID

  • end_time
    (datetime) –

    End time

get_active_session async

get_active_session(username: str, session_id: str)

Get an active session for a user.

Parameters:

  • username
    (str) –

    Username

  • session_id
    (str) –

    Logind session ID

Returns:

  • tuple

    Session data or None if not found

get_all_active_sessions async

get_all_active_sessions()

Get all currently active sessions.

Returns:

  • list

    List of active sessions

get_all_usernames

get_all_usernames() -> list

Return all usernames (except 'default') from the database.

Returns:

  • list ( list ) –

    List of usernames

get_daily_usage async

get_daily_usage(username: str, date: date)

Get total usage time for a user on a given date.

Parameters:

  • username
    (str) –

    Username

  • date
    (date) –

    Date to check

Returns:

  • int

    Total usage time in seconds

get_history

get_history(
    username: str,
    start_date: str = None,
    end_date: str = None,
)

Retrieve history entries for a user within a date range.

Parameters:

  • username
    (str) –

    Username to get history for

  • start_date
    (str, default: None ) –

    Start date in YYYY-MM-DD format

  • end_date
    (str, default: None ) –

    End date in YYYY-MM-DD format

Returns:

  • list

    List of history entries as dictionaries

get_last_reset_date

get_last_reset_date() -> str

Retrieve the last daily reset date from the database.

Returns:

  • str ( str ) –

    Date in YYYY-MM-DD format

get_last_reset_timestamp

get_last_reset_timestamp() -> Optional[float]

Retrieve the last daily reset timestamp from the database.

Returns:

  • Optional[float]

    float | None: EPOCH timestamp of last reset or None

get_open_sessions

get_open_sessions() -> list

Get all currently open sessions from the database.

Returns:

  • list ( list ) –

    List of tuples (logind_session_id, username, uid, start_time, duration, desktop, service)

get_sessions_count_since

get_sessions_count_since(timestamp: float) -> int

Get count of sessions since a given timestamp.

Parameters:

  • timestamp
    (float) –

    Unix timestamp

Returns:

  • int ( int ) –

    Count of sessions

get_sessions_for_user

get_sessions_for_user(
    username: str, since: Optional[float] = None
) -> list

Retrieve all sessions for a user, optionally since a specific time.

Parameters:

  • username
    (str) –

    Username

  • since
    (float, default: None ) –

    Start time (Unix timestamp)

Returns:

  • list ( list ) –

    List of sessions as tuples

get_usage_in_date_range async

get_usage_in_date_range(
    username: str, start_date: datetime, end_date: datetime
)

Get total usage time for a user between two dates.

Parameters:

  • username
    (str) –

    Username

  • start_date
    (datetime) –

    Start date

  • end_date
    (datetime) –

    End date

Returns:

  • int

    Total usage time in seconds

get_user_settings

get_user_settings(username: str) -> Optional[dict]

Retrieve user settings from the database for the given username.

Parameters:

  • username
    (str) –

    Username

Returns:

  • Optional[dict]

    dict | None: User settings or None

get_weekly_usage async

get_weekly_usage(username: str, date: date)

Get total usage time for a user in the week containing the given date.

Parameters:

  • username
    (str) –

    Username

  • date
    (date) –

    Date within the week to check

Returns:

  • int

    Total usage time in seconds

logind_to_epoch staticmethod

logind_to_epoch(logind_timestamp: int) -> float

Convert logind timestamp (microseconds since boot) to EPOCH timestamp.

Parameters:

  • logind_timestamp
    (int) –

    Microseconds since boot

Returns:

  • float ( float ) –

    EPOCH timestamp

save_history_entry

save_history_entry(summary: dict)

Save a history entry from a session summary.

Parameters:

  • summary
    (dict) –

    Session summary data

set_last_reset_date

set_last_reset_date(date_str: str)

Store the last daily reset date in the database.

Parameters:

  • date_str
    (str) –

    Date in YYYY-MM-DD format

set_last_reset_timestamp

set_last_reset_timestamp(ts: float)

Store the last daily reset timestamp in the database.

Parameters:

  • ts
    (float) –

    EPOCH timestamp

set_user_settings

set_user_settings(username: str, settings: dict)

Store user settings in the database for the given username.

Parameters:

  • username
    (str) –

    Username

  • settings
    (dict) –

    Settings dictionary

summarize_user_sessions

summarize_user_sessions(username: str, date: str = None)

Summarize all sessions for a user on a given date and create a history entry. If date is not provided, summarize sessions from the most recent day.

Parameters:

  • username
    (str) –

    Username to summarize sessions for

  • date
    (str, default: None ) –

    Date in YYYY-MM-DD format, defaults to today

Returns:

  • dict

    Summary of session data

sync_config_to_db

sync_config_to_db(config: dict)

Synchronize configuration data to the database. Merges user settings with defaults to ensure complete configuration.

Parameters:

  • config
    (dict) –

    Configuration data

update_session_logout

update_session_logout(
    session_id: str,
    end_time: float,
    duration_seconds: float,
)

Update session entry with logout time and duration.

Parameters:

  • session_id
    (str) –

    Logind session ID to update

  • end_time
    (float) –

    End time in EPOCH seconds

  • duration_seconds
    (float) –

    Session duration in seconds

update_session_progress

update_session_progress(
    session_id: str, duration_seconds: float
)

Periodically update session entry with current duration (while session is active). This is critical for preserving session time across daemon restarts.

Parameters:

  • session_id
    (str) –

    The logind session ID to update

  • duration_seconds
    (float) –

    Duration in seconds

systemd_manager

Systemd manager for guardian-daemon. Creates and manages systemd timers/units for daily reset and curfew.

Classes:

  • SystemdManager

    Manages systemd timers and units for daily reset and curfew enforcement.

SystemdManager

SystemdManager()

Manages systemd timers and units for daily reset and curfew enforcement.

Methods:

create_curfew_timer

create_curfew_timer(start_time='22:00', end_time='06:00')

Create a systemd timer and service unit for curfew enforcement.

create_daily_reset_timer

create_daily_reset_timer(reset_time='03:00')

Create a systemd timer and corresponding service unit for the daily quota reset.

reload_systemd async

reload_systemd()

Reload systemd units to apply changes.

remove_timer_and_service

remove_timer_and_service(timer_name)

Remove a systemd timer and service unit by name.

user_manager

User manager for guardian-daemon. Manages login time windows for children via /etc/security/time.conf and handles user-specific systemd services.

Classes:

  • SetupError

    Exception raised when critical setup operations fail.

  • UserManager

    Manages user-specific configurations, PAM time rules, and systemd services.

SetupError

Bases: Exception

Exception raised when critical setup operations fail.

UserManager

UserManager(
    policy: Policy = None, tracker: SessionTracker = None
)

Manages user-specific configurations, PAM time rules, and systemd services.

This class is responsible for: - Managing the 'kids' group and user memberships - Writing and maintaining PAM time.conf rules for curfews - Setting up user-specific systemd services (guardian-agent) - Configuring D-Bus policies for agent communication - Ensuring PAM modules are properly configured

The UserManager works closely with the Policy class to enforce time-based access controls and user quotas.

Security: All methods that accept usernames validate them against path traversal and use canonical system paths via pwd.getpwnam().

Parameters:

  • policy

    (Policy, default: None ) –

    The Policy instance containing user rules and configurations

  • tracker

    (SessionTracker, default: None ) –

    The SessionTracker instance (optional, can be set later)

Note

The tracker can be set later using set_tracker() to avoid circular dependencies during initialization.

Methods:

  • check_if_locked

    Check if a user account is currently locked by examining password status.

  • ensure_kids_group

    Ensure the 'kids' group exists and all managed users are members of it.

  • ensure_pam_time_module

    Ensures pam_time.so is active using two complementary approaches:

  • ensure_systemd_user_service

    Ensure that systemd user services are set up for the given user without enabling lingering.

  • lock_user_account

    Temporarily lock a user account to prevent login.

  • remove_time_rules

    Remove time rules set by guardian-daemon from /etc/security/time.conf.

  • set_tracker

    Set the session tracker after initialization to resolve circular dependencies.

  • setup_dbus_policy

    Creates /etc/dbus-1/system.d/guardian.conf to allow managed users access to org.guardian.Daemon.

  • setup_user_login

    Comprehensive setup for a user upon login.

  • setup_user_service

    Sets up the guardian_agent.service for the given user's systemd.

  • sync_account_locks

    Synchronize user account locks with their current quota status.

  • unlock_all_managed_users

    Emergency function to unlock all managed user accounts.

  • unlock_user_account

    Unlock a previously locked user account.

  • update_policy

    Update the policy instance and re-evaluate rules.

  • user_exists

    Check if a user exists on the system.

  • validate_username

    Validate username format to prevent path traversal and injection attacks.

  • write_time_rules

    Updates the time rules for all children according to the policy in /etc/security/time.conf,

check_if_locked

check_if_locked(username: str) -> bool

Check if a user account is currently locked by examining password status.

Parameters:

  • username
    (str) –

    The username to check

Returns:

  • bool ( bool ) –

    True if account is locked, False otherwise

ensure_kids_group

ensure_kids_group()

Ensure the 'kids' group exists and all managed users are members of it. Also ensures all managed users are in the 'users' group to access agent files.

ensure_pam_time_module

ensure_pam_time_module()

Ensures pam_time.so is active using two complementary approaches:

  1. Creates a custom authselect profile with pam_time.so in the system-auth stack (applies to all PAM services that include system-auth)

  2. Directly modifies /etc/pam.d/sddm to explicitly include pam_time.so before the system-account include (ensuring SDDM enforces time restrictions even if authselect updates the system files)

This dual approach ensures maximum compatibility and resilience against system updates or configuration changes.

ensure_systemd_user_service

ensure_systemd_user_service(username)

Ensure that systemd user services are set up for the given user without enabling lingering. Only starts the service if the user is actively logged in with a session.

Security: Validates username and uses pwd.getpwnam() to prevent path traversal.

lock_user_account

lock_user_account(username: str) -> bool

Temporarily lock a user account to prevent login. Uses usermod -L to disable password authentication.

Parameters:

  • username
    (str) –

    The username to lock

Returns:

  • bool ( bool ) –

    True if successful, False otherwise

remove_time_rules

remove_time_rules()

Remove time rules set by guardian-daemon from /etc/security/time.conf.

set_tracker

set_tracker(tracker: SessionTracker)

Set the session tracker after initialization to resolve circular dependencies.

setup_dbus_policy

setup_dbus_policy()

Creates /etc/dbus-1/system.d/guardian.conf to allow managed users access to org.guardian.Daemon. Both 'kids' and 'users' groups are given permissions to support transition periods.

setup_user_login

setup_user_login(username: str) -> bool

Comprehensive setup for a user upon login. Ensures group membership, PAM rules, and systemd service are correctly configured.

setup_user_service

setup_user_service(username: str)

Sets up the guardian_agent.service for the given user's systemd. Updates the service file if its checksum has changed. Ensures correct directory structure and permissions.

Security: Validates username and uses pwd.getpwnam() to prevent path traversal.

sync_account_locks async

sync_account_locks()

Synchronize user account locks with their current quota status. Lock users who are out of time and within monitoring hours, unlock those who have time or are outside monitoring hours.

This should be called: - On daemon startup (to restore consistent state) - During quota reset - When curfew windows change

unlock_all_managed_users

unlock_all_managed_users() -> int

Emergency function to unlock all managed user accounts. Used for manual recovery by administrators.

Returns:

  • int ( int ) –

    Number of users successfully unlocked

unlock_user_account

unlock_user_account(username: str) -> bool

Unlock a previously locked user account. Uses usermod -U to re-enable password authentication.

Parameters:

  • username
    (str) –

    The username to unlock

Returns:

  • bool ( bool ) –

    True if successful, False otherwise

update_policy

update_policy(policy: Policy)

Update the policy instance and re-evaluate rules.

user_exists

user_exists(username)

Check if a user exists on the system.

Parameters:

  • username

    The username to check

Returns:

  • bool

    True if user exists, False otherwise

validate_username staticmethod

validate_username(username: str) -> bool

Validate username format to prevent path traversal and injection attacks.

Parameters:

  • username
    (str) –

    The username to validate

Returns:

  • bool ( bool ) –

    True if username is valid, False otherwise

write_time_rules

write_time_rules()

Updates the time rules for all children according to the policy in /etc/security/time.conf, without overwriting foreign rules.

This method: 1. First checks if the file is excessively large and needs cleanup 2. Compares existing content with what we need to write 3. Only writes if content needs updating