? ? Success

User tests: Successful: Unsuccessful:

avatar Bakual
Bakual
12 Sep 2020

We discussed this in Glip today, so I threw together kind of a proof of concept here.

I think we all encountered once an item which was edited by someone else, and that one just closed the browser or hit the back button instead of saving or canceling. Leaving the item checked out for eternity. It then needs a superuser to check that in again.

Summary of Changes

This PR adjusts the checkout method so it checks if the user who locked the item actually still has an active session or if he went away long time ago.
It does that by quering the #__session table, fetching the newest entry for that userid and then calculates of that session is expired or not.

If there is no session anymore (eg the user logged out) or the session is expired, the checkout method will first check in the item and then regulary check it out again with the active user.

Testing Instructions

  • Edit an item and then close the browser window, leaving the item checked out.
  • Wait 15 minutes (depending on the lifetime setting) so the session expires.

OR

  • Edit an item, hit the back button of your browser and the log out the user.

THEN

  • In backend, try to edit the item with a different user.

Actual result BEFORE applying this Pull Request

You get an error that the item is checked out.

Expected result AFTER applying this Pull Request

The lock is still present, but you're able to edit the item neverthless.

Documentation Changes Required

Maybe, don't know if that is documented somewhere.

Caveats

In Glip, it was mentioned that this may not work anymore in J4 as the session table is not always populated. Depending on session handler, it may be empty.

The checkout is only cleared once you try to edit the item. Before you try to edit, the lock icon is still there, even if the session is expired.

Also, currently it will only work in backend, as in frontend to my knowledge you don't get an edit link at all if the item is checked out. This could be changed of course.

It was also suggested to use a different approach. Eg using the session garbage collector. Maybe someone has a good idea how it could be achieved better.
The critical point is that you need to be able to somehow match a userid to a session. And you need to know which table to manipulate with which fields (checked_out may).

Please give also feedback if that is even a desired behavior.

avatar Bakual Bakual - open - 12 Sep 2020
avatar Bakual Bakual - change - 12 Sep 2020
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 12 Sep 2020
Category Libraries
avatar Hackwar
Hackwar - comment - 12 Sep 2020

Regardless of the solution, we are not accepting new features to Joomla 3. So this PR would have to be made against the 4.0-dev branch instead.

avatar Bakual
Bakual - comment - 12 Sep 2020

Sure. In J3 I just knew where to do it. In J4 I don't know yet. So for an RFC that will have to do.

avatar nibra
nibra - comment - 12 Sep 2020

This functionality belongs in the session garbage collection (or wherever sessions are marked as expired).

Ideally, checking out an item will emit an event for a listener that registers that item. Releasing the item by saving or cancelling the edit process emits an event for a listener that unregisters the item. The session cleanup process emits another event on closing a session (as does the logout) for a listener that checks-in all items registered with that session.

Thus, the lock icon keeps its meaning.

avatar Bakual
Bakual - comment - 13 Sep 2020

I like the idea with the events.

The listener doesn't need to register the items as we already do that in the table when checking out the item. It wouldn't make much sense to tie the lock to a specific session anyway as the user may switch browsers and keep editing the same item or switch the application (eg from backend to frontend) or even device.

If the cargabe collector can pass the userid to the event, then I think it would be sufficient if a component can listen to the "unregister" event (with a component specific plugin or a dedicated helper method) and check-in all items checked-out by that user. That would be a rather simple SQL command in that case.

We would have to be sure it was the last active session of that userid, if other sessions are still active (eg in another browser or another client) we shouldn't check-in the items.

But I haven't looked at that cargabe collector method yet. Is it able to provide that information to the event? We'd need the userid and if another session is still active for that userid.
If not we indeed need the register and unregister events and a plugin needs to store the session and table information when editing an item.

avatar Fedik
Fedik - comment - 13 Sep 2020

Another way could be, is to check how old the date in "check in" column.
Since the "check in" date are updates on every "save action", we could determine if user still "aktive"
Something like:

