Bug 28739

Summary: Objects in notices should restrict the methods that can be called
Product: Koha Reporter: Nick Clemens (kidclamp) <nick>
Component: NoticesAssignee: Jonathan Druart <jonathan.druart>
Status: CLOSED FIXED QA Contact: Kyle M Hall (khall) <kyle>
Severity: normal    
Priority: P5 - low CC: 1joynelson, bjorn.nylen, dcook, fridolin.somers, jonathan.druart, kyle, lucas, m.de.rooy, martin.renvoize, nick, tomascohen
Version: unspecified   
Hardware: All   
OS: All   
See Also: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=19966
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=32442
Change sponsored?: --- Patch complexity: Small patch
Documentation contact: Documentation submission:
Text to go in the release notes:
Version(s) released in:
22.11.00
Circulation function:
Bug Depends on: 19966    
Bug Blocks:    
Attachments: Bug 28739: Ignore store, update and delete when called from Template Toolkit
[FOR DISCUSSION] Bug 28739: Add Koha::Object->read_only
Bug 28739: Execute the letter processing inside a transaction
Bug 28739: Execute the letter processing inside a transaction
Bug 28739: Execute the letter processing inside a transaction
Bug 28739: Execute the letter processing inside a transaction

Description Nick Clemens (kidclamp) 2021-07-22 14:49:52 UTC
Currently you can do something like:
[% biblio.delete %]

