Piotr Wargulak created FINERACT-2953:
----------------------------------------

             Summary: Datatable entry update/delete with a second id acts on 
another entity's row
                 Key: FINERACT-2953
                 URL: https://issues.apache.org/jira/browse/FINERACT-2953
             Project: Apache Fineract
          Issue Type: Bug
            Reporter: Piotr Wargulak


{{PUT}} and {{{}DELETE /datatables/\{datatable}/\{apptableId}/{datatableId{}}}} 
(also through {{{}/batches{}}}, and {{{}DELETE 
/survey/\{surveyName}/\{clientId}/{fulfilledId{}}}}, which reaches the same 
delete) check that {{apptableId}} exists and is within the user's office scope, 
but choose the row they write or delete by {{{}datatableId{}}}. Three cases 
follow:
 # *One-to-one datatable, PUT with a second id.* 
{{DatatableUtil#retrieveDataTableGenericResultSet}} ignores {{datatableId}} on 
a one-to-one table, so the existing row is read for {{{}apptableId{}}}; the 
UPDATE is then keyed on {{datatableId ?? apptableId}} 
({{{}DatatableWriteServiceImpl#updateDatatableEntry{}}}). The row of the entity 
whose id is {{datatableId}} is updated.
 # *One-to-one datatable, DELETE with a second id.* The statement is {{{}DELETE 
... WHERE "id" = ?{}}}, a column a one-to-one table does not have, so the 
caller gets HTTP 403 {{error.msg.data.integrity.issue}} carrying the raw 
database message ({{{}ERROR: column "id" does not exist{}}}).
 # *One-to-many datatable, DELETE with a second id.* The statement is {{DELETE 
... WHERE id = ?}} with no condition on {{{}apptableId{}}}, so an entry 
belonging to another entity is deleted. (PUT is not affected: its read uses 
both ids and answers 404.)

In cases 1 and 3, the office scope check and any state check made on 
{{apptableId}} do not apply to the entity whose row actually changes.

A related edge: {{isMultirowDatatable}} only looks for a column named 
{{{}id{}}}. A table registered through {{POST /datatables/register/...}} whose 
primary key is the foreign key, and which also has a plain {{id}} column, reads 
as one-to-many, and its PUT keys the UPDATE on {{datatableId}} as in case 1.

{*}Steps to reproduce{*}: two clients X and B, a one-to-one datatable 
{{dt_one}} and a one-to-many {{dt_many}} on {{{}m_client{}}}, one entry each.
||Request||Result||
|{{PUT /datatables/dt_one/X/B}} {{{{}"note":"via-X"{}}}}|200; *B's* row is now 
{{{}via-X{}}}, X's unchanged|
|{{DELETE /datatables/dt_one/X/B}}|403, message {{ERROR: column "id" does not 
exist}}|
|{{DELETE /datatables/dt_many/X/<id of B's entry>}}|200; *B's* entry deleted|
|{{POST /batches}} with {{PUT v1/datatables/dt_one/X/B}}|inner 200; B's row 
written|
|{{DELETE /survey/dt_many/X/<id of B's entry>}}|200; *B's* entry deleted|

*Expected*
 * A one-to-one datatable refuses an entry id on PUT and DELETE (403, like the 
existing {{error.msg.attempting.multiple.update}} for a one-to-many PUT without 
one).
 * A one-to-many DELETE by entry id deletes only an entry of 
{{{}apptableId{}}}; when no such entry exists, 404 
{{{}error.msg.datatable.data.not.found{}}}, as the PUT already answers.
 * A PUT updates the row it has just read for {{apptableId}} (keyed on that 
row's primary key).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to