Files
inkwell/tests/test_installer.py
T
bvandeusenandClaude Opus 5.5 fae03c7eca install.sh reads INKWELL_SERVER, INKWELL_CHANNEL and INKWELL_TOKEN (#5372)
The installer's environment variables kept the ThoughtSync-era TS_ prefix
after the rename to Inkwell. They are now INKWELL_*, as is the
INKWELL_SERVER_DEFAULT line the server fills in when it serves the script.
The old names are not read any more; the operator approved the clean cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:01:13 -04:00

124 lines
4.7 KiB
Python

import pytest
from inkwell import installer, settings
from inkwell.app import create_app
from inkwell.installer import PLACEHOLDER, SOURCE_SCRIPT, render, server_address
# DB-free, like test_client_dist: the route reads `public_url` from the live cache
# rather than from the database, which is what makes it testable here.
SCRIPT = f"#!/bin/sh\nset -eu\n{PLACEHOLDER}\nserver=\"${{INKWELL_SERVER:-$INKWELL_SERVER_DEFAULT}}\"\n"
@pytest.fixture(autouse=True)
def _defaults():
settings.reset_live()
yield
settings.reset_live()
@pytest.fixture
def app():
return create_app()
def test_the_published_script_carries_the_line_the_server_rewrites_exactly_once():
"""The forge-served script and the server-served one are the same file; this is
the one line that differs. Edit it and the server stops serving rather than
serving a script with no address in it — this test is what says so first."""
assert SOURCE_SCRIPT.read_text(encoding="utf-8").count(PLACEHOLDER) == 1
def test_render_writes_the_address_into_the_one_variable():
body = render(SCRIPT, "https://notes.example.com")
assert "INKWELL_SERVER_DEFAULT='https://notes.example.com'" in body
assert PLACEHOLDER not in body
# Nothing else moved.
assert body.replace("INKWELL_SERVER_DEFAULT='https://notes.example.com'", PLACEHOLDER) == SCRIPT
@pytest.mark.parametrize(
"address",
[
"https://notes.example.com/sub/path",
"http://192.168.1.20:5000",
"https://notes.example.com:8443",
],
)
def test_an_ordinary_address_is_accepted(address):
assert render(SCRIPT, address) is not None
@pytest.mark.parametrize(
"address",
[
# Each is a way out of the single quotes, or a second command.
"https://x.example.com'; rm -rf ~; '",
"https://x.example.com/$(id)",
"https://x.example.com/`id`",
"https://x.example.com\nrm -rf ~",
"https://x.example.com/a b",
"https://x.example.com/;id",
# Not an address at all.
"ftp://x.example.com",
"x.example.com",
"",
],
)
def test_an_address_that_could_mean_something_to_a_shell_is_refused(address):
assert render(SCRIPT, address) is None
@pytest.mark.parametrize("script", ["#!/bin/sh\n", SCRIPT + PLACEHOLDER + "\n"])
def test_a_script_without_exactly_one_placeholder_is_not_served(script):
assert render(script, "https://notes.example.com") is None
def test_the_public_address_setting_beats_the_request_host():
"""Behind a reverse proxy the Host this request arrived with may be an internal
one; Settings → Public address is what the operator says people use."""
assert server_address("https://notes.example.com", "http", "inkwell:5000") == "https://notes.example.com"
def test_without_the_setting_the_request_address_is_used():
assert server_address("", "https", "notes.example.com") == "https://notes.example.com"
def test_a_trailing_slash_is_dropped():
assert server_address("https://notes.example.com/", "http", "ignored") == "https://notes.example.com"
def test_a_host_header_that_is_not_an_address_yields_none():
assert server_address("", "http", "evil.example.com'$(id)") is None
async def test_the_route_serves_the_script_pointed_at_this_server(app):
resp = await app.test_client().get("/install.sh", headers={"Host": "notes.example.com"})
assert resp.status_code == 200
assert resp.mimetype == "text/plain"
body = await resp.get_data(as_text=True)
assert "INKWELL_SERVER_DEFAULT='http://notes.example.com'" in body
assert body.startswith("#!/bin/sh")
async def test_the_route_uses_the_public_address_when_one_is_set(app, monkeypatch):
monkeypatch.setitem(settings._live, "public_url", "https://notes.example.com")
resp = await app.test_client().get("/install.sh", headers={"Host": "inkwell:5000"})
assert "INKWELL_SERVER_DEFAULT='https://notes.example.com'" in await resp.get_data(as_text=True)
async def test_the_route_refuses_rather_than_serve_an_unsafe_address(app, monkeypatch):
# A Public address saved before it was validated this strictly: Settings only
# checks the scheme, so this is reachable.
monkeypatch.setitem(settings._live, "public_url", "https://notes.example.com/'$(id)'")
resp = await app.test_client().get("/install.sh", headers={"Host": "notes.example.com"})
assert resp.status_code == 500
assert "INKWELL_SERVER_DEFAULT" not in await resp.get_data(as_text=True)
async def test_a_server_with_no_copy_of_the_script_404s(app, monkeypatch, tmp_path):
monkeypatch.setattr(installer, "BAKED_SCRIPT", tmp_path / "absent")
monkeypatch.setattr(installer, "SOURCE_SCRIPT", tmp_path / "also-absent")
resp = await app.test_client().get("/install.sh")
assert resp.status_code == 404