import os
import sys
from testlib import Error
HELPERS_DIR = os.path.dirname(__file__)
sys.path.append(HELPERS_DIR)
from password import Password
from step_logger import log_step
from steps import ACCOUNTS
USERS_SERVICE = "org.fedoraproject.Anaconda.Modules.Users"
USERS_INTERFACE = USERS_SERVICE
USERS_OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Users"
ACCOUNTS_SCREEN = ACCOUNTS
CREATE_ACCOUNT_ID_PREFIX = f"{ACCOUNTS_SCREEN}-create-account"
ROOT_ACCOUNT_ID_PREFIX = f"{ACCOUNTS_SCREEN}-root-account"
ACCOUNTS_READONLY_USERS = "[data-testid='accounts-users-readonly']"
ACCOUNTS_READONLY_USER_ROW = "accounts-users-readonly-user"
def override_user_interface_conf_keys(test, **kwargs):
"""Patch `[User Interface]` boolean keys in `/run/anaconda/anaconda.conf` (single restore)."""
conf = '/run/anaconda/anaconda.conf'
test.restore_file(conf)
for key, value in kwargs.items():
text = value if isinstance(value, str) else str(value)
if "\n" in text:
lines = [line.strip() for line in text.strip().splitlines() if line.strip()]
sed_text = "\\\n".join([f"{key} =", *[f" {line}" for line in lines]])
test.machine.execute(f"sed -i '/^{key} =/,/^$/c\\\n{sed_text}' {conf}")
else:
test.machine.execute(f"sed -i '/^{key} =/c\\{key} = {text}' {conf}")
class UsersDBus():
def __init__(self, machine):
self.machine = machine
self._bus_address = self.machine.execute("cat /run/anaconda/bus.address")
def dbus_get_users(self):
return self.machine.execute(
f'busctl --address="{self._bus_address}" \
get-property \
{USERS_SERVICE} \
{USERS_OBJECT_PATH} \
{USERS_INTERFACE} Users'
)
def dbus_clear_users(self):
self.machine.execute(f'busctl --address="{self._bus_address}" \
set-property \
{USERS_SERVICE} \
{USERS_OBJECT_PATH} \
{USERS_INTERFACE} Users aa{{sv}} 0')
def dbus_get_root_locked(self):
ret = self.machine.execute(f'busctl --address="{self._bus_address}" \
get-property \
{USERS_SERVICE} \
{USERS_OBJECT_PATH} \
{USERS_INTERFACE} IsRootAccountLocked')
return ret.split()[1].strip() == "true"
def dbus_set_root_locked(self, locked):
self.machine.execute(f'busctl --address="{self._bus_address}" \
set-property \
{USERS_SERVICE} \
{USERS_OBJECT_PATH} \
{USERS_INTERFACE} IsRootAccountLocked b {"true" if locked else "false"}')
def dbus_get_is_root_password_set(self):
ret = self.machine.execute(f'busctl --address="{self._bus_address}" \
get-property \
{USERS_SERVICE} \
{USERS_OBJECT_PATH} \
{USERS_INTERFACE} IsRootPasswordSet')
return ret.split()[1].strip() == "true"
class Users(UsersDBus):
def __init__(self, browser, machine):
self.browser = browser
UsersDBus.__init__(self, machine)
@log_step(snapshot_before=True)
def set_user_name(self, user_name, append=False, value_check=True):
sel = f"#{ACCOUNTS_SCREEN}-create-account-user-name"
self.browser.set_input_text(sel, user_name, append=append, value_check=value_check)
@log_step(snapshot_before=True)
def check_user_name(self, user_name):
sel = f"#{ACCOUNTS_SCREEN}-create-account-user-name"
self.browser.wait_val(sel, user_name)
@log_step(snapshot_before=True)
def set_full_name(self, full_name, append=False, value_check=True):
sel = f"#{ACCOUNTS_SCREEN}-create-account-full-name"
self.browser.set_input_text(sel, full_name, append=append, value_check=value_check)
@log_step(snapshot_before=True)
def check_full_name(self, full_name):
sel = f"#{ACCOUNTS_SCREEN}-create-account-full-name"
self.browser.wait_val(sel, full_name)
@log_step(snapshot_before=True)
def enable_root_account(self, enable):
sel = f"#{ACCOUNTS_SCREEN}-root-account-enable-root-account"
try:
self.browser.set_checked(sel, enable)
self.browser.wait_visible(f"{sel}:checked" if enable else f"{sel}:not(:checked)")
except Error:
self.browser.set_checked(sel, enable)
self.browser.wait_visible(f"{sel}:checked" if enable else f"{sel}:not(:checked)")
if enable:
p = Password(self.browser, ROOT_ACCOUNT_ID_PREFIX)
p.check_pw_focused()
@log_step(snapshot_before=True)
def enable_user_account(self, enable):
sel = f"#{ACCOUNTS_SCREEN}-create-account-set-user-account"
self.browser.set_checked(sel, enable)
def set_valid_root_password(self, valid=True):
p = Password(self.browser, ROOT_ACCOUNT_ID_PREFIX)
password = "password"
p.set_password(password)
p.set_password_confirm(password if valid else "X")
def check_readonly_users_section_visible(self):
"""Assert the Accounts step shows the read-only user summary (kickstart-defined users)."""
self.browser.wait_visible(ACCOUNTS_READONLY_USERS)
def check_readonly_user_displayed(self, username, full_name=None):
"""
Assert a user is listed in the read-only summary.
Optionally check the displayed text: 'Full Name (username)' or 'username'.
"""
sel = f"[data-testid='{ACCOUNTS_READONLY_USER_ROW}-{username}']"
self.browser.wait_visible(sel)
if full_name is not None:
expected = f"{full_name} ({username})"
self.browser.wait_text(sel, expected)
def create_user(browser, machine):
p = Password(browser, CREATE_ACCOUNT_ID_PREFIX)
u = Users(browser, machine)
password = "password"
p.set_password(password)
p.set_password_confirm(password)
u.set_user_name("tester")