diff --git a/client/dist/js/BrokenExternalLinksReport.js b/client/dist/js/BrokenExternalLinksReport.js
index f4144c5..27cea29 100644
--- a/client/dist/js/BrokenExternalLinksReport.js
+++ b/client/dist/js/BrokenExternalLinksReport.js
@@ -1 +1 @@
-!function(){"use strict";var t={311:function(t){t.exports=jQuery}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var s=e[o]={exports:{}};return t[o](s,s.exports,n),s.exports}!function(){var t=n(311);t.entwine("ss",(t=>{t(".external-links-report__create-report").entwine({PollTimeout:null,ButtonIsLoading:!1,ReloadContent:!1,onclick(t){t.preventDefault(),this.buttonLoading(),this.start()},onmatch(){this.poll()},start(){const e=this;t(".external-links-report__report-progress").empty().text("Running report 0%"),t.ajax({url:"admin/externallinks/start",async:!0,timeout:3e3,success(){e.setReloadContent(!0),e.poll()},error(t){"undefined"!=typeof console&&console.error(t)}})},getButton(){return t(".external-links-report__create-report")},buttonLoading(){if(this.getButtonIsLoading())return;this.setButtonIsLoading(!0);const e=this.getButton();e.addClass("btn--loading loading"),e.attr("disabled",!0),e.is("button")&&(e.append(t('
')),e.css(`${e.outerWidth()}px`))},buttonReset(){this.setButtonIsLoading(!1);const t=this.getButton();t.removeClass("btn--loading loading"),t.attr("disabled",!1),t.find(".btn__loading-icon").remove(),t.css("width","auto")},poll(){const e=this;this.buttonLoading(),t.ajax({url:"admin/externallinks/getJobStatus",async:!0,success(n){if(!n)return void e.buttonReset();const o=n.Completed?n.Completed:0,r=n.Total?n.Total:0;if("Completed"===n.Status)return e.getReloadContent()&&(t(".cms-container").loadPanel(document.location.href,null,{},!0,!1),e.setReloadContent(!1)),t(".external-links-report__report-progress").text(`Report finished ${o}/${r}`),void e.buttonReset();if(o{t(".external-links-report__create-report").poll()}),1e3))},error(t){"undefined"!=typeof console&&console.error(t),e.buttonReset()}})}})}))}()}();
\ No newline at end of file
+!function(){"use strict";var t={311:function(t){t.exports=jQuery}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var s=e[o]={exports:{}};return t[o](s,s.exports,n),s.exports}!function(){var t=n(311);t.entwine("ss",(t=>{t(".external-links-report__create-report").entwine({PollTimeout:null,ButtonIsLoading:!1,ReloadContent:!1,onclick(t){t.preventDefault(),this.buttonLoading(),this.start()},onmatch(){this.poll()},start(){const e=this;t(".external-links-report__report-progress").empty().text("Running report 0%"),t.ajax({url:"admin/externallinks/start",async:!0,timeout:3e3,success(){e.setReloadContent(!0),e.poll()},error(){e.buttonReset()}})},getButton(){return t(".external-links-report__create-report")},buttonLoading(){if(this.getButtonIsLoading())return;this.setButtonIsLoading(!0);const e=this.getButton();e.addClass("btn--loading loading"),e.attr("disabled",!0),e.is("button")&&(e.append(t('
')),e.css(`${e.outerWidth()}px`))},buttonReset(){this.setButtonIsLoading(!1);const t=this.getButton();t.removeClass("btn--loading loading"),t.attr("disabled",!1),t.find(".btn__loading-icon").remove(),t.css("width","auto")},poll(){const e=this;this.buttonLoading(),t.ajax({url:"admin/externallinks/getJobStatus",async:!0,success(n){if(!n)return void e.buttonReset();const o=n.Completed?n.Completed:0,r=n.Total?n.Total:0;if("Completed"===n.Status)return e.getReloadContent()&&(t(".cms-container").loadPanel(document.location.href,null,{},!0,!1),e.setReloadContent(!1)),t(".external-links-report__report-progress").text(`Report finished ${o}/${r}`),void e.buttonReset();if(o{t(".external-links-report__create-report").poll()}),1e3))},error(){e.buttonReset()}})}})}))}()}();
\ No newline at end of file
diff --git a/client/src/js/BrokenExternalLinksReport.js b/client/src/js/BrokenExternalLinksReport.js
index 3396bff..a3f3225 100644
--- a/client/src/js/BrokenExternalLinksReport.js
+++ b/client/src/js/BrokenExternalLinksReport.js
@@ -34,11 +34,8 @@
self.setReloadContent(true);
self.poll();
},
- error(e) {
- if (typeof console !== 'undefined') {
- // eslint-disable-next-line no-console
- console.error(e);
- }
+ error() {
+ self.buttonReset();
}
});
},
@@ -141,11 +138,7 @@
$('.external-links-report__create-report').poll();
}, 1000));
},
- error(e) {
- if (typeof console !== 'undefined') {
- // eslint-disable-next-line no-console
- console.error(e);
- }
+ error() {
self.buttonReset();
}
});
diff --git a/src/Controllers/CMSExternalLinksController.php b/src/Controllers/CMSExternalLinksController.php
index a6cae46..1855e47 100644
--- a/src/Controllers/CMSExternalLinksController.php
+++ b/src/Controllers/CMSExternalLinksController.php
@@ -8,6 +8,7 @@
use SilverStripe\Control\Controller;
use Symbiote\QueuedJobs\Services\QueuedJobService;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
+use SilverStripe\Security\Permission;
class CMSExternalLinksController extends Controller
{
@@ -24,6 +25,9 @@ class CMSExternalLinksController extends Controller
*/
public function getJobStatus()
{
+ if (!Permission::check('CMS_ACCESS_CMSMain')) {
+ return $this->httpError(403, 'You do not have permission to access this resource');
+ }
// Set headers
HTTPCacheControlMiddleware::singleton()->setMaxAge(0);
$this->response
@@ -49,6 +53,9 @@ public function getJobStatus()
*/
public function start()
{
+ if (!Permission::check('CMS_ACCESS_CMSMain')) {
+ return $this->httpError(403, 'You do not have permission to access this resource');
+ }
// return if the a job is already running
$status = BrokenExternalPageTrackStatus::get_latest();
if ($status && $status->Status == 'Running') {
diff --git a/tests/php/ExternalLinksTest.php b/tests/php/ExternalLinksTest.php
index 433ea5b..edbdd2d 100644
--- a/tests/php/ExternalLinksTest.php
+++ b/tests/php/ExternalLinksTest.php
@@ -3,7 +3,7 @@
namespace SilverStripe\ExternalLinks\Tests;
use SilverStripe\Core\Injector\Injector;
-use SilverStripe\Dev\SapphireTest;
+use SilverStripe\Dev\FunctionalTest;
use SilverStripe\ExternalLinks\Model\BrokenExternalPageTrackStatus;
use SilverStripe\ExternalLinks\Reports\BrokenExternalLinksReport;
use SilverStripe\ExternalLinks\Tasks\CheckExternalLinksTask;
@@ -13,7 +13,7 @@
use SilverStripe\i18n\i18n;
use SilverStripe\Reports\Report;
-class ExternalLinksTest extends SapphireTest
+class ExternalLinksTest extends FunctionalTest
{
protected static $fixture_file = 'ExternalLinksTest.yml';
@@ -125,4 +125,29 @@ public function testArchivedPagesAreHiddenFromReport()
// Ensure report does not list the link associated with an archived page
$this->assertEquals(3, BrokenExternalLinksReport::create()->sourceRecords()->count());
}
+
+ public function provideGetJobStatus(): array
+ {
+ return [
+ 'ADMIN - valid permission' => ['ADMIN', 200],
+ 'CMS_ACCESS_CMSMain - valid permission' => ['CMS_ACCESS_CMSMain', 200],
+ 'VIEW_SITE - not enough permission' => ['VIEW_SITE', 403],
+ ];
+ }
+
+ /**
+ * @dataProvider provideGetJobStatus
+ */
+ public function testGetJobStatus(
+ string $permission,
+ int $expectedResponseCode
+ ): void {
+ $this->logInWithPermission($permission);
+
+ $response = $this->get('admin/externallinks/start', null, ['Accept' => 'application/json']);
+ $this->assertEquals($expectedResponseCode, $response->getStatusCode());
+
+ $response = $this->get('admin/externallinks/getJobStatus', null, ['Accept' => 'application/json']);
+ $this->assertEquals($expectedResponseCode, $response->getStatusCode());
+ }
}