A video stays on /watch/, anything else is given out on /file/ and a folder on /folder/. The token is the whole key, so every path opens every link and the links already sent keep working. The new paths are kept out of search indexes like /watch/, boot the player alone, and the unfurl card calls a file a file.
138 lines
5.2 KiB
Python
138 lines
5.2 KiB
Python
"""A share link's address says what it opens: /watch/ a video, /file/ anything else, /folder/ a folder.
|
|
|
|
Only a word for the reader: the token is the key, so every path opens every link, and the links
|
|
already sent out on /watch/ keep working for good. DB-lane.
|
|
"""
|
|
|
|
import pytest
|
|
from cryptography.fernet import Fernet
|
|
|
|
from app import main, security
|
|
from app.config import settings
|
|
from app.downloads import og
|
|
from app.downloads import probe as probemod
|
|
|
|
_PAGE = """<!doctype html><html><head>
|
|
<!--OG:START--><meta property="og:title" content="Siftlode" /><!--OG:END-->
|
|
</head><body><script src="/assets/{entry}.js"></script></body></html>"""
|
|
|
|
_VIDEO = {
|
|
"streams": [
|
|
{"codec_type": "video", "codec_name": "h264", "pix_fmt": "yuv420p"},
|
|
{"codec_type": "audio", "codec_name": "aac"},
|
|
],
|
|
"format": {"format_name": "mov,mp4", "duration": "5"},
|
|
}
|
|
_AUDIO = {
|
|
"streams": [{"codec_type": "audio", "codec_name": "aac"}],
|
|
"format": {"format_name": "mov,mp4", "duration": "5"},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def pages(tmp_path, monkeypatch):
|
|
index, watch = tmp_path / "index.html", tmp_path / "watch.html"
|
|
index.write_text(_PAGE.format(entry="app"), encoding="utf-8")
|
|
watch.write_text(_PAGE.format(entry="watch"), encoding="utf-8")
|
|
monkeypatch.setattr(main, "INDEX_HTML", index)
|
|
monkeypatch.setattr(main, "WATCH_HTML", watch)
|
|
|
|
|
|
@pytest.fixture
|
|
def key(monkeypatch):
|
|
"""A link's address is read back from its encrypted token."""
|
|
monkeypatch.setattr(security, "_fernet", Fernet(Fernet.generate_key()))
|
|
|
|
|
|
@pytest.fixture
|
|
def shared(as_user, make_user, tmp_path, monkeypatch, upload_headers):
|
|
"""Uploads a file ffprobe reads as `data` (None: it cannot read it) and shares it."""
|
|
monkeypatch.setattr(settings, "files_root", str(tmp_path / "media"))
|
|
owner = as_user(make_user())
|
|
|
|
def share(name: str, data: dict | None, **link: object) -> dict:
|
|
monkeypatch.setattr(probemod, "probe_json", lambda _p: data)
|
|
job = owner.post(
|
|
"/api/files/upload",
|
|
content=b"some bytes",
|
|
headers=upload_headers(name, display_name=name),
|
|
)
|
|
assert job.status_code == 200, job.text
|
|
made = owner.post(f"/api/downloads/{job.json()['id']}/links", json=link)
|
|
assert made.status_code == 200, made.text
|
|
return made.json()
|
|
|
|
share.owner = owner # type: ignore[attr-defined]
|
|
return share
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("name", "data", "prefix"),
|
|
[
|
|
("clip.mp4", _VIDEO, "/watch/"),
|
|
("song.m4a", _AUDIO, "/file/"),
|
|
("backup.tar.gz", None, "/file/"),
|
|
],
|
|
)
|
|
def test_a_link_is_given_out_on_the_path_of_what_it_opens(shared, name, data, prefix):
|
|
made = shared(name, data)
|
|
assert made["url"] == f"{prefix}{made['token']}"
|
|
|
|
|
|
def test_a_folder_link_is_given_out_on_folder(shared, key):
|
|
owner = shared.owner
|
|
folder = owner.post("/api/files/folders", json={"name": "Friends"}).json()
|
|
made = owner.post(f"/api/downloads/folders/{folder['id']}/links", json={}).json()
|
|
assert made["url"] == f"/folder/{made['token']}"
|
|
listed = owner.get(f"/api/downloads/folders/{folder['id']}/links").json()
|
|
assert [entry["url"] for entry in listed] == [made["url"]]
|
|
|
|
|
|
def test_the_list_gives_the_same_address_as_the_making(shared, key):
|
|
made = shared("backup.tar.gz", None)
|
|
owner = shared.owner
|
|
files = owner.get("/api/files").json()
|
|
job_id = next(f["id"] for f in files if f["display_name"] == "backup.tar.gz")
|
|
listed = owner.get(f"/api/downloads/{job_id}/links").json()
|
|
assert [entry["url"] for entry in listed] == [made["url"]]
|
|
|
|
|
|
@pytest.mark.parametrize("path", ["watch", "file", "folder"])
|
|
@pytest.mark.parametrize(
|
|
("name", "data"), [("clip.mp4", _VIDEO), ("backup.tar.gz", None)], ids=["video", "file"]
|
|
)
|
|
def test_every_path_opens_every_link(pages, shared, client, path, name, data):
|
|
"""The links already sent on /watch/ open whatever they open, for good."""
|
|
token = shared(name, data)["token"]
|
|
r = client.get(f"/{path}/{token}")
|
|
assert r.status_code == 200
|
|
assert "/assets/watch.js" in r.text and "/assets/app.js" not in r.text
|
|
assert f'content="{name}"' in r.text
|
|
|
|
|
|
@pytest.mark.parametrize("path", ["/file/no-such-token", "/folder/no-such-token", "/file/a/b"])
|
|
def test_a_new_path_without_a_live_link_still_gets_the_player(pages, client, path):
|
|
r = client.get(path)
|
|
assert r.status_code == 200
|
|
assert "/assets/watch.js" in r.text and "/assets/app.js" not in r.text
|
|
|
|
|
|
def test_a_card_names_a_file_as_a_file(shared, db):
|
|
made = shared("backup.tar.gz", None)
|
|
tags = og._watch_tags(made["token"], db)
|
|
assert f'{made["url"]}"' in tags
|
|
assert "video.other" not in tags
|
|
|
|
locked = shared("notes.tar.gz", None, password="pw")
|
|
hidden = og._watch_tags(locked["token"], db)
|
|
assert "Password-protected file" in hidden and "notes" not in hidden
|
|
assert "video.other" not in hidden
|
|
|
|
|
|
def test_a_card_of_a_video_stays_a_video(shared, db):
|
|
made = shared("clip.mp4", _VIDEO)
|
|
tags = og._watch_tags(made["token"], db)
|
|
assert f"/watch/{made['token']}" in tags and "video.other" in tags
|
|
locked = shared("other.mp4", _VIDEO, password="pw")
|
|
assert "Password-protected video" in og._watch_tags(locked["token"], db)
|