
John Heenan
Members-
Posts
79 -
Joined
-
Last visited
-
Days Won
2
Everything posted by John Heenan
-
Thanks for the report. For others, the attched file is 9.2MB of deprecated messages logged mainly from files originating in vendors/blesta/h2o/h2o directory. Below I deal with a specific fix for a reported message and an example of an appoach that made 80 IDE reported error messages disappear for a single file with a two line fix, that may also be reported in messages. A specific fix that fixed five errors in one go when fixing one: Here is one of the reported messages: ... general.NOTICE: E_DEPRECATED: ...{"code":8192,"message":"Creation of dynamic property H2o_Token::$type is deprecated","file":".../vendors/blesta/h2o/h2o/datatype.php","line":110} Download the source code, open in VSCode, use a php extension such as inteliphense and hover over red underlined part of line 110 to see undefined property type message. All five red lines disappear with one line added: protected mixed $type, $content, $result, $position; A more general approach that fixed 80 reported IDE errors in one go: There may be an incredibly easy to fix a lot more very quickly that I have noted to try. Just poking around within VSCode IDE shows file components/invoice_templates/perforated_invoice/perforated_invoice_pdf.php has 81 problems: Who wants to fix problems like this? However, with a change of two lines from to I can make 80 of 81 reported problems disappear.
-
This bug has alredy been fixed in Blesta 5.10.0-b2 beta, which was released nine days ago. I missed the release because b2 beta was not announced in the Blesta software feed reader. The fix used is the same as a shorter fix included in a post by me below. The fix I included for the upgrade/downgrade bug is also included in b2 beta. Thanks Blesta
-
Blesta: 5.10.0.b1 PHP: 8.2.18 OS: Debian 12.5 Line 871 in Virtualmin module file virtualmin.php, in editService function, now causes an error instead of a deprecation message with php 8.2.17, with array_key_exists: if (!array_key_exists($key, $service_fields) || $vars[$key] != $service_fields->$key) { $service_fields is a stdClass, not an array. Reference for array_key_exists is at https://www.php.net/manual/en/function.array-key-exists.php One line fix is : if (!property_exists($service_fields, $key) || $vars[$key] != $service_fields->$key) {
-
One line fix for 5.10beta1 Webhooks failing when using cache
John Heenan replied to John Heenan's topic in Bugs
This fix, however, does not fix the issue of file present but uninstalled plugins having their events read and newly instralled plugins having to wait for the cache to be renewed for their events to be rrecognised. Cache renewal is forced with cache deleion. -
With Blesta 5.10beta1, an incoming Webhook fails if the cache is used. The cache is incorrectly constructed. Following is a one line fix. Edit line in plugin file webhooks/models/webhook_events.php FROM 'file' => $file->getRealPath(), TO 'file' => (new ReflectionClass($class))->getFileName(), This inserts the correct file name for later use within the cache. The reason the workaround, which is to delete the cache, works is that when the cache is constructed the correct required file gets included in order to construct the cache, along with many others, from using @include_once $file->getRealPath(); earlier. The $file variable is stale when used as above. Using reflection avoids having to construct an earlier mapping of each found Observer class to the file name it came from.
-
With Blesta 5.10beta1, incoming Webhook call backs with GET and POST have been confirmed to work with a workaround (link at end). POSTJSON does not work. Following is a one line fix. Edit line in file controllers/trigger.php FROM $params = json_decode($post); TO $params = json_decode($post, true); Explanation for fix: from https://www.php.net/manual/en/function.json-decode.php, setting the second paarmeter to true guarantess the decoded json will be returned as an associative array instead of an object. Currently a workaroud is required to get incoming Webhooks to work. Information at
-
For 5.10beta1, Webhooks cache must not exist for incoming webhook to work
John Heenan replied to John Heenan's topic in Bugs
Both GET and POST for incoming webhooks works. POSTJSON for incoming webhook does not work without alteration of source code as the incoming JSON parameters are passed as a class object, not an array. -
For 5.10beta1, Webhooks cache must not exist for incoming webhook to work
John Heenan replied to John Heenan's topic in Bugs
The name of the event to form an incoming callback for in Webhooks is WebhooksIncomingExample.add The cache has to be deleted twice: once to even view the event to register the callback, a second time to successfuly obtain a result (with repeat deletion). More informration in topic linked to in above post. -
Blesta: 5.10beta1 PHP: 8.2.17 OS: Debian (stable, bookworm) Attached is a zip file of a plugin called webhhook_incoming_example, link webhooks_incoming_example.zip, that can be used to demonstrate an incoming webhook. Problem is the webhook only works ONCE after the webooks cache has been deleted, such as with command: rm cache/?/plugins/webhooks/* After calling once the cache is recreated and just an empty answer is returned, while the cache exists. This suggets there is a Webhooks cache bug. Whatever is recorded and read back from the cache is not reconstructed to its original pre saved form. If an oncoming GET webhook has been setup with callback 'webhooksexampleadd', then the following URI path can be used to add two integers a and b with values 1 and 2: /admin/plugin/webhooks/trigger/index/webhooksexampleadd?a=1&b=2 The answer after cache is deleted is returned as {"__return__":{"a":1,"b":2,"c":"a (1) + b (2) = c (3)"},"a":1,"b":2} The answer, until cache is deleted again is [ ] There is more information with images in topic at
-
Some notes on progress. 1. I added in the following two functions below the automatically generated getEvents() function in sample_a_plugin.php (part of SampleAPlugin class) public function SampleaAdd(EventInterface $event) { $params = $event->getParams(); $this->logger->info("SampleaAdd $params", [$params]); $a = (int) ($params['a'] ?? 0); $b = (int) ($params['b'] ?? 0); $c = $a + $b; $resultadd['a'] = $a; $resultadd['b'] = $b; $resultadd['c'] = "a ($a) + b ($b) = c ($c)"; $event->setReturnValue($resultadd); } public function triggerEvent($name, array $params = []) { $this->logger->info("triggerEvent", [$name, $params]); $eventFactory = new EventFactory(); $eventListener = $eventFactory->listener(); $eventListener->register($name, [$this, $name]); $event = $eventListener->trigger($eventFactory->event($name, $params)); // Get the event return value $returnValue = $event->getReturnValue(); // Put return in a special index $return = ['__return__' => $returnValue]; // Any return values that match the submitted params should be put in their own index to support extract() calls if (is_array($returnValue)) { foreach ($returnValue as $key => $data) { if (array_key_exists($key, $params)) { $return[$key] = $data; } } } return $return; } 2. I left the SampleAObserver class where I had previously added it in as above (at the end of sample_a_plugin.php and outside SampleAPlugin class). 3. I could only get incoming webbhook events triggered with a GET request. A POST_JSON request causes confusion because an object gets passed through instead of an array. I could not get a plain POST with parameters recognised, the parameters were ignored. 4. The incoming webhook only work ONCE after the cache is busted. After this the event is not triggered again until the cache is busted again. 5. In my example, setting an outgoing POST_JSON webhook for the same incoming webhook resulted in the data form the incoming request getting echoed, not the results of the event triggered. This makes sense. The triggerEvent function can be expanded to fire a second 'after' event which can include both the original paremeters and the result, which can be subscribed to instead. 6. The outgoing webhook, which echoes incoming parameters, only activates if if the event is triggered as above. Hence the same requirement to bust the cache is required. 7. Following is the result of making a GET request to the incoming webhook to trigger the 'Sample A' add event to add 1 and 2 with URI path /admin/plugin/webhooks/trigger/index/SampleaAdd?a=1&b=2 8. The result shown from above to add 1+2 is {"__return__":{"a":1,"b":2,"c":"a (1) + b (2) = c (3)"},"a":1,"b":2}. Again, it will only work once after each cache bust as above. 9. So, I did manage to simplify as noted above. All additions are to a single file and there is no use of a load function to include the Observer derived class. Ironically I have not so far being able to trigger incoming webhook events in the domain module or in core events.
-
A quick review of Webhooks source code reveals why the bugs exist. In fact it was a review of the Webhooks source code that prompted tests to confirm these bugs do exist, rather than behavioural observations. I was lucky I reviewed the code before starting tests. Just to be clear, 'Sample A' exists to prove bugs and does not include a triggerEvent function, but it can easily be added into a top level model file. Blesta likes to keep Observer derived classes in separate files and include these classes in parent triggerEvent functions through a load mechansim. The triggerEvent function is required for incoming Webhooks and I assume other functionality. Also the use of an Observer derived class, as above, is also required for Webhooks functionality and I also assume other functionality. It does not matter what file it is on as long it is in a plugin top level .php file. While Observer derived classes in separate files is fine for complex core functionaliy, I would personally like to see use use of a less complex mechanism, like including the Observer class in the same top level model file as the triggerEvent function for simpler use cases, while keeping an option to change.
-
How to reproduce the two bugs above with one sample generated plugin: Using the extensions generator plugin, create an advanced Form Type Plugin with name 'Sample A' and add in an event 'SampleA.add' with callback SampleaAdd Adding in event: The plugin that was generated and that can now be edited and regenerated: The plugin without being installed: Just exists as files in plugins directory: Add in the following to the end of file sample_a_plugin.php: use Blesta\Core\Util\Events\Observer; class SampleAObserver extends Observer { public static function add(EventInterface $event) { return parent::triggerEvent($event); } } Delete the webhooks record of available events with rm cache/1/plugins/webhooks/* Without installing the Sample A plugin: 1) Refresh Webhooks Tools page anf click on '+' at top right for 'Add Webhook'. 2) Open the Event drop down list 3) Scroll to end The 'SampleA.add' event is listed as available despite plugin 'Sample A' not being installed: Install the plugin to confirm the event is recognised by Blesta: 1) Uninstall the plugin 2) Delete the sample_a directory in plugins 3) Refresh the Webhooks Tools page as above 4) The 'SampleA.add' event is still listed as available despite the plugin uninstalled and deleted from the file system Remove the Webhooks cache as before with rm cache/1/plugins/webhooks/* Refresh the Webhooks Tools page as before The 'SampleA.add' event is no longer listed as available
-
Blesta: 5.10.beta1 PHP: 8.2.18 OS: Debian 12.5 (stable, bookworm) Webhooks reads available events from files with Observer derived classes in core/Util/Events/Observers directory and in top level plugins directories. 1) Even if a plugin is not installed (but its files are present), or is installed but disabled, Webhooks still incorrectly reads these file for available events. 2) Webhooks caches its list of availabe events using the Cache class from minphp. Once the cache is setup it is not renewed again. This mean without manually deleting the cache, the cache cannot read new available events from new or edited plugins. Also it cannot remove events no longer available.
-
To write new plugins using incoming Webhooks, there is enough to adapt from within existing Blesta source code plugins, without further examples. We don't need to register or include any file in the /installdir/core/Util/Events/Observers/ directory and we don't need to include any handlers in the /installdir/core/Util/Events/Handlers/ directory. Everything can be kept within the plugins directory. The domains plugin is the only plugin that I am aware of that triggers events and implements self containment as above. The orders plugin is an example of a plugin that subscribes to triggered domain events. The webhooks plugin subscribes to domain events as a proxy for outgoing webhooks. The webhooks plugin can trigger domain events with an incoming webhook. These will be seen by the orders plugin, although there is little point in this as information does not come from the original intended source. For incoming webhooks it is better to write a plugin specifically to be triggered by an incoming webhook and is a powerful new feature. For example events can be triggered that a server is running low on disk space, that RAM usage is too high, that another server cannot be pinged. The particular advantage of informing Blesta of such alarms is that they can be centrally logged by Blesta, as well as keep others informed of issues who are on a support desk using Blesta.
-
My impression from looking at source code and documentation is that the events listed for triggering (incoming) or triggered (outgoing) in the Webhooks plugin are from a central register of events in files in the /installdir/core/Util/Events/Observers/ directory. These events have predefined handlers, either in /installdir/core/Util/Events/Handlers/ or in plugins. The Webhooks plugin reads the contents of files in /installdir/core/Util/Events/Observers/ directory to determine what these events are and caches its results. It adds itself in as an additional handler for these events (if configured to do so by settings for Webhooks) and then further dispactches them through registered outgoing webhooks we have added in. For registered incoming webhooks we add in, it simply triggers the event and passes on data. So I guess to properly make use of incoming webhooks we need to write our own plugins and make sure the events they are meant to handle are listed properly in a file in the /installdir/core/Util/Events/Observers/, otherwise Webhooks won't know about our events. A full simple minimal example would be greatly appreciated.
-
If you use https://github.com/btcpayserver/btcpayserver-docker then something like the following can be used to add in ltc, dogecoin, dash and monero. I have not tried it so I don't know how much of it will work. Enabling even one coin at a time puts a heavy strain on server at the start of catching up with its blockchain. It is not just a matter of downloading, the blockchain needs to be verified and a pool of UTXOs (chainstate) needs to be built up. So while you can enable multiple coins at one time, its not ideal. # to see current settings exported in environment set | grep BTCPAYGEN # do not run this sequence one after another. enable one coin only at a time and wait for its blockchain to catch up # add in ltc btcpay-down.sh export BTCPAYGEN_CRYPTO2=ltc cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i # add in dogecoin btcpay-down.sh export BTCPAYGEN_ADDITIONAL_FRAGMENTS="$BTCPAYGEN_ADDITIONAL_FRAGMENTS;dogecoin" export BTCPAYGEN_CRYPTO3=doge cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i # add in dash btcpay-down.sh export BTCPAYGEN_ADDITIONAL_FRAGMENTS="$BTCPAYGEN_ADDITIONAL_FRAGMENTS;dash" export BTCPAYGEN_CRYPTO4=dash cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i # add in monero # see also https://sethforprivacy.com/guides/accepting-monero-via-btcpay-server/ btcpay-down.sh export BTCPAYGEN_ADDITIONAL_FRAGMENTS="$BTCPAYGEN_ADDITIONAL_FRAGMENTS;monero" export BTCPAYGEN_CRYPTO5=xmr cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i # to only allow btc and ltc btcpay-down.sh export BTCPAYGEN_EXCLUDE_FRAGMENTS="dogecoin;dash;monero" cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i # to only allow btc, ltc and dogecoin btcpay-down.sh export BTCPAYGEN_EXCLUDE_FRAGMENTS="dash;monero" cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i # to reallow dash and monero btcpay-down.sh export BTCPAYGEN_EXCLUDE_FRAGMENTS="" cd $BTCPAY_BASE_DIRECTORY/btcpayserver-docker . ./btcpay-setup.sh -i
-
With regard to outgoing callbacks/Webhooks: I will answer this question myself. Yes there is and it is dead easy, provided your web server logs are safe from being pried at and provided SSL is used. Here is an example for a POST JSON method. For an outgoing callback use an entry similiar to https://someserver.com/cgi-bin/dumpalltoemail.cgi?server=someotherserver&service=blesta5.10.beta1&event=Packages.editAfter&apiKey=somerandomkey The receving web server can decode this to server=someotherserver service=blesta5.10.beta1 event=Packages.editAfter apiKey=somerandomkey The apiKey (or something else) can be used to prevent fake callbacks and can even be interpreted to allow a privilege level. However URL encoding rules need to be followed and it is necessary to double checked Blesta does not mangle the callback entry. At an rate, the above worked as is (with someserver and someotherserver changed). In addition, environment variables passed through by the web server can be checked, such as REMOTE_ADDR. The json from the POST is in the body of the request as a string and there were no problems decoding the body back into json. I proved this by decoding the string and then encoding it again (this time as a 'pretty' string). With regard to incoming callbacks/Webhooks: Again, I will answer this myself. Blesta has good documentation. The relevant link to start from is at https://docs.blesta.com/display/dev/Events
-
Better still Better still, can you tell us how we can register events of our own choosing for triggering and subscribing to? I have changed the title of this topic to better reflect the current issue
-
@Kurogane, if you do want an invitation to open a store, your tests are sucessful with LTC anf you want to try othe altcoins then I will enable them in order of your choice until I run out of hard drive space for storing their blockchains. Currently I have three BTCPay running on three servers, only one of which has enough hard drive space for extra altcoins and I plan on letting this server go in the next few weeks.
-
Sorry, I don't hold LTC or any of the other altcoins you showed. Nor do I plan to in the future. I don't have anything against them though. If you want I can send you an invite to open your own store for a few days. You can then add in xpubs for Bitcoin and LTC and even use Lightning with an external node or with Breez or with Blink, as I have enabled these extra plugins in BTCPay. Of course I can make off with your Breez and Blink funds, so you would need to trust me. But I could not make off with youe BTC and LTC funds, if you use xpubs. You can generate your own invoice and pay yourself. If you still run Blesta you can try and see what happens when you comment out line 268. I hope this is acceptable.