]> BookStack Code Mirror - bookstack/blob - app/Util/DatabaseTransaction.php
Perms: Added transactions around permission effecting actions
[bookstack] / app / Util / DatabaseTransaction.php
1 <?php
2
3 namespace BookStack\Util;
4
5 use Closure;
6 use Illuminate\Support\Facades\DB;
7 use Throwable;
8
9 /**
10  * Run the given code within a database transactions.
11  * Wraps Laravel's own transaction method, but sets a specific runtime isolation method.
12  * This sets a session level since this won't cause issues if already within a transaction,
13  * and this should apply to the next transactions anyway.
14  *
15  * "READ COMMITTED" ensures that changes from other transactions can be read within
16  * a transaction, even if started afterward (and for example, it was blocked by the initial
17  * transaction). This is quite important for things like permission generation, where we would
18  * want to consider the changes made by other committed transactions by the time we come to
19  * regenerate permission access.
20  *
21  * @throws Throwable
22  * @template TReturn of mixed
23  */
24 class DatabaseTransaction
25 {
26     /**
27      * @param  (Closure(static): TReturn)  $callback
28      */
29     public function __construct(
30         protected Closure $callback
31     ) {
32     }
33
34     /**
35      * @return TReturn
36      */
37     public function run(): mixed
38     {
39         DB::statement('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED');
40         return DB::transaction($this->callback);
41     }
42 }