[mod] remove backward compatible code for passlib and force modern version
Undoing changes in CubicWeb---------------------------Many desktop applications offer the possibility for the user toundo its last changes : this *undo feature* has now beenintegrated into the CubicWeb framework. This document willintroduce you to the *undo feature* both from the end-user and theapplication developer point of view.But because a semantic web application and a common desktopapplication are not the same thing at all, especially as far asundoing is concerned, we will first introduce *what* is the *undofeature* for now.What's *undoing* in a CubicWeb application~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~What is an *undo feature* is quite intuitive in the context of adesktop application. But it is a bit subtler in the context of aSemantic Web application. This section introduces some of the maindifferences between a classical desktop and a Semantic Webapplications to keep in mind in order to state precisely *what wewant*.The notion transactions```````````````````````A CubicWeb application acts upon an *Entity-Relationship* model,described by a schema. This allows to ensure some data integrityproperties. It also implies that changes are made by all-or-nonegroups called *transactions*, such that the data integrity ispreserved whether the transaction is completely applied *or* noneof it is applied.A transaction can thus include more actions than just thosedirectly required by the main purpose of the user. For example,when a user *just* writes a new blog entry, the underlying*transaction* holds several *actions* as illustrated below :* By admin on 2012/02/17 15:18 - Created Blog entry : Torototo#. Created Blog entry : Torototo#. Added relation : Torototo owned by admin#. Added relation : Torototo blog entry of Undo Blog#. Added relation : Torototo in state draft (draft)#. Added relation : Torototo created by adminBecause of the very nature (all-or-none) of the transactions, the"undoable stuff" are the transactions and not the actions !Public and private actions within a transaction```````````````````````````````````````````````Actually, within the *transaction* "Created Blog entry :Torototo", two of those *actions* are said to be *public* andthe others are said to be *private*. *Public* here means that thepublic actions (1 and 3) were directly requested by the end user ;whereas *private* means that the other actions (2, 4, 5) weretriggered "under the hood" to fulfill various requirements for theuser operation (ensuring integrity, security, ... ).And because quite a lot of actions can be triggered by a "simple"end-user request, most of which the end-user is not (and does notneed or wish to be) aware, only the so-called public actions willappear [1]_ in the description of the an undoable transaction.* By admin on 2012/02/17 15:18 - Created Blog entry : Torototo#. Created Blog entry : Torototo#. Added relation : Torototo blog entry of Undo BlogBut note that both public and private actions will be undonetogether when the transaction is undone.(In)dependent transactions : the simple case````````````````````````````````````````````A CubicWeb application can be used *simultaneously* by different users(whereas a single user works on an given office document at agiven time), so that there is not always a single historytime-line in the CubicWeb case. Moreover CubicWeb providessecurity through the mechanism of *permissions* granted to eachuser. This can lead to some transactions *not* being undoable insome contexts.In the simple case two (unprivileged) users Alice and Bob makerelatively independent changes : then both Alice and Bob can undotheir changes. But in some case there is a clean dependencybetween Alice's and Bob's actions or between actions of one ofthem. For example let's suppose that :- Alice has created a blog,- then has published a first post inside,- then Bob has published a second post in the same blog,- and finally Alice has updated its post contents.Then it is clear that Alice can undo her contents changes and Bobcan undo his post creation independently. But Alice can not undoher post creation while she has not first undone her changes.It is also clear that Bob should *not* have thepermissions to undo any of Alice's transactions.More complex dependencies between transactions``````````````````````````````````````````````But more surprising things can quickly happen. Going back to theprevious example, Alice *can* undo the creation of the blog afterBob has published its post in it ! But this is possible onlybecause the schema does not *require* for a post to be in ablog. Would the *blog entry of* relation have been mandatory, thenAlice could not have undone the blog creation because it wouldhave broken integrity constraint for Bob's post.When a user attempts to undo a transaction the system will checkwhether a later transaction has explicit dependency on thewould-be-undone transaction. In this case the system will not evenattempt the undo operation and inform the user.If no such dependency is detected the system will attempt the undooperation but it can fail, typically because of integrityconstraint violations. In such a case the undo operation iscompletely [3]_ rollbacked.The *undo feature* for CubicWeb end-users~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~The exposition of the undo feature to the end-user through a Webinterface is still quite basic and will be improved toward agreater usability. But it is already fully functional. For nowthere are two ways to access the *undo feature* as long as the ithas been activated in the instance configuration file with theoption *undo-support=yes*.Immediately after having done the change to be canceled throughthe **undo** link in the message. This allows to undo anhastily action immediately. For example, just after havingvalidated the creation of the blog entry *A second blog entry* weget the following message, allowing to undo the creation...image:: /images/undo_mesage_w600.png:width: 600px:alt: Screenshot of the undo link in the message:align: centerAt any time we can access the **undo-history view** accessible from thestart-up page...image:: /images/undo_startup-link_w600.png:width: 600px:alt: Screenshot of the startup menu with access to the history view:align: centerThis view will provide inspection of the transaction and their (public)actions. Each transaction provides its own **undo** link. Only thetransactions the user has permissions to see and undo will be shown...image:: /images/undo_history-view_w600.png:width: 600px:alt: Screenshot of the undo history main view:align: centerIf the user attempts to undo a transaction which can't be undone orwhose undoing fails, then a message will explain the situation andno partial undoing will be left behind.This is all for the end-user side of the undo mechanism : this isquite simple indeed ! Now, in the following section, we are goingto introduce the developer side of the undo mechanism.The *undo feature* for CubicWeb application developers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~A word of warning : this section is intended for developers,already having some knowledge of what's under CubicWeb's hood. Ifit is not *yet* the case, please refer to CubicWeb documentationhttp://docs.cubicweb.org/ .Overview````````The core of the undo mechanisms is at work in the *native source*,beyond the RQL. This does mean that *transactions* and *actions*are *no entities*. Instead they are represented at the SQL leveland exposed through the *DB-API* supported by the repository*Connection* objects.Once the *undo feature* has been activated in the instanceconfiguration file with the option *undo-support=yes*, eachmutating operation (cf. [2]_) will be recorded in some special SQLtable along with its associated transaction. Transaction areidentified by a *txuuid* through which the functions of the*DB-API* handle them.On the web side the last commited transaction *txuuid* isremembered in the request's data to allow for imediate undoingwhereas the *undo-history view* relies upon the *DB-API* to listthe accessible transactions. The actual undoing is performed bythe *UndoController* accessible at URL of the form`www.my.host/my/instance/undo?txuuid=...`The repository side```````````````````Please refer to the file `cubicweb/server/sources/native.py` and`cubicweb/transaction.py` for the details.The undoing information is mainly stored in three SQL tables:`transactions` Stores the txuuid, the user eid and the date-and-time of the transaction. This table is referenced by the two others.`tx_entity_actions` Stores the undo information for actions on entities.`tx_relation_actions` Stores the undo information for the actions on relations.When the undo support is activated, entries are added to thosetables for each mutating operation on the data repository, and aredeleted on each transaction undoing.Those table are accessible through the following methods of therepository `Connection` object :`undoable_transactions` Returns a list of `Transaction` objects accessible to the user and according to the specified filter(s) if any.`tx_info` Returns a `Transaction` object from a `txuuid``undo_transaction` Returns the list of `Action` object for the given `txuuid`. NB: By default it only return *public* actions.The web side````````````The exposure of the *undo feature* to the end-user through the Webinterface relies on the *DB-API* introduced above. This impliesthat the *transactions* and *actions* are not *entities* linked by*relations* on which the usual views can be applied directly.That's why the file `cubicweb/web/views/undohistory.py` definessome dedicated views to access the undo information :`UndoHistoryView` This is a *StartupView*, the one accessible from the home page of the instance which list all transactions.`UndoableTransactionView` This view handles the display of a single `Transaction` object.`UndoableActionBaseView` This (abstract) base class provides private methods to build the display of actions whatever their nature.`Undoable[Add|Remove|Create|Delete|Update]ActionView` Those views all inherit from `UndoableActionBaseView` and each handles a specific kind of action.`UndoableActionPredicate` This predicate is used as a *selector* to pick the appropriate view for actions.Apart from this main *undo-history view* a `txuuid` is stored inthe request's data `last_undoable_transaction` in order to allowimmediate undoing of a hastily validated operation. This ishandled in `cubicweb/web/application.py` in the `main_publish` and`add_undo_link_to_msg` methods for the storing and displayingrespectively.Once the undo information is accessible, typically through a`txuuid` in an *undo* URL, the actual undo operation can beperformed by the `UndoController` defined in`cubicweb/web/views/basecontrollers.py`. This controller basicallyextracts the `txuuid` and performs a call to `undo_transaction` andin case of an undo-specific error, lets the top level publisherhandle it as a validation error.Conclusion~~~~~~~~~~The undo mechanism relies upon a low level recording of themutating operation on the repository. Those records are accessiblethrough some method added to the *DB-API* and exposed to theend-user either through a whole history view of through animmediate undoing link in the message box.The undo feature is functional but the interface and configurationoptions are still quite reduced. One major improvement would be tobe able to filter with a finer grain which transactions or actionsone wants to see in the *undo-history view*. Another criticalimprovement would be to enable the undo feature on a part only ofthe entity-relationship schema to avoid storing too much uselessdata and reduce the underlying overhead.But both functionality are related to the strong design choice notto represent transactions and actions as entities andrelations. This has huge benefits in terms of safety and conceptualsimplicity but prevents from using lots of convenient CubicWebfeatures such as *facets* to access undo information.Before developing further the undo feature or eventually revisingthis design choice, it appears that some return of experience isstrongly needed. So don't hesitate to try the undo feature in yourapplication and send us some feedback.Notes~~~~~..[1] The end-user Web interface could be improved to enable user to choose whether he wishes to see private actions...[2] There is only five kind of elementary actions (beyond merely accessing data for reading):***C** : creating an entity***D** : deleting an entity***U** : updating an entity attributes***A** : adding a relation***R** : removing a relation..[3] Meaning none of the actions in the transaction is undone. Depending upon the application, it might make sense to enable *partial* undo. That is to say undo in which some actions could not be undo without preventing to undo the others actions in the transaction (as long as it does not break schema integrity). This is not forbidden by the back-end but is deliberately not supported by the front-end (for now at least).