The workshop + managed-global overlay surface fully covers the admin-SFTP flow that 'external' was a placeholder for. Drop the type from the model defaults, builder registry, routes, template, and tests, and add migration 0004 that deletes any leftover external rows along with their blueprint and job references. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
167 lines
6.4 KiB
Python
167 lines
6.4 KiB
Python
from sqlalchemy import select
|
|
|
|
from l4d2web.db import init_db, session_scope
|
|
from l4d2web.models import GlobalOverlaySource, Job, Overlay, User
|
|
from l4d2web.services.global_overlays import (
|
|
enqueue_refresh_global_overlays,
|
|
ensure_global_overlays,
|
|
is_creatable_overlay_type,
|
|
)
|
|
|
|
|
|
def test_ensure_global_overlays_creates_singletons_and_directories(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{tmp_path/'global_overlays.db'}")
|
|
monkeypatch.setenv("LEFT4ME_ROOT", str(tmp_path))
|
|
init_db()
|
|
|
|
with session_scope() as session:
|
|
created = ensure_global_overlays(session)
|
|
assert created == {"cedapug-maps", "l4d2center-maps"}
|
|
|
|
second = ensure_global_overlays(session)
|
|
assert second == set()
|
|
|
|
overlays = session.scalars(select(Overlay).order_by(Overlay.name)).all()
|
|
assert [overlay.name for overlay in overlays] == ["cedapug-maps", "l4d2center-maps"]
|
|
assert [overlay.type for overlay in overlays] == ["cedapug_maps", "l4d2center_maps"]
|
|
assert [overlay.user_id for overlay in overlays] == [None, None]
|
|
assert len({overlay.path for overlay in overlays}) == 2
|
|
for overlay in overlays:
|
|
assert (tmp_path / "overlays" / overlay.path).is_dir()
|
|
|
|
sources = session.scalars(select(GlobalOverlaySource).order_by(GlobalOverlaySource.source_key)).all()
|
|
assert [source.source_key for source in sources] == ["cedapug-maps", "l4d2center-maps"]
|
|
assert [source.source_type for source in sources] == [
|
|
"cedapug_custom_page",
|
|
"l4d2center_csv",
|
|
]
|
|
|
|
|
|
def test_ensure_global_overlays_repairs_existing_rows(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{tmp_path/'global_overlay_repair.db'}")
|
|
monkeypatch.setenv("LEFT4ME_ROOT", str(tmp_path))
|
|
init_db()
|
|
|
|
with session_scope() as session:
|
|
overlay = Overlay(name="cedapug-maps", path="legacy", type="cedapug_maps", user_id=None)
|
|
session.add(overlay)
|
|
session.flush()
|
|
session.add(
|
|
GlobalOverlaySource(
|
|
overlay_id=overlay.id,
|
|
source_key="cedapug-maps",
|
|
source_type="wrong",
|
|
source_url="https://example.invalid/wrong",
|
|
)
|
|
)
|
|
|
|
(tmp_path / "overlays" / "legacy").mkdir(parents=True)
|
|
|
|
with session_scope() as session:
|
|
created = ensure_global_overlays(session)
|
|
assert created == {"l4d2center-maps"}
|
|
|
|
repaired = session.scalar(select(Overlay).where(Overlay.name == "cedapug-maps"))
|
|
assert repaired is not None
|
|
assert repaired.type == "cedapug_maps"
|
|
assert repaired.user_id is None
|
|
assert (tmp_path / "overlays" / repaired.path).is_dir()
|
|
|
|
source = session.scalar(
|
|
select(GlobalOverlaySource).where(GlobalOverlaySource.source_key == "cedapug-maps")
|
|
)
|
|
assert source is not None
|
|
assert source.source_type == "cedapug_custom_page"
|
|
assert source.source_url == "https://cedapug.com/custom"
|
|
|
|
|
|
def test_ensure_global_overlays_does_not_hijack_private_overlay_name(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{tmp_path/'global_overlay_private_name.db'}")
|
|
monkeypatch.setenv("LEFT4ME_ROOT", str(tmp_path))
|
|
init_db()
|
|
|
|
with session_scope() as session:
|
|
user = User(username="alice", password_digest="digest", admin=False)
|
|
session.add(user)
|
|
session.flush()
|
|
private = Overlay(
|
|
name="l4d2center-maps",
|
|
path="private-l4d2center",
|
|
type="workshop",
|
|
user_id=user.id,
|
|
)
|
|
session.add(private)
|
|
session.flush()
|
|
private_id = private.id
|
|
private_user_id = user.id
|
|
|
|
with session_scope() as session:
|
|
created = ensure_global_overlays(session)
|
|
|
|
assert created == {"cedapug-maps", "l4d2center-maps"}
|
|
private = session.scalar(select(Overlay).where(Overlay.id == private_id))
|
|
assert private is not None
|
|
assert private.user_id == private_user_id
|
|
assert private.type == "workshop"
|
|
assert private.path == "private-l4d2center"
|
|
|
|
system = session.scalar(
|
|
select(Overlay).where(Overlay.name == "l4d2center-maps", Overlay.user_id.is_(None))
|
|
)
|
|
assert system is not None
|
|
assert system.id != private_id
|
|
assert system.type == "l4d2center_maps"
|
|
assert (tmp_path / "overlays" / system.path).is_dir()
|
|
|
|
source = session.scalar(
|
|
select(GlobalOverlaySource).where(GlobalOverlaySource.source_key == "l4d2center-maps")
|
|
)
|
|
assert source is not None
|
|
assert source.overlay_id == system.id
|
|
|
|
|
|
def test_enqueue_refresh_global_overlays_coalesces_active_jobs(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{tmp_path/'refresh_jobs.db'}")
|
|
init_db()
|
|
|
|
for state in ("queued", "running", "cancelling"):
|
|
with session_scope() as session:
|
|
session.query(Job).delete()
|
|
existing = Job(
|
|
user_id=7,
|
|
server_id=None,
|
|
overlay_id=None,
|
|
operation="refresh_global_overlays",
|
|
state=state,
|
|
)
|
|
session.add(existing)
|
|
session.flush()
|
|
existing_id = existing.id
|
|
|
|
job = enqueue_refresh_global_overlays(session, user_id=None)
|
|
assert job.id == existing_id
|
|
assert session.query(Job).filter_by(operation="refresh_global_overlays").count() == 1
|
|
|
|
|
|
def test_enqueue_refresh_global_overlays_creates_system_job(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{tmp_path/'refresh_system_job.db'}")
|
|
init_db()
|
|
|
|
with session_scope() as session:
|
|
job = enqueue_refresh_global_overlays(session, user_id=None)
|
|
|
|
assert job.id is not None
|
|
assert job.user_id is None
|
|
assert job.server_id is None
|
|
assert job.overlay_id is None
|
|
assert job.operation == "refresh_global_overlays"
|
|
assert job.state == "queued"
|
|
|
|
|
|
def test_is_creatable_overlay_type_policy():
|
|
assert is_creatable_overlay_type("workshop", admin=False) is True
|
|
assert is_creatable_overlay_type("workshop", admin=True) is True
|
|
assert is_creatable_overlay_type("external", admin=False) is False
|
|
assert is_creatable_overlay_type("external", admin=True) is False
|
|
assert is_creatable_overlay_type("l4d2center_maps", admin=True) is False
|
|
assert is_creatable_overlay_type("cedapug_maps", admin=True) is False
|