Collaborative work / user tracking / How to prevent editing the same entry simultaneously?


#1

I have a multi user setup, where different persons could possibly edit the same entry at the same time. If person 1 saves the entry, person 2 has to be noticed, that the entry changed before she saves - and overwrites the changes from person 1.

Generally, I want to avoid as much user tracking as possible and I don’t want to slow down my application.

Did someone build anything like this before?

This job shouldn’t be too hard, but I don’t want to reinvent the wheel and there might be a lot of edge cases.

This is the sketch I wrote in the last two hours (not very dynamic, yet):

$app->on('cockpit.account.login', function($user) {

    $active_user = [[
        'user' => $user['user'],
        'name' => $user['name'],
        '_id' => $user['_id'],
    ]];

    $this->storage->save('cockpit/collab', $active_user);

});

$app->on('cockpit.account.logout', function($user) {

    $this->storage->remove("cockpit/collab", ['_id' => $user['_id']]);

});

$app->on('app.layout.contentbefore', function() {

    $this->storage->update('cockpit/collab', ['_id' => $this['user']['_id']], ['route' => $this['route']]);

    $users = $this->storage->find('cockpit/collab');

    echo '<div riot-mount><p>active users: ';
    foreach($users as $user) {
        if ($user['_id'] != $this['user']['_id']) {
            if ($user['route'] == $this['route']) {
                echo '<i class="uk-icon-warning" title="'.$user['name'].' is on the same page" data-uk-tooltip></i> ';
            }
            echo '<cp-gravatar alt="'.$user['name'].'" size="25" title="'.$user['name'].'" data-uk-tooltip></cp-gravatar> ';
        }
    }
    echo '</p></div>';

});

#2

It is on my to do list, but I need to figure out an elegant way to do this…it will get implemented in one of the next releases


#3

That would be a very interesting feature, there are some edge cases, but would say that something like below can do the job:

  1. Configuration can define a TTL for entry locks, e.g.:
content_lock:
  page: 3600 #1h
  blog: 7200 #2h
  1. User access entry, if collection type is in the config and there is no lock a new one is created (entry_id + user_id + timestamp)
  2. Another user access entry, if there is a lock and is not expired a message is displayed to the user
  3. Another user access entry, lock is expired, user can access entry
  4. A user with admin group access same entry and lock exists, a prompt is displayed to the user if he wants to break the lock

A possible issue with above is that we can end with n lock entries as cockpit doesn’t have a cron functionality, maybe a cli command can be used to remove expired locks


#4

Not final yet, but the implementation has started: https://github.com/agentejo/cockpit/commit/917ba5afdcb9e8504fa5fbedc0e4b76563a6c62e


#5

Nice.

Some thoughts…

  • Instead of the lock screen, the entry should be displayed with readonly access. Now I’m not able to display the data, just because someone else opened it.
  • It would be interesting, if the locking wouldn’t be per entry, but per field - but this could cause massive requests on larger forms.
  • What if the data changed via api call, e. g. from a different application? The entry can’t be locked in this case.
  • I thought about continuous checks, like the check-backend-session, that reloads the current data at regular intervals. --> Can cause a lot of traffic.

#6

Amazing @artur, let’s start it simple and then increase the complexity

@raffaelj, regarding your points:

  1. At least a message needs to be displayed to the user explaining the reason is not able to access
  2. Lock per field seems overcomplicating to me
  3. For API requests shall be the same if the entry is locked because you are working on it you don’t want it to be updated in background without you notice it, also remember, if that is configurable you can decide on the collection types, in such case usually you create collection types that are expected to be edited in the UI and collection types that are specifically to be created/edited by the API
  4. Yeah, in that case why not reuse the check-backend-session?

#7

Yes, point 3+4 needs to be solved. but it was already too late yesterday :wink:

@raffaelj I always try to implement the most simple possible solution and target the main issue first.

so in this case the most important thing is to prevent editing the same item by multiple users. a lock screen does the job perfectly for now.

Improvements can be made in future release iterations to not block other features/addons I have in mind.