if (time_now - check_in_time) >  session_time * 2:
  User is inactive

It not 100% accurate, but could work also :)

avatar Bakual
Bakual - comment - 13 Sep 2020

Yep, that works. Plugins like https://extensions.joomla.org/extension/autocheckin/ work like that.
However there are several drawbacks:

  • Sessions are kept forever when the user has an editor open. The keepalive JS takes care of that. So the checkout could time out while the user is still actively editing the item (even without saving it). That would basically make the checkout useless.
  • The mentioned plugin has a performance impact as it does run several database queries on each pageload. That's not very efficient. Also it only works for the tables it checks (articles, menu, modules, plugins), it doesn't work for all other items. That's why I wanted to do something in the checkout method - but then the lock icons are not cleared beforehand.
avatar jiweigert
jiweigert - comment - 13 Sep 2020

Just an idea,
Inform the user in an existing session, that there is an object still checked-out, with the option to either discard it or edit it.
This could be additional done onlogin / onlogout.
Administrator/ Super User can set a max-check-out time, which were presented to the user as a countdown-timer.
When the max-checkout-time is reached, the object is reverted to the last version and checked-in or, in case there is no version available, that object will be either disabled or just checked-in again.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/30625.
avatar Bakual
Bakual - comment - 13 Sep 2020

Inform the user in an existing session, that there is an object still checked-out, with the option to either discard it or edit it.

That would need a specific table where we store checked-out items per user. Otherwise we just don't know it without quering each database table - which for obvious reasons isn't going to happen on each pageload.
Also it doesn't help when the user just closes the browser.

When the max-checkout-time is reached, the object is reverted to the last version and checked-in or, in case there is no version available, that object will be either disabled or just checked-in again.

There would be nothing to revert or disable or whatever. "Checked Out" means the user started editing, but that is always done in the users browsers. The server doesn't know about the edited content until it is saved, and then it's live right away.
So all that has to be done is clearing the "checked_out" field in the database table.

avatar jiweigert
jiweigert - comment - 13 Sep 2020

Ok, but in combination with the upcoming workflow feature in 4.0, isn't
there already a table for that?
I mean, a kind of default workflow (just the user has to approve) and in
the way that the user had hit Save at least once, would help here?

And in the case (with that default workflow) that the user haven't saved
even once so the changes are lost, he just hit discard or the timeout runs
out and the object is checked-in again...

Just my 2c ....

Thomas Hunziker notifications@github.com schrieb am So., 13. Sep. 2020,
21:10:

Inform the user in an existing session, that there is an object still
checked-out, with the option to either discard it or edit it.

That would need a specific table where we store checked-out items per
user. Otherwise we just don't know it without quering each database table -
which for obvious reasons isn't going to happen on each pageload.
Also it doesn't help when the user just closes the browser.

When the max-checkout-time is reached, the object is reverted to the last
version and checked-in or, in case there is no version available, that
object will be either disabled or just checked-in again.

There would be nothing to revert or disable or whatever. "Checked Out"
means the user started editing, but that is always done in the users
browsers. The server doesn't know about the edited content until it is
saved, and then it's live right away.
So all that has to be done is clearing the "checked_out" field in the
database table.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#30625 (comment),
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AQNZU54PW32IFCZDWV4OKETSFUKKZANCNFSM4RJ4TTRQ
.

avatar Bakual
Bakual - comment - 3 Aug 2021

I'm closing this RFC as it is clear it is not going to work in J4 and I don't have the ressources and knowledge to deal with the garbage collector.

avatar Bakual Bakual - change - 3 Aug 2021
Status Pending Closed
Closed_Date 0000-00-00 00:00:00 2021-08-03 15:18:15
Closed_By Bakual
Labels Added: ? ?
Removed: ? ?
avatar Bakual Bakual - close - 3 Aug 2021

Add a Comment

Login with GitHub to post a comment