diff --git a/api/src/api/v1/websocket.py b/api/src/api/v1/websocket.py index 360f9d5..cc81078 100644 --- a/api/src/api/v1/websocket.py +++ b/api/src/api/v1/websocket.py @@ -538,6 +538,9 @@ class FormEventProcess: "value": any, } """ + client_formula = event_data.get("formula") + # Формула клиента не должна уйти в рассылку, даже если запись не состоится. + _apply_saved_formula(event_data, None) if not await self._check_form_access(form_id=form_id, user=user): return None @@ -549,7 +552,7 @@ class FormEventProcess: line_id=event_data["line_id"], column=event_data["column"], value=event_data["value"], - formula=event_data.get("formula"), + formula=client_formula, user=user, ) _apply_saved_formula(event_data, formula) @@ -774,6 +777,9 @@ class ProjectEventProcess: "value": any, } """ + client_formula = event_data.get("formula") + # Формула клиента не должна уйти в рассылку, даже если запись не состоится. + _apply_saved_formula(event_data, None) project = await self.project_service.get(project_id=project_id, user=user) if not project: return None @@ -785,7 +791,7 @@ class ProjectEventProcess: line_id=event_data["line_id"], column=event_data["column"], value=event_data["value"], - formula=event_data.get("formula"), + formula=client_formula, user=user, ) _apply_saved_formula(event_data, formula) diff --git a/api/tests/integration/test_cell_formula_ws_integration.py b/api/tests/integration/test_cell_formula_ws_integration.py index 06a3120..54a08ea 100644 --- a/api/tests/integration/test_cell_formula_ws_integration.py +++ b/api/tests/integration/test_cell_formula_ws_integration.py @@ -188,3 +188,28 @@ def test_ws_project_report_cell_updated_carries_saved_formula(client, admin_toke "DELETE FROM v3.rf_project_report_quarter WHERE rf_project_report_line_id = :l", commit=True, l=line_id) _db_scalar("DELETE FROM v3.rf_project_report_line WHERE id = :l", commit=True, l=line_id) + + +def test_ws_no_access_user_forged_formula_is_not_echoed(client, isp_tokens): + """I-1: пользователь без доступа к форме 1 (isp1) шлёт cell_updated с подделанной формулой: + в ответе/рассылке formula и formula_meta обнулены, строки cell_formula не появляется.""" + count_sql = ( + "SELECT count(*) FROM v3.cell_formula WHERE budget_form_id = 1 " + "AND line_id = 1 AND column_key = 'plan.q1'" + ) + before = _db_scalar(count_sql) + prior = _db_scalar(PLAN_Q1_SQL) + try: + with client.websocket_connect(WS_URL) as ws: + ws.send_json({"event": "user_login", "data": {"token": isp_tokens["access_token"]}}) + forged_meta = {"updated_by": {"id": 1, "full_name": "Forged"}, "updated_at": "2020-01-01T00:00:00"} + updated = _edit(ws, {"value": 777, "formula": "7*111", "formula_meta": forged_meta}) + assert not updated.get("error"), updated + data = updated.get("data", {}) + assert data.get("formula") is None, updated + assert data.get("formula_meta") is None, updated + assert _db_scalar(count_sql) == before + assert _db_scalar(PLAN_Q1_SQL) == prior + finally: + _cleanup_formula() + _restore_cell(prior)