tests: adds test for auth ghost user; refactors accessing default/ghost user

This commit is contained in:
ievgenii vdovenko 2025-07-26 15:08:32 +02:00
parent 544e757a34
commit 1db5e92ca3
2 changed files with 46 additions and 13 deletions

View file

@ -1261,15 +1261,6 @@ class User(Base, BaseModel):
raise Exception("FATAL: Missing administrative account!")
return user
@classmethod
def get_ghost_user(cls):
stmt = cls.select().where(User.username == User.GHOST_USER)
user = cls.scalars(stmt).first()
if user is None:
raise Exception("FATAL: Missing ghost user!")
return user
@classmethod
def get_all_super_admins(cls, only_active=False):
"""
@ -1291,13 +1282,21 @@ class User(Base, BaseModel):
qry = qry.filter(User.active == true())
return [x.user_id for x in qry]
@classmethod
def get_ghost_user(cls, cache=False, refresh=False):
return cls._get_system_user(username=User.GHOST_USER, cache=cache, refresh=refresh)
@classmethod
def get_default_user(cls, cache=False, refresh=False):
user = User.get_by_username(User.DEFAULT_USER, cache=cache)
return cls._get_system_user(username=User.DEFAULT_USER, cache=cache, refresh=refresh)
@classmethod
def _get_system_user(cls, username, cache=False, refresh=False):
user = User.get_by_username(username, cache=cache)
if user is None:
raise Exception("FATAL: Missing default account!")
raise Exception("FATAL: Missing %s account!" % username)
if refresh:
# The default user might be based on outdated state which
# The 'system' user might be based on outdated state which
# has been loaded from the cache.
# A call to refresh() ensures that the
# latest state from the database is used.

View file

@ -572,7 +572,12 @@ def test_auth_user_get_cookie_store_for_normal_user(user_util):
assert auth_user.get_cookie_store() == expected_data
def test_auth_user_get_cookie_store_for_default_user():
def test_auth_user_get_cookie_store_for_default_user(baseapp):
# NOTE: Importing baseapp is important—if this test runs in isolation,
# the User class may not be bound to the Session, resulting in an error.
# Importing baseapp ensures the session is explicitly bound for this test.
# When tests are run in batch, this binding often happens implicitly as a side effect of other tests or fixtures.
default_user = User.get_default_user()
auth_user = auth.AuthUser()
expected_data = {
@ -584,6 +589,35 @@ def test_auth_user_get_cookie_store_for_default_user():
assert auth_user.get_cookie_store() == expected_data
def test_auth_not_allowed_for_ghost_user(baseapp):
# NOTE: Importing baseapp is important—if this test runs in isolation,
# the User class may not be bound to the Session, resulting in an error.
# Importing baseapp ensures the session is explicitly bound for this test.
# When tests are run in batch, this binding often happens implicitly as a side effect of other tests or fixtures.
ghost = User.get_ghost_user()
try:
# Under normal conditions, the ghost user should not have a password and should remain inactive.
ghost.password = "<PASSWORD>"
ghost.active = True
Session().commit()
auth_user = auth.AuthUser(user_id=ghost.user_id)
expected_data = {
"username": User.GHOST_USER,
"user_id": ghost.user_id,
"password": md5_safe(ghost.password),
"is_authenticated": False,
}
assert auth_user.get_cookie_store() == expected_data
finally:
# Important: Clean up after this test since the ghost user is unique in the system.
# Not cleaning up could affect other tests or parts of the application.
ghost.password = None
ghost.active = False
Session().commit()
def get_permissions(user, **kwargs):
"""
Utility filling in useful defaults into the call to `_cached_perms_data`.