Allow same-team clip reads in gameday
This commit is contained in:
@@ -54,6 +54,26 @@ def resolve_media_scope(
|
||||
return session.external_team_id, session.external_player_id
|
||||
|
||||
|
||||
def resolve_media_read_scope(
|
||||
session: UserSession,
|
||||
*,
|
||||
requested_team_id: str | None = None,
|
||||
requested_player_id: str | None = None,
|
||||
) -> tuple[str, str | None]:
|
||||
if session.is_admin:
|
||||
team_id = requested_team_id or session.external_team_id
|
||||
player_id = requested_player_id if requested_player_id is not None else session.external_player_id
|
||||
if not team_id:
|
||||
raise HTTPException(status_code=422, detail="Select a team before viewing media")
|
||||
return team_id, player_id
|
||||
|
||||
if not session.external_team_id:
|
||||
raise HTTPException(status_code=422, detail="Select a team before viewing media")
|
||||
if requested_team_id and requested_team_id != session.external_team_id:
|
||||
raise HTTPException(status_code=403, detail="This team does not match your selected session")
|
||||
return session.external_team_id, requested_player_id
|
||||
|
||||
|
||||
def clip_to_response(clip: AudioClip) -> AudioClipResponse:
|
||||
normalized_url = f"/media/files/{clip.normalized_path}" if clip.normalized_path else None
|
||||
waveform = storage.load_or_generate_waveform(clip.asset.storage_path)
|
||||
@@ -452,7 +472,7 @@ def list_clips(
|
||||
session: UserSession = Depends(require_session),
|
||||
db: Session = Depends(get_db),
|
||||
) -> list[AudioClipResponse]:
|
||||
external_team_id, owner_external_player_id = resolve_media_scope(
|
||||
external_team_id, owner_external_player_id = resolve_media_read_scope(
|
||||
session,
|
||||
requested_team_id=external_team_id,
|
||||
requested_player_id=owner_external_player_id,
|
||||
|
||||
@@ -690,6 +690,58 @@ def test_hidden_clips_are_removed_from_gameday_views_but_remain_pinnable() -> No
|
||||
assert [item["clip_id"] for item in pins.json()] == [clip.id]
|
||||
|
||||
|
||||
def test_same_team_player_can_read_another_players_clips() -> None:
|
||||
db = SessionLocal()
|
||||
owner_session = UserSession(
|
||||
session_token="owner-library-session",
|
||||
provider="teamsnap",
|
||||
external_team_id="team-share",
|
||||
external_player_id="player-owner",
|
||||
)
|
||||
viewer_session = UserSession(
|
||||
session_token="viewer-library-session",
|
||||
provider="teamsnap",
|
||||
external_team_id="team-share",
|
||||
external_player_id="player-viewer",
|
||||
)
|
||||
db.add_all([owner_session, viewer_session])
|
||||
db.flush()
|
||||
|
||||
asset = AudioAsset(
|
||||
external_team_id="team-share",
|
||||
owner_external_player_id="player-owner",
|
||||
uploaded_by_session_id=owner_session.id,
|
||||
title="Shared song",
|
||||
original_filename="shared-song.mp3",
|
||||
mime_type="audio/mpeg",
|
||||
size_bytes=123,
|
||||
storage_path="uploads/shared-song.mp3",
|
||||
)
|
||||
db.add(asset)
|
||||
db.flush()
|
||||
clip = AudioClip(
|
||||
asset_id=asset.id,
|
||||
label="Shared clip",
|
||||
start_ms=0,
|
||||
end_ms=10000,
|
||||
normalization_status="ready",
|
||||
normalized_path="normalized/shared-clip.mp3",
|
||||
)
|
||||
db.add(clip)
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
client.cookies.set(settings.session_cookie_name, "viewer-library-session")
|
||||
response = client.get(
|
||||
"/media/clips",
|
||||
params={"external_team_id": "team-share", "owner_external_player_id": "player-owner"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert [item["id"] for item in response.json()] == [clip.id]
|
||||
assert response.json()[0]["owner_external_player_id"] == "player-owner"
|
||||
|
||||
|
||||
def test_clip_updates_can_use_player_scoped_authorization() -> None:
|
||||
uploader_session = UserSession(session_token="uploader-session", provider="teamsnap")
|
||||
editor_session = UserSession(
|
||||
|
||||
Reference in New Issue
Block a user