Background automations had no session, so get_current_profile_id() fell back to admin (1) — wrong for a non-admin's scheduled job. Now the engine declares the automation's owner around handler execution via a contextvar (core/profile_context.py), and get_current_profile_id() consults it only when there's NO web request. So: - a real logged-in request always wins (foreground unchanged), - admin + system automations are profile 1 → resolve to admin exactly as before (the 8 admin-owned auto-sync pipelines behave identically), - only non-admin-owned automations gain their correct identity, deep through the whole call chain (incl. the per-profile client resolvers) — no threading profile_id through dozens of signatures. Reset in a finally so a pooled thread can't leak the override to the next job. Tests: contextvar set/reset/nested; get_current_profile_id honours the override only outside a request (a real session still wins); and end-to-end — the engine runs a non-admin automation as profile 4, an admin one as 1, an explicit trigger profile overrides the owner, and the context resets even when the handler raises. 27 + 4 tests pass. Part 2 (next): point the sync handlers' source-playlist READ at get_spotify_client_for_profile so a non-admin's auto-sync pulls THEIR playlist.
31 lines
1.1 KiB
Python
31 lines
1.1 KiB
Python
"""Background profile context (per-profile automations).
|
|
|
|
Lets background work (the automation engine) declare which profile it's acting
|
|
for, so get_current_profile_id() resolves to the automation's OWNER instead of
|
|
admin when there's no web request. A real request must still win; admin/system
|
|
(profile 1) and no-override must stay admin.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from core.profile_context import (
|
|
set_background_profile, reset_background_profile, get_background_profile,
|
|
)
|
|
|
|
|
|
def test_set_reset_roundtrip():
|
|
assert get_background_profile() is None
|
|
tok = set_background_profile(5)
|
|
assert get_background_profile() == 5
|
|
reset_background_profile(tok)
|
|
assert get_background_profile() is None
|
|
|
|
|
|
def test_nested_set_reset():
|
|
t1 = set_background_profile(3)
|
|
t2 = set_background_profile(1) # e.g. an admin/system sub-run
|
|
assert get_background_profile() == 1
|
|
reset_background_profile(t2)
|
|
assert get_background_profile() == 3 # back to the outer profile
|
|
reset_background_profile(t1)
|
|
assert get_background_profile() is None # fully cleared (no leak)
|