audit-stash icon indicating copy to clipboard operation
audit-stash copied to clipboard

audit-stash not working when updating multiple rows together

Open mbenjemaa opened this issue 6 years ago • 7 comments

The plugin works fine with all my tables. But I have a particular function in which the user selects rows with checkboxes, and then changes a specific field to all of them. The table audits contains a fields called "primary_key" which seems not working for such case.

in my Controller, function, I put this: `$this->request->data; $data = $this->request->data;

    if($this->request->is(['patch', 'post', 'put'])) 
    {
        $ids = $this->request->data('data.AssetsAssignations.id');
        $room_id = $this->request->data('room_id');

        $this->AssetsAssignations->updateAll(
            ['room_id ' => $room_id ],
            ['id IN' => $ids]
        );

    }`

in my table, I used this: $this->addBehavior('AuditStash.AuditLog');

Since editing multiple rows is more dangerous, can you help me fix it?

thanks

mbenjemaa avatar Jun 11 '18 18:06 mbenjemaa

There is no way around this, updateAll bypasses model callbacks by directly sending a query to the database. You will need to update records one by one of you need to keep the log

lorenzo avatar Jun 11 '18 19:06 lorenzo

Thanks. Can you advice me how to to transform my code into an update one by one:

`if($this->request->is(['patch', 'post', 'put'])) { $ids = $this->request->data('data.AssetsAssignations.id'); $room_id = $this->request->data('room_id');

    $this->AssetsAssignations->updateAll(
        ['room_id ' => $room_id ],
        ['id IN' => $ids]
    );

}`

mbenjemaa avatar Jun 11 '18 19:06 mbenjemaa

You will need to find by those ids, and then do a save(). I’ve done this in the past from a cli worker, so that I don’t reach the max time limit in the web. I can paste a larger example here tomorrow

lorenzo avatar Jun 11 '18 20:06 lorenzo

Perfect. I will try it by myself. I appreciate if you paste your code when available.

mbenjemaa avatar Jun 11 '18 20:06 mbenjemaa

@mbenjemaa You have to do something like:

// First find entities with condition
$assetAssignments = $this->AssetsAssignations->find()->where(['id IN' => $ids]);

// And then loop through each entity to save it individually
foreach ($assetAssignments as $assetAssignment) {
    $entity = $this->AssetsAssignations->patchEntity(
        $entity,
        ['room_id' => $room_id]
    );
    $this->AssetsAssignations->save($entity);
}

ishanvyas22 avatar May 22 '20 12:05 ishanvyas22

I also wanted to keep an audit of entities using Table::updateAll(). I've overridden \App\Model\Table\AppTable::updateAll to record an audit log. Its not bullet-proof given the nature of updateAll() but for the majority of cases where you're updating a single entity based on a single id this should suffice. Means not having to retrieve the entity and re-save it, that seems overkill.

public function updateAll($fields, $conditions): int
{
    $rowCount = parent::updateAll($fields, $conditions);

    // we've updated one or more records, try to create an audit log
    if($rowCount > 0){

        if(isset($conditions['id']) && is_int($conditions['id'])){

            /** @var \Cake\Http\ServerRequest $request */
            $request = Router::getRequest();

            $data = [
                'user_id'       => $this->loggedInUserId,
                'url'           => $request->getRequestTarget(),
                'ip'            => $request->clientIp(),
                'timestamp'     => Time::now()->format('Y-m-d H:i:s'),
                'transaction'   => (string)Uuid::uuid4(),
                'type'          => 'update',
                'primary_key'   => $conditions['id'],
                'source'        => Inflector::singularize($this->getAlias()),
                'changed'       => json_encode($fields),
            ];

            $auditTable = FactoryLocator::get('Table')->get('AuditLogs');
            $auditLog = $auditTable->newEntity($data);
            $auditTable->save($auditLog);
        }

    }

    return $rowCount;
}

chopstik avatar Aug 14 '20 14:08 chopstik

@mbenjemaa I forked the original project and added this feature... you can try it if you like :) https://github.com/kkdesilva/audit-trail

kkdesilva avatar Feb 09 '22 18:02 kkdesilva

I opened https://github.com/lorenzo/audit-stash/pull/73 for a discussion would be nice if some of the useful changes would be ported back into this one where they make sense.

Closing this then in favor of follow up PRs.

dereuromark avatar Jan 10 '24 10:01 dereuromark