Skip to content

Commit

Permalink
ENH Restrict access to getJobStatus execution
Browse files Browse the repository at this point in the history
  • Loading branch information
Sabina Talipova committed Nov 8, 2023
1 parent 20c2231 commit a6c11ce
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 37 deletions.
23 changes: 19 additions & 4 deletions client/javascript/BrokenExternalLinksReport.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},

start: function() {
var self = this;
// initiate a new job
$('.external-links-report__report-progress')
.empty()
Expand All @@ -25,10 +26,21 @@
$.ajax({
url: "admin/externallinks/start",
async: true,
timeout: 3000
});
timeout: 3000,
success: function() {
self.poll();
},
error: function(e) {
if (typeof console !== 'undefined') {
let message = (e && e.responseText)
? e.responseText
: 'You do not have permission to access this resource';

this.poll();
console.error(message);
}
self.buttonReset();
}
});
},

/**
Expand Down Expand Up @@ -127,7 +139,10 @@
},
error: function(e) {
if (typeof console !== 'undefined') {
console.log(e);
let message = (e && e.responseText)
? e.responseText
: e;
console.error(message);
}
self.buttonReset();
}
Expand Down
72 changes: 41 additions & 31 deletions src/Controllers/CMSExternalLinksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use SilverStripe\Control\Controller;
use Symbiote\QueuedJobs\Services\QueuedJobService;
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Security;

class CMSExternalLinksController extends Controller
{
Expand All @@ -24,22 +26,26 @@ class CMSExternalLinksController extends Controller
*/
public function getJobStatus()
{
// Set headers
HTTPCacheControlMiddleware::singleton()->setMaxAge(0);
$this->response
->addHeader('Content-Type', 'application/json')
->addHeader('Content-Encoding', 'UTF-8')
->addHeader('X-Content-Type-Options', 'nosniff');
if (Permission::checkMember(Security::getCurrentUser(), ['CMS_ACCESS_CMSMain'])) {
// Set headers
HTTPCacheControlMiddleware::singleton()->setMaxAge(0);
$this->response
->addHeader('Content-Type', 'application/json')
->addHeader('Content-Encoding', 'UTF-8')
->addHeader('X-Content-Type-Options', 'nosniff');

// Format status
$track = BrokenExternalPageTrackStatus::get_latest();
if ($track) {
return json_encode([
'TrackID' => $track->ID,
'Status' => $track->Status,
'Completed' => $track->getCompletedPages(),
'Total' => $track->getTotalPages()
]);
// Format status
$track = BrokenExternalPageTrackStatus::get_latest();
if ($track) {
return json_encode([
'TrackID' => $track->ID,
'Status' => $track->Status,
'Completed' => $track->getCompletedPages(),
'Total' => $track->getTotalPages()
]);
}
} else {
return $this->httpError(403, 'You do not have permission to access this resource');
}
}

Expand All @@ -49,24 +55,28 @@ public function getJobStatus()
*/
public function start()
{
// return if the a job is already running
$status = BrokenExternalPageTrackStatus::get_latest();
if ($status && $status->Status == 'Running') {
return;
}
if (Permission::checkMember(Security::getCurrentUser(), ['CMS_ACCESS_CMSMain'])) {
// return if the a job is already running
$status = BrokenExternalPageTrackStatus::get_latest();
if ($status && $status->Status == 'Running') {
return;
}

// Create a new job
if (class_exists(QueuedJobService::class)) {
// Force the creation of a new run
BrokenExternalPageTrackStatus::create_status();
$checkLinks = new CheckExternalLinksJob();
singleton(QueuedJobService::class)->queueJob($checkLinks);
// Create a new job
if (class_exists(QueuedJobService::class)) {
// Force the creation of a new run
BrokenExternalPageTrackStatus::create_status();
$checkLinks = new CheckExternalLinksJob();
singleton(QueuedJobService::class)->queueJob($checkLinks);
} else {
//TODO this hangs as it waits for the connection to be released
// should return back and continue processing
// http://us3.php.net/manual/en/features.connection-handling.php
$task = CheckExternalLinksTask::create();
$task->runLinksCheck();
}
} else {
//TODO this hangs as it waits for the connection to be released
// should return back and continue processing
// http://us3.php.net/manual/en/features.connection-handling.php
$task = CheckExternalLinksTask::create();
$task->runLinksCheck();
return $this->httpError(403, 'You do not have permission to access this resource');
}
}
}
30 changes: 28 additions & 2 deletions tests/php/ExternalLinksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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';
Expand Down Expand Up @@ -125,4 +125,30 @@ public function testArchivedPagesAreHiddenFromReport()
// Ensure report does not list the link associated with an archived page
$this->assertEquals(3, BrokenExternalLinksReport::create()->sourceRecords()->count());
}

public function getJobStatusDataProvider()
{
return [
'ADMIN - valid permission' => ['ADMIN', 200],
'CMS_ACCESS_CMSMain - valid permission' => ['CMS_ACCESS_CMSMain', 200],
'VIEW_SITE - not enough permission' => ['VIEW_SITE', 403],
];
}

/**
* @dataProvider getJobStatusDataProvider
*/
public function testGetJobStatus(
string $permission,
int $expectedResponseCode
) {
$this->logOut();
$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());
}
}

0 comments on commit a6c11ce

Please sign in to comment.