diff --git a/classes/sns_client.php b/classes/sns_client.php index 36e06a9..b92bc54 100644 --- a/classes/sns_client.php +++ b/classes/sns_client.php @@ -27,6 +27,10 @@ defined('MOODLE_INTERNAL') || die; +require_once(__DIR__ . '/../lib/aws-sns-message-validator/src/Exception/InvalidSnsMessageException.php'); +require_once(__DIR__ . '/../lib/aws-sns-message-validator/src/Message.php'); +require_once(__DIR__ . '/../lib/aws-sns-message-validator/src/MessageValidator.php'); + use Aws\Sns\Exception\InvalidSnsMessageException; use Aws\Sns\Message; use Aws\Sns\MessageValidator; diff --git a/lib/aws-sns-message-validator/LICENSE.md b/lib/aws-sns-message-validator/LICENSE.md new file mode 100644 index 0000000..8d53e9f --- /dev/null +++ b/lib/aws-sns-message-validator/LICENSE.md @@ -0,0 +1,141 @@ +# Apache License +Version 2.0, January 2004 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +## 1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 +through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the +License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled +by, or are under common control with that entity. For the purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract +or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software +source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, +including but not limited to compiled object code, generated documentation, and conversions to other media +types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, +as indicated by a copyright notice that is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) +the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, +as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not +include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work +and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any +modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to +Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to +submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of +electronic, verbal, or written communication sent to the Licensor or its representatives, including but not +limited to communication on electronic mailing lists, source code control systems, and issue tracking systems +that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been +received by Licensor and subsequently incorporated within the Work. + +## 2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare +Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +## 3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent +license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such +license applies only to those patent claims licensable by such Contributor that are necessarily infringed by +their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such +Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim +or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work +constitutes direct or contributory patent infringement, then any patent licenses granted to You under this +License for that Work shall terminate as of the date such litigation is filed. + +## 4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, + trademark, and attribution notices from the Source form of the Work, excluding those notices that do + not pertain to any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that + You distribute must include a readable copy of the attribution notices contained within such NOTICE + file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed as part of the Derivative Works; within + the Source form or documentation, if provided along with the Derivative Works; or, within a display + generated by the Derivative Works, if and wherever such third-party notices normally appear. The + contents of the NOTICE file are for informational purposes only and do not modify the License. You may + add Your own attribution notices within Derivative Works that You distribute, alongside or as an + addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be + construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license +terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative +Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the +conditions stated in this License. + +## 5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by +You to the Licensor shall be under the terms and conditions of this License, without any additional terms or +conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate +license agreement you may have executed with Licensor regarding such Contributions. + +## 6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, service marks, or product names of +the Licensor, except as required for reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +## 7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor +provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +## 8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless +required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any +Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential +damages of any character arising as a result of this License or out of the use or inability to use the Work +(including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has been advised of the possibility +of such damages. + +## 9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole +responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold +each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/lib/aws-sns-message-validator/NOTICE.md b/lib/aws-sns-message-validator/NOTICE.md new file mode 100644 index 0000000..9357419 --- /dev/null +++ b/lib/aws-sns-message-validator/NOTICE.md @@ -0,0 +1,16 @@ +# Amazon SNS Message Validator for PHP + + + +Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"). +You may not use this file except in compliance with the License. +A copy of the License is located at + + + +or in the "license" file accompanying this file. This file is distributed +on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. See the License for the specific language governing +permissions and limitations under the License. \ No newline at end of file diff --git a/lib/aws-sns-message-validator/README.md b/lib/aws-sns-message-validator/README.md new file mode 100644 index 0000000..f2045ed --- /dev/null +++ b/lib/aws-sns-message-validator/README.md @@ -0,0 +1,179 @@ +# Amazon SNS Message Validator for PHP + +[![@awsforphp on Twitter](http://img.shields.io/badge/twitter-%40awsforphp-blue.svg?style=flat)](https://twitter.com/awsforphp) +[![Total Downloads](https://img.shields.io/packagist/dt/aws/aws-php-sns-message-validator.svg?style=flat)](https://packagist.org/packages/aws/aws-php-sns-message-validator) +[![Build Status](https://img.shields.io/travis/aws/aws-php-sns-message-validator.svg?style=flat)](https://travis-ci.org/aws/aws-php-sns-message-validator) +[![Apache 2 License](https://img.shields.io/packagist/l/aws/aws-php-sns-message-validator.svg?style=flat)](http://aws.amazon.com/apache-2-0/) + +The **Amazon SNS Message Validator for PHP** library allows you to validate that +incoming HTTP(S) POST messages are valid Amazon SNS notifications. This library +is standalone and does not depend on the AWS SDK for PHP or Guzzle; however, it +does require PHP 5.4+ and that the OpenSSL PHP extension is installed. + +Jump To: +* [Basic Usage](_#Basic-Usage_) +* [Installation](_#Installation_) +* [About Amazon SNS](_#About-Amazon-SNS_) +* [Handling Messages](_#Handling-Messages_) +* [Testing Locally](_#Testing-Locally_) +* [Contributing](_#Contributing_) + +## Basic Usage + +To validate a message, you can instantiate a `Message` object from the POST +data using the `Message::fromRawPostData`. This reads the raw POST data from +the [`php://input` stream][php-input], decodes the JSON data, and validates +the message's type and structure. + +Next, you must create an instance of `MessageValidator`, and then use either +the `isValid()` or `validate()`, methods to validate the message. The +message validator checks the `SigningCertURL`, `SignatureVersion`, and +`Signature` to make sure they are valid and consistent with the message data. + +```php +isValid($message)) { + // do something with the message +} +``` + +## Installation + +The SNS Message Validator can be installed via [Composer][]. + + composer require aws/aws-php-sns-message-validator + +## Getting Help + +Please use these community resources for getting help. We use the GitHub issues for tracking bugs and feature requests and have limited bandwidth to address them. + +* Ask a question on [StackOverflow](https://stackoverflow.com/) and tag it with [`aws-php-sdk`](http://stackoverflow.com/questions/tagged/aws-php-sdk) +* Come join the AWS SDK for PHP [gitter](https://gitter.im/aws/aws-sdk-php) +* Open a support ticket with [AWS Support](https://console.aws.amazon.com/support/home/) +* If it turns out that you may have found a bug, please [open an issue](https://github.com/aws/aws-php-sns-message-validator/issues/new/choose) + +## About Amazon SNS + +[Amazon Simple Notification Service (Amazon SNS)][sns] is a fast, fully-managed, +push messaging service. Amazon SNS can deliver messages to email, mobile devices +(i.e., SMS; iOS, Android and FireOS push notifications), Amazon SQS queues,and +— of course — HTTP/HTTPS endpoints. + +With Amazon SNS, you can setup topics to publish custom messages to subscribed +endpoints. However, SNS messages are used by many of the other AWS services to +communicate information asynchronously about your AWS resources. Some examples +include: + +* Configuring Amazon Glacier to notify you when a retrieval job is complete. +* Configuring AWS CloudTrail to notify you when a new log file has been written. +* Configuring Amazon Elastic Transcoder to notify you when a transcoding job + changes status (e.g., from "Progressing" to "Complete") + +Though you can certainly subscribe your email address to receive SNS messages +from service events like these, your inbox would fill up rather quickly. There +is great power, however, in being able to subscribe an HTTP/HTTPS endpoint to +receive the messages. This allows you to program webhooks for your applications +to easily respond to various events. + +## Handling Messages + +### Confirming a Subscription to a Topic + +In order to handle a `SubscriptionConfirmation` message, you must use the +`SubscribeURL` value in the incoming message: + +```php +use Aws\Sns\Message; +use Aws\Sns\MessageValidator; +use Aws\Sns\Exception\InvalidSnsMessageException; + +// Instantiate the Message and Validator +$message = Message::fromRawPostData(); +$validator = new MessageValidator(); + +// Validate the message and log errors if invalid. +try { + $validator->validate($message); +} catch (InvalidSnsMessageException $e) { + // Pretend we're not here if the message is invalid. + http_response_code(404); + error_log('SNS Message Validation Error: ' . $e->getMessage()); + die(); +} + +// Check the type of the message and handle the subscription. +if ($message['Type'] === 'SubscriptionConfirmation') { + // Confirm the subscription by sending a GET request to the SubscribeURL + file_get_contents($message['SubscribeURL']); +} +``` + +### Receiving a Notification + +To receive a notification, use the same code as the preceding example, but +check for the `Notification` message type. + +```php +if ($message['Type'] === 'Notification') { + // Do whatever you want with the message body and data. + echo $message['MessageId'] . ': ' . $message['Message'] . "\n"; +} +``` + +The message body will be a string, and will hold whatever data was published +to the SNS topic. + +### Unsubscribing + +Unsubscribing looks the same as subscribing, except the message type will be +`UnsubscribeConfirmation`. + +```php +if ($message['Type'] === 'UnsubscribeConfirmation') { + // Unsubscribed in error? You can resubscribe by visiting the endpoint + // provided as the message's SubscribeURL field. + file_get_contents($message['SubscribeURL']); +} +``` + +## Testing Locally + +One challenge of using webhooks in a web application is testing the integration +with the service. Testing integrations with SNS notifications can be fairly easy +using tools like [ngrok][] and [PHP's built-in webserver][php-server]. One of +our blog posts, [*Testing Webhooks Locally for Amazon SNS*][blogpost], illustrates +a good technique for testing. + +> **NOTE:** The code samples in the blog post are specific to the message +> validator in Version 2 of the SDK, but can be easily adapted to using this +> version. + +### Special Thank You + +A special thanks goes out to [Julian Vidal][] who helped create the [initial +implementation][] in Version 2 of the [AWS SDK for PHP][]. + +[php-input]: http://php.net/manual/en/wrappers.php.php#wrappers.php.input +[composer]: https://getcomposer.org/ +[source code]: https://github.com/aws/aws-php-sns-message-validator/archive/master.zip +[sns]: http://aws.amazon.com/sns/ +[ngrok]: https://ngrok.com/ +[php-server]: http://www.php.net/manual/en/features.commandline.webserver.php +[blogpost]: http://blogs.aws.amazon.com/php/post/Tx2CO24DVG9CAK0/Testing-Webhooks-Locally-for-Amazon-SNS +[Julian Vidal]: https://github.com/poisa +[initial implementation]: https://github.com/aws/aws-sdk-php/tree/2.8/src/Aws/Sns/MessageValidator +[AWS SDK for PHP]: https://github.com/aws/aws-sdk-php + +## Contributing + +We work hard to provide a high-quality and useful SDK for our AWS services, and we greatly value feedback and contributions from our community. Please review our [contributing guidelines](./CONTRIBUTING.md) before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. diff --git a/lib/aws-sns-message-validator/readme_moodle.txt b/lib/aws-sns-message-validator/readme_moodle.txt new file mode 100644 index 0000000..22876e2 --- /dev/null +++ b/lib/aws-sns-message-validator/readme_moodle.txt @@ -0,0 +1,7 @@ +Instructions to import/update aws-sns-message-validator library into tool_emailutils: + +Update aws-sns-message-validator library +1. Download the latest aws-sns-message-validator library package from https://github.com/aws/aws-php-sns-message-validator +2. Copy the src directory to /admin/tool/emailutils/lib/aws-sns-message-validator/src folder +3. Copy the associated files LICENCE, README.md etc. to aws-sns-message-validator directory +4. Update version diff --git a/lib/aws-sns-message-validator/src/Exception/InvalidSnsMessageException.php b/lib/aws-sns-message-validator/src/Exception/InvalidSnsMessageException.php new file mode 100644 index 0000000..289c13b --- /dev/null +++ b/lib/aws-sns-message-validator/src/Exception/InvalidSnsMessageException.php @@ -0,0 +1,9 @@ +getBody()); + } + + /** + * Creates a Message object from a JSON-decodable string. + * + * @param string $requestBody + * @return Message + */ + public static function fromJsonString($requestBody) + { + $data = json_decode($requestBody, true); + if (JSON_ERROR_NONE !== json_last_error() || !is_array($data)) { + throw new \RuntimeException('Invalid POST data.'); + } + + return new Message($data); + } + + /** + * Creates a Message object from an array of raw message data. + * + * @param array $data The message data. + * + * @throws \InvalidArgumentException If a valid type is not provided or + * there are other required keys missing. + */ + public function __construct(array $data) + { + // Ensure that all the required keys for the message's type are present. + $this->validateRequiredKeys($data, self::$requiredKeys); + if ($data['Type'] === 'SubscriptionConfirmation' + || $data['Type'] === 'UnsubscribeConfirmation' + ) { + $this->validateRequiredKeys($data, self::$subscribeKeys); + } + + $this->data = $data; + } + + #[\ReturnTypeWillChange] + public function getIterator() + { + return new \ArrayIterator($this->data); + } + + #[\ReturnTypeWillChange] + public function offsetExists($key) + { + return isset($this->data[$key]); + } + + #[\ReturnTypeWillChange] + public function offsetGet($key) + { + return isset($this->data[$key]) ? $this->data[$key] : null; + } + + #[\ReturnTypeWillChange] + public function offsetSet($key, $value) + { + $this->data[$key] = $value; + } + + #[\ReturnTypeWillChange] + public function offsetUnset($key) + { + unset($this->data[$key]); + } + + /** + * Get all the message data as a plain array. + * + * @return array + */ + public function toArray() + { + return $this->data; + } + + private function validateRequiredKeys(array $data, array $keys) + { + foreach ($keys as $key) { + $keyIsArray = is_array($key); + if (!$keyIsArray) { + $found = isset($data[$key]); + } else { + $found = false; + foreach ($key as $keyOption) { + if (isset($data[$keyOption])) { + $found = true; + break; + } + } + } + + if (!$found) { + if ($keyIsArray) { + $key = $key[0]; + } + throw new \InvalidArgumentException( + "\"{$key}\" is required to verify the SNS Message." + ); + } + } + } +} diff --git a/lib/aws-sns-message-validator/src/MessageValidator.php b/lib/aws-sns-message-validator/src/MessageValidator.php new file mode 100644 index 0000000..474aec8 --- /dev/null +++ b/lib/aws-sns-message-validator/src/MessageValidator.php @@ -0,0 +1,195 @@ +.amazonaws.com (AWS) + * - sns.us-gov-west-1.amazonaws.com (AWS GovCloud) + * - sns.cn-north-1.amazonaws.com.cn (AWS China) + */ + private static $defaultHostPattern + = '/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/'; + + private static function isLambdaStyle(Message $message) + { + return isset($message['SigningCertUrl']); + } + + private static function convertLambdaMessage(Message $lambdaMessage) + { + $keyReplacements = [ + 'SigningCertUrl' => 'SigningCertURL', + 'SubscribeUrl' => 'SubscribeURL', + 'UnsubscribeUrl' => 'UnsubscribeURL', + ]; + + $message = clone $lambdaMessage; + foreach ($keyReplacements as $lambdaKey => $canonicalKey) { + if (isset($message[$lambdaKey])) { + $message[$canonicalKey] = $message[$lambdaKey]; + unset($message[$lambdaKey]); + } + } + + return $message; + } + + /** + * Constructs the Message Validator object and ensures that openssl is + * installed. + * + * @param callable $certClient Callable used to download the certificate. + * Should have the following function signature: + * `function (string $certUrl) : string|false $certContent` + * @param string $hostNamePattern + */ + public function __construct( + callable $certClient = null, + $hostNamePattern = '' + ) { + $this->certClient = $certClient ?: function($certUrl) { + return @ file_get_contents($certUrl); + }; + $this->hostPattern = $hostNamePattern ?: self::$defaultHostPattern; + } + + /** + * Validates a message from SNS to ensure that it was delivered by AWS. + * + * @param Message $message Message to validate. + * + * @throws InvalidSnsMessageException If the cert cannot be retrieved or its + * source verified, or the message + * signature is invalid. + */ + public function validate(Message $message) + { + if (self::isLambdaStyle($message)) { + $message = self::convertLambdaMessage($message); + } + + // Get the certificate. + $this->validateUrl($message['SigningCertURL']); + $certificate = call_user_func($this->certClient, $message['SigningCertURL']); + if ($certificate === false) { + throw new InvalidSnsMessageException( + "Cannot get the certificate from \"{$message['SigningCertURL']}\"." + ); + } + + // Extract the public key. + $key = openssl_get_publickey($certificate); + if (!$key) { + throw new InvalidSnsMessageException( + 'Cannot get the public key from the certificate.' + ); + } + + // Verify the signature of the message. + $content = $this->getStringToSign($message); + $signature = base64_decode($message['Signature']); + $algo = ($message['SignatureVersion'] === self::SIGNATURE_VERSION_1 ? OPENSSL_ALGO_SHA1 : OPENSSL_ALGO_SHA256); + if (openssl_verify($content, $signature, $key, $algo) !== 1) { + throw new InvalidSnsMessageException( + 'The message signature is invalid.' + ); + } + } + + /** + * Determines if a message is valid and that is was delivered by AWS. This + * method does not throw exceptions and returns a simple boolean value. + * + * @param Message $message The message to validate + * + * @return bool + */ + public function isValid(Message $message) + { + try { + $this->validate($message); + return true; + } catch (InvalidSnsMessageException $e) { + return false; + } + } + + /** + * Builds string-to-sign according to the SNS message spec. + * + * @param Message $message Message for which to build the string-to-sign. + * + * @return string + * @link http://docs.aws.amazon.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html + */ + public function getStringToSign(Message $message) + { + static $signableKeys = [ + 'Message', + 'MessageId', + 'Subject', + 'SubscribeURL', + 'Timestamp', + 'Token', + 'TopicArn', + 'Type', + ]; + + if ($message['SignatureVersion'] !== self::SIGNATURE_VERSION_1 + && $message['SignatureVersion'] !== self::SIGNATURE_VERSION_2) { + throw new InvalidSnsMessageException( + "The SignatureVersion \"{$message['SignatureVersion']}\" is not supported." + ); + } + + $stringToSign = ''; + foreach ($signableKeys as $key) { + if (isset($message[$key])) { + $stringToSign .= "{$key}\n{$message[$key]}\n"; + } + } + + return $stringToSign; + } + + /** + * Ensures that the URL of the certificate is one belonging to AWS, and not + * just something from the amazonaws domain, which could include S3 buckets. + * + * @param string $url Certificate URL + * + * @throws InvalidSnsMessageException if the cert url is invalid. + */ + private function validateUrl($url) + { + $parsed = parse_url($url); + if (empty($parsed['scheme']) + || empty($parsed['host']) + || $parsed['scheme'] !== 'https' + || substr($url, -4) !== '.pem' + || !preg_match($this->hostPattern, $parsed['host']) + ) { + throw new InvalidSnsMessageException( + 'The certificate is located on an invalid domain.' + ); + } + } +} diff --git a/tests/sns_client_test.php b/tests/sns_client_test.php new file mode 100644 index 0000000..279fe31 --- /dev/null +++ b/tests/sns_client_test.php @@ -0,0 +1,41 @@ +. + +namespace tool_emailutils; + +/** + * Tests for SNS client. + * + * @package tool_emailutils + * @author Benjamin Walker + * @copyright Catalyst IT 2024 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class sns_client_test extends \advanced_testcase { + + /** + * Test required libs are installed. + * + * @covers \tool_emailutils\sns_client::__construct + */ + public function test_lib(): void { + // Use process message to ensure no errors from missing libs are produced. + // This should result in an exception not an error. + $this->expectException(\Exception::class); + $client = new \tool_emailutils\sns_client('', '', ''); + $client->process_message(); + } +} diff --git a/thirdpartylibs.xml b/thirdpartylibs.xml new file mode 100644 index 0000000..77d1344 --- /dev/null +++ b/thirdpartylibs.xml @@ -0,0 +1,11 @@ + + + + lib/aws-sns-message-validator + Amazon SNS Message Validator for PHP + 1.9.0 + apache + 2.0 + https://github.com/aws/aws-php-sns-message-validator + + diff --git a/version.php b/version.php index 140b5a5..ce1d0e1 100644 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024111800; -$plugin->release = 2024111800; +$plugin->version = 2024111801; +$plugin->release = 2024111801; $plugin->requires = 2024042200; $plugin->component = 'tool_emailutils'; $plugin->maturity = MATURITY_STABLE;