We should have a way to restrict this
Comment 1 Kyle M Hall (khall) 2021-07-23 12:15:43 UTC
Created attachment 123104 [details] [review]
Bug 28739: Ignore store, update and delete when called from Template Toolkit
Comment 2 Kyle M Hall (khall) 2021-07-23 12:16:09 UTC
Created attachment 123105 [details] [review]
[FOR DISCUSSION] Bug 28739: Add Koha::Object->read_only
Comment 3 Marcel de Rooy 2021-10-01 09:30:52 UTC
(In reply to Nick Clemens from comment #0)
> Currently you can do something like:
> [% biblio.delete %]
> 
> We should have a way to restrict this

Sure.
But I definitely like the idea, hahaha
Comment 4 Martin Renvoize (ashimema) 2021-10-01 10:15:49 UTC
Very interesting.. I like the readonly flag.. I wonder about how we identify all 'setters' however.. we have a few methods in objects that have actions at a distance.. we'd need to somehow catch those too.. somehow identifying them as setters for this case.
Comment 5 Jonathan Druart 2021-10-13 12:46:51 UTC
Created attachment 126190 [details] [review]
Bug 28739: Execute the letter processing inside a transaction
Comment 6 Jonathan Druart 2021-10-13 12:47:58 UTC
New patch for a KISS approach, still for discussion as I haven't stressed it much.

Why didn't we think about that before? Sounds like the more robust and simple solution :)
Comment 7 Marcel de Rooy 2021-10-13 13:15:04 UTC
(In reply to Jonathan Druart from comment #6)
> New patch for a KISS approach, still for discussion as I haven't stressed it
> much.
> 
> Why didn't we think about that before? Sounds like the more robust and
> simple solution :)

Hmm. I dont hear you talk about performance, deadlocks etc. ? You would do that for every single notice..
Comment 8 Kyle M Hall (khall) 2021-10-14 15:49:27 UTC
(In reply to Marcel de Rooy from comment #7)
> (In reply to Jonathan Druart from comment #6)
> > New patch for a KISS approach, still for discussion as I haven't stressed it
> > much.
> > 
> > Why didn't we think about that before? Sounds like the more robust and
> > simple solution :)
> 
> Hmm. I dont hear you talk about performance, deadlocks etc. ? You would do
> that for every single notice..

Jonathan, can you run some tests to get some metrics?

I think it's safe to assume attempts at db changes will be rare. I'd be interested how much time the transaction wrap adds when no updates take place. I'm hoping the answer is little to none!

Considering you might send thousands of overdue, due and predue notices a night, it would be nice to have metrics over that kind of range.
Comment 9 Marcel de Rooy 2021-10-15 15:15:53 UTC
Another thought: What about having another more restricted mysql user context for these kind of things? Only reading.
Was thinking about Reporting too for that matter.

But code wise it would require a bit more discipline to use the right db connection etc. Safer, not nicer?
Comment 10 Jonathan Druart 2022-02-10 14:13:48 UTC
*** Bug 30071 has been marked as a duplicate of this bug. ***
Comment 11 David Cook 2022-02-11 00:03:38 UTC
(In reply to Marcel de Rooy from comment #9)
> Another thought: What about having another more restricted mysql user
> context for these kind of things? Only reading.
> Was thinking about Reporting too for that matter.

+1

I've been wanting a read-only database connection for a while. I was just thinking about for Reports, but this would be another good use case. (It would be good to be able to specify a different endpoint as well for a clustered DB setup where you have read-only nodes).

> But code wise it would require a bit more discipline to use the right db
> connection etc. Safer, not nicer?

We might need to do some re-factoring, but after reviewing https://metacpan.org/pod/DBIx::Class::Schema it looks like it shouldn't be too hard to manage multiple connections.
Comment 18 Jonathan Druart 2022-02-11 08:40:20 UTC
Created attachment 130482 [details] [review]
Bug 28739: Execute the letter processing inside a transaction
Comment 19 Jonathan Druart 2022-02-11 08:43:20 UTC
I still think that the transaction is the best (efficient and easy to implement) we can do. We should not care about performance here, especially when the only bit that could suffer are cronjobs.
Comment 20 Jonathan Druart 2022-02-11 08:44:16 UTC
David, you discussed everything but the last suggestion (I admit that the patch was confusing, it embedded non-related stuffs).
Comment 21 Björn Nylén 2022-02-11 14:34:14 UTC
Chiming in, did some back to back testing of the overdue_notices.pl on our test database. Generated ~480 notices from ~1000 overdue items. No real world difference with or without processing inside a transaction. Both finished in 48-50s when running a few times in sequence.
Comment 22 Jonathan Druart 2022-02-11 15:28:41 UTC
Thanks for the feedback, Björn.

I am considering this version ready for signoff.
Comment 23 Martin Renvoize (ashimema) 2022-05-20 10:31:26 UTC
Created attachment 135236 [details] [review]
Bug 28739: Execute the letter processing inside a transaction

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Comment 24 Martin Renvoize (ashimema) 2022-05-20 10:32:43 UTC
Oop, I lost track of this one.

Really glad to see someone did some performance testing.. I've just confirmed the same.. for me the impact was imperceivable.

Works as expected and is covered by tests (and passes QA script too).

Signing off
Comment 25 Marcel de Rooy 2022-05-22 14:13:02 UTC
(In reply to Björn Nylén from comment #21)
> Chiming in, did some back to back testing of the overdue_notices.pl on our
> test database. Generated ~480 notices from ~1000 overdue items. No real
> world difference with or without processing inside a transaction. Both
> finished in 48-50s when running a few times in sequence.

Great to hear, Bjorn.
But I think that it is not all there is to say about performance.
The point is imo: how are other processes that touch the same table hindered by all transactions that process_message_queue might start (per notice)?
In a normal situation without [% branch.delete %] stuff, there is nothing to rollback. So I guess that shouldnt be a big thing. (Can we prove that too?)

But we are testing edge cases under security. So what would be the impact on a script that does branch updating while you run these 500 notices with a branch delete creating 500 transactions and rollbacks? 
The penalty here could well be less imperceivable ;)
Still not a real-life situation. Perhaps anyone else has a better idea to test?
Comment 26 Kyle M Hall (khall) 2022-07-01 10:58:01 UTC
Created attachment 136804 [details] [review]
Bug 28739: Execute the letter processing inside a transaction

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Comment 27 David Cook 2022-07-04 00:39:04 UTC
(In reply to Jonathan Druart from comment #6)
> New patch for a KISS approach, still for discussion as I haven't stressed it
> much.
> 
> Why didn't we think about that before? Sounds like the more robust and
> simple solution :)

Oh that's clever! 

(In reply to Martin Renvoize from comment #4)
> Very interesting.. I like the readonly flag.. I wonder about how we identify
> all 'setters' however.. we have a few methods in objects that have actions
> at a distance.. we'd need to somehow catch those too.. somehow identifying
> them as setters for this case.

I'm trying to think if this could still be an issue. In theory, all direct database changes would be nullified by the rollback. 

I suppose the actions at a distance to worry about would be API/network calls, file system changes, and anything that doesn't directly relate to the database.

This is where a granular authorization layer would be handy. But that would be a huge project on its own.
Comment 28 Martin Renvoize (ashimema) 2022-07-04 07:38:10 UTC
Hmm, it just occured to me, I didn't test this in conjunction with bug 19966... Or rather for the passing in an object case.  I'm reasonably sure it'll still work as expected, but may be worth adding a test for to make sure?
Comment 29 Tomás Cohen Arazi (tcohen) 2022-07-08 19:38:49 UTC
Pushed to master for 22.11.

Nice work everyone, thanks!
Comment 30 Lucas Gass (lukeg) 2022-08-23 15:29:11 UTC
Missing dependencies for 22.05, no backport