diff --git a/README.md b/README.md index 019c121..1371452 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ There are two types of roles with this module. * Website owner; (typically assigned to the Administrator group) ensures that a website is accurate and up-to-date, by delegating responsibility to content reviewers. * Content reviewer; responsible for keeping a website or part of a website accurate and up-to-date. -## Requirements +## Installation - * Silverstripe ^4.0 - - **Note:** For Silverstripe 3.x, please use the [3.x release line](https://github.com/silverstripe/silverstripe-contentreview/tree/3). +```sh +composer require silverstripe/contentreview +``` ## Features @@ -36,7 +36,7 @@ There are two types of roles with this module. ## Composer installation ```sh -$ composer require silverstripe/contentreview +composer require silverstripe/contentreview ``` You'll also need to run `dev/build`. diff --git a/composer.json b/composer.json index 200d675..b7f8a37 100644 --- a/composer.json +++ b/composer.json @@ -49,4 +49,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} +} \ No newline at end of file diff --git a/package.json b/package.json index 4db29ed..af3b776 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "redux": "^4.2.0" }, "devDependencies": { - "@silverstripe/eslint-config": "^1.0.0-alpha6", - "@silverstripe/webpack-config": "^2.0.0-alpha5", + "@silverstripe/eslint-config": "^1.0.0", + "@silverstripe/webpack-config": "^2.0.0", "webpack": "^5.74.0", "webpack-cli": "^5.0.0" }, diff --git a/src/Tasks/ContentReviewEmails.php b/src/Tasks/ContentReviewEmails.php index c59bc56..2131796 100644 --- a/src/Tasks/ContentReviewEmails.php +++ b/src/Tasks/ContentReviewEmails.php @@ -3,6 +3,7 @@ namespace SilverStripe\ContentReview\Tasks; use Page; +use RuntimeException; use SilverStripe\ContentReview\Compatibility\ContentReviewCompatability; use SilverStripe\Control\Email\Email; use SilverStripe\Control\HTTPRequest; @@ -15,18 +16,29 @@ use SilverStripe\Security\Member; use SilverStripe\SiteConfig\SiteConfig; use SilverStripe\View\ArrayData; use SilverStripe\View\SSViewer; -use SilverStripe\ContentReview\Models\ContentReviewLog; /** * Daily task to send emails to the owners of content items when the review date rolls around. */ class ContentReviewEmails extends BuildTask { + private array $invalid_emails = []; + /** * @param HTTPRequest $request + * @throws RuntimeException */ public function run($request) { + if (!$this->isValidEmail($senderEmail = SiteConfig::current_site_config()->ReviewFrom)) { + throw new RuntimeException( + sprintf( + 'Provided sender email address is invalid: "%s".', + $senderEmail + ) + ); + } + $compatibility = ContentReviewCompatability::start(); // First grab all the pages with a custom setting @@ -42,6 +54,16 @@ class ContentReviewEmails extends BuildTask } ContentReviewCompatability::done($compatibility); + + if (is_array($this->invalid_emails) && count($this->invalid_emails) > 0) { + $plural = count($this->invalid_emails) > 1 ? 's are' : ' is'; + throw new RuntimeException( + sprintf( + 'Provided email' . $plural . ' invalid: "%s".', + implode(', ', $this->invalid_emails) + ) + ); + } } /** @@ -93,6 +115,13 @@ class ContentReviewEmails extends BuildTask // Prepare variables $siteConfig = SiteConfig::current_site_config(); $owner = Member::get()->byID($ownerID); + + if (!$this->isValidEmail($owner->Email)) { + $this->invalid_emails[] = $owner->Name . ': ' . $owner->Email; + + return; + } + $templateVariables = $this->getTemplateVariables($owner, $siteConfig, $pages); // Build email @@ -159,4 +188,12 @@ class ContentReviewEmails extends BuildTask 'ToEmail' => $recipient->Email, ]; } + + /** + * Check validity of email + */ + protected function isValidEmail(?string $email): bool + { + return (bool) filter_var($email, FILTER_VALIDATE_EMAIL); + } } diff --git a/tests/php/ContentReviewNotificationTest.php b/tests/php/ContentReviewNotificationTest.php index d2e7aca..241dd9c 100644 --- a/tests/php/ContentReviewNotificationTest.php +++ b/tests/php/ContentReviewNotificationTest.php @@ -3,6 +3,7 @@ namespace SilverStripe\ContentReview\Tests; use Page; +use ReflectionClass; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension; @@ -132,6 +133,26 @@ class ContentReviewNotificationTest extends SapphireTest DBDatetime::clear_mock_now(); } + /** + * Test that provided email is valid + */ + public function testIsValidEmail() + { + $class = new ReflectionClass(ContentReviewEmails::class); + $method = $class->getMethod('isValidEmail'); + $method->setAccessible(true); + + $member = $this->objFromFixture(Member::class, 'author'); + $task = new ContentReviewEmails(); + + $this->assertTrue($method->invokeArgs($task, [$member->Email])); + $this->assertTrue($method->invokeArgs($task, ['correct.email@example.com'])); + + $this->assertFalse($method->invokeArgs($task, [null])); + $this->assertFalse($method->invokeArgs($task, ['broken.email'])); + $this->assertFalse($method->invokeArgs($task, ['broken@email'])); + } + /** * Deletes all pages except those passes in to the $ids parameter * diff --git a/yarn.lock b/yarn.lock index ec0795a..b5ad5fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1261,10 +1261,10 @@ resolved "https://registry.yarnpkg.com/@sect/modernizr-loader/-/modernizr-loader-1.0.3.tgz#7fd8cec372426c53f113f3cfd9344cb29e959825" integrity sha512-47zKwv4/1I0CYptZz8s4aSYSe0awmuyqa+HFKxN89/75h2q8hr6V752TZ9VjhGDhQ4gU0EU7Plew7b+7bf2crg== -"@silverstripe/eslint-config@^1.0.0-alpha6": - version "1.0.0-alpha6" - resolved "https://registry.yarnpkg.com/@silverstripe/eslint-config/-/eslint-config-1.0.0-alpha6.tgz#1f243b003fddf3503a4abea37f35a8a5968cc96e" - integrity sha512-+P7UzhMRSmc7UlRYCiSXwjauLFYU11oBPwHl/bpacJ7xUcFY3Jt3CgcDt6d+XLvAJO8zMRsG9RcOm5MnxsyCsg== +"@silverstripe/eslint-config@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@silverstripe/eslint-config/-/eslint-config-1.0.0.tgz#dcf3f9cf2158bb587d8048a7c2860c0513221d40" + integrity sha512-pcHzB+6KWd8BPStBhHM8achdNY/Yj1p3WSTEs/CSw61VRcfBfg5GZECtvEerTSX/0ZeawAM1ABvstIAYihcfAg== dependencies: eslint "^8.26.0" eslint-config-airbnb "^19.0.4" @@ -1274,10 +1274,10 @@ eslint-plugin-react "^7.31.10" eslint-webpack-plugin "^3.2.0" -"@silverstripe/webpack-config@^2.0.0-alpha5": - version "2.0.0-alpha8" - resolved "https://registry.yarnpkg.com/@silverstripe/webpack-config/-/webpack-config-2.0.0-alpha8.tgz#df97d047ceb0f1726cea7c18864ce15eba1361ce" - integrity sha512-aIwflLBdC2neS7zAq4qN+P2lhkb1vrxTVZSUILI7Gpthp/8tQ7k91W2UdXWWXOUytQYLo+5gBfkh4P60Mys/nQ== +"@silverstripe/webpack-config@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@silverstripe/webpack-config/-/webpack-config-2.0.0.tgz#278a72a1adbc6fa2362497d60424c78fba58e8e1" + integrity sha512-m1qGRxlsdhWL567cWe7IZNBUCzeyg3T1Y9yY9Y6XClwAqlg1oIO9uLfvfauA4dbtECrzU5n1AkaaU6kMRtN6Aw== dependencies: "@babel/core" "^7.19.6" "@babel/preset-env" "^7.19.4"