Fix scan-to-download auth and share every photo widget's current photo
The share QR's URL carried no auth params at all, so it silently fell back through require_device's legacy-token resolution to whichever frame happened to still be flagged legacy -- working only by accident for a single frame, sharing the wrong frame's photos for any other, and going fully dead once that frame's legacy flag was cleared. Move the endpoint to manage.py, keyed on the frame's own manage_token (same pattern /m/<manage_token> already uses) instead of device auth. Since the server now resolves assets itself instead of trusting a caller-supplied asset_id, it naturally generalizes to gather every photo widget's current photo into one Immich share link, not just one "primary" widget's.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""End-to-end HTTP tests for the widget-system cutover in
|
||||
routers/device.py -- /frame/image, /frame/advance, /frame/back, and
|
||||
/frame/share against real widget rows (via the migration-backfilled
|
||||
frame #1, or a purpose-built second frame), a real TestClient, real
|
||||
routers/device.py -- /frame/image, /frame/advance, and /frame/back
|
||||
against real widget rows (via the migration-backfilled frame #1, or a
|
||||
purpose-built second frame), a real TestClient, real
|
||||
render_panel/compose_into. Only Immich itself is mocked (monkeypatched
|
||||
at the app.widgets.photos module boundary, same pattern as
|
||||
test_widgets_photos.py) -- everything else in the pipeline is real.
|
||||
@@ -23,7 +23,6 @@ from app.models import (
|
||||
Frame,
|
||||
FrameButtonAction,
|
||||
PhotoWidgetConfig,
|
||||
User,
|
||||
Widget,
|
||||
)
|
||||
|
||||
@@ -145,33 +144,3 @@ def test_two_widget_frame_composites_both_and_next_targets_calendar(client, db_s
|
||||
photo_cfg = db_session.get(PhotoWidgetConfig, photo_widget.id)
|
||||
assert cal_cfg.browse_offset == 1
|
||||
assert photo_cfg.current_asset_id == "" # untouched -- NEXT was never bound to it
|
||||
|
||||
|
||||
def test_frame_share_checks_widget_scoped_state(client, db_session, monkeypatch):
|
||||
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
||||
frame = db_session.get(Frame, 1)
|
||||
frame.owner_user_id = db_session.query(User).filter_by(username="alice").one().id
|
||||
widget = db_session.query(Widget).filter_by(frame_id=frame.id, widget_type="photos").one()
|
||||
cfg = db_session.get(PhotoWidgetConfig, widget.id)
|
||||
cfg.album_id = "album-1"
|
||||
cfg.current_asset_id = "asset-1"
|
||||
cfg.queue = ["asset-2"]
|
||||
frame.immich_url = "http://immich.example.com"
|
||||
frame.immich_api_key = "key"
|
||||
db_session.commit()
|
||||
|
||||
# Not showing/queued -- rejected before ever touching Immich
|
||||
resp = client.get("/frame/share/asset-not-on-this-frame")
|
||||
assert resp.status_code == 404
|
||||
|
||||
# Currently showing -- allowed through to the (mocked) Immich call
|
||||
monkeypatch.setattr(
|
||||
"app.routers.device.immich_client_for",
|
||||
lambda frame: type("C", (), {"create_share_link": lambda self, asset_id, expires_in_s: "https://immich.example.com/share/abc"})(),
|
||||
)
|
||||
resp = client.get("/frame/share/asset-1", follow_redirects=False)
|
||||
assert resp.status_code in (302, 303, 307)
|
||||
|
||||
# Queued (not current) -- also allowed
|
||||
resp = client.get("/frame/share/asset-2", follow_redirects=False)
|
||||
assert resp.status_code in (302, 303, 307)
|
||||
|
||||
Reference in New Issue
Block a user