mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-15 16:14:16 +00:00
fix(admin): address review findings
- 0034's backfill set target_id to the acting admin for instance- and team-scoped quota policy changes, which are filed under the actor and have no user target. It now returns NULL for those, matching what quotas.py records going forward, with a test covering all three scopes. - The CSV export wrote every cell verbatim. user_agent is an attacker's raw header, recorded without authenticating on a denied login, and the export is opened in a spreadsheet by an admin -- a cell starting "=" would be evaluated there. Every cell now has a leading formula trigger neutralized. - The activity feed applied every response it received, so a slow reply for an old filter could overwrite the current one. Guarded by a request id, the same way settings/Analytics already does. - The activity detail expander and the top-user drill-down were row onClick handlers, unreachable without a mouse. Both are real buttons now, the expander carrying aria-expanded and a label naming its event. - FLOW_LABELS was applied to both breakdowns in the spend modal, so a model named "fallback" or "workflow" rendered as a flow description. Only the flow table maps keys now. - Changing the range in that modal left the previous range's totals and chart on screen while the new request was in flight.
This commit is contained in:
1 parent
64200a7f23
commit
2ea9d66789
7 files changed
+141
-25
No files matched your search
@@ -193,6 +193,29 @@ class TestExport:
|
||||
lines = body.strip().split("\n")
|
||||
assert [json.loads(line)["id"] for line in lines] == ["1", "2"]
|
||||
|
||||
def test_csv_cells_cannot_smuggle_a_spreadsheet_formula(self, client):
|
||||
"""``user_agent`` is an unauthenticated attacker's raw header."""
|
||||
repo = _repo(
|
||||
rows=[_row(user_agent="=cmd|'/c calc'!A0", actor_id="+1", ip="-2")]
|
||||
)
|
||||
with _admin(repo):
|
||||
body = client.get(
|
||||
"/api/admin/activity/export?format=csv"
|
||||
).get_data(as_text=True)
|
||||
row = next(csv.DictReader(io.StringIO(body)))
|
||||
assert row["user_agent"].startswith("'=")
|
||||
assert row["actor_id"].startswith("'+")
|
||||
assert row["ip"].startswith("'-")
|
||||
|
||||
def test_csv_leaves_ordinary_cells_alone(self, client):
|
||||
with _admin(_repo()):
|
||||
body = client.get(
|
||||
"/api/admin/activity/export?format=csv"
|
||||
).get_data(as_text=True)
|
||||
row = next(csv.DictReader(io.StringIO(body)))
|
||||
assert row["user_agent"] == "curl/8"
|
||||
assert row["event"] == "oidc_login"
|
||||
|
||||
def test_empty_csv_export_still_has_its_header(self, client):
|
||||
with _admin(_repo(rows=[])):
|
||||
body = client.get("/api/admin/activity/export").get_data(as_text=True)
|
||||
|
||||
@@ -125,3 +125,38 @@ class TestMigration0034RoundTrip:
|
||||
assert rows["oidc_login"] == "someone|someone"
|
||||
# Team events were always filed under the actor; they have no user target.
|
||||
assert rows["team.create"] == "actor-3|-"
|
||||
|
||||
def test_backfill_scopes_quota_policy_targets(self, pg_engine):
|
||||
"""Only a user-scoped quota policy has a user target.
|
||||
|
||||
Instance and team policies are filed under the acting admin, so
|
||||
backfilling ``target_id = user_id`` would claim the admin was acted on.
|
||||
"""
|
||||
url = pg_engine.url.render_as_string(hide_password=False)
|
||||
_run_alembic(url, "downgrade", _0033)
|
||||
with pg_engine.begin() as conn:
|
||||
conn.execute(
|
||||
text(
|
||||
"INSERT INTO auth_events (user_id, event, metadata) VALUES "
|
||||
"('admin-q', 'quota_policy_set', "
|
||||
" '{\"by\": \"admin-q\", \"scope\": \"instance\"}'::jsonb), "
|
||||
"('admin-q2', 'quota_policy_deleted', "
|
||||
" '{\"by\": \"admin-q2\", \"scope\": \"team\"}'::jsonb), "
|
||||
"('capped-user', 'quota_policy_set', "
|
||||
" '{\"by\": \"admin-q3\", \"scope\": \"user\"}'::jsonb)"
|
||||
)
|
||||
)
|
||||
_run_alembic(url, "upgrade", "head")
|
||||
with pg_engine.connect() as conn:
|
||||
rows = dict(
|
||||
conn.execute(
|
||||
text(
|
||||
"SELECT user_id, actor_id || '|' || COALESCE(target_id, '-') "
|
||||
"FROM auth_events WHERE user_id IN "
|
||||
"('admin-q', 'admin-q2', 'capped-user')"
|
||||
)
|
||||
).fetchall()
|
||||
)
|
||||
assert rows["admin-q"] == "admin-q|-"
|
||||
assert rows["admin-q2"] == "admin-q2|-"
|
||||
assert rows["capped-user"] == "admin-q3|capped-user"
|
||||
Reference in new issue
Block a user