Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Secured as attribute for PHP >= 8.0 #37

Merged
merged 2 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Secured.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php declare(strict_types=1);

namespace Nextras\Application\UI;

use Attribute;


#[Attribute(Attribute::TARGET_METHOD)]
class Secured
{

}
3 changes: 2 additions & 1 deletion src/SecuredLinksControlTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public function signalReceived(string $signal): void

if (method_exists($this, $method)) {
$reflection = new \ReflectionMethod($this, $method);
$secured = Nette\Application\UI\ComponentReflection::parseAnnotation($reflection, 'secured') !== NULL;
$secured = Nette\Application\UI\ComponentReflection::parseAnnotation($reflection, 'secured') !== NULL
|| (method_exists($reflection, 'getAttributes') && count($reflection->getAttributes(Secured::class)) > 0);
if ($secured) {
$params = array($this->getUniqueId());
if ($this->params) {
Expand Down
2 changes: 1 addition & 1 deletion src/SecuredLinksPresenterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function createSecuredLink(Component $component, string $link, string $de
$method = $component->formatSignalMethod($signal);
$signalReflection = $reflection->getMethod($method);

if (!$signalReflection->hasAnnotation('secured')) {
if (!$signalReflection->hasAnnotation('secured') && count($signalReflection->getAttributes(Secured::class)) === 0) {
break;
}

Expand Down
95 changes: 95 additions & 0 deletions tests/cases/SecuredLinksTest.attribute.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php
/**
* @phpVersion >= 8.0.0
*/

use Nette\Application\Request;
use Nette\Application\Routers\SimpleRouter;
use Nette\Application\UI\Control;
use Nette\Application\UI\Presenter;
use Nette\Http\Request as HttpRequest;
use Nette\Http\Response;
use Nette\Http\UrlScript;
use Nextras\Application\UI\Secured;
use Nextras\Application\UI\SecuredLinksControlTrait;
use Nextras\Application\UI\SecuredLinksPresenterTrait;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


class TestControl extends Control
{
use SecuredLinksControlTrait;
#[Secured]
public function handlePay($amount = 0)
{
}
}


class TestPresenter extends Presenter
{
use SecuredLinksPresenterTrait;
protected function startup()
{
parent::startup();
$this['mycontrol'] = new TestControl;
}
public function renderDefault()
{
$this->terminate();
}
#[Secured]
public function handlePay($amount = 0)
{
}
#[Secured]
public function handlePay2($amount)
{
}
#[Secured]
public function handleList(array $sections)
{
}
}


$url = new UrlScript('http://localhost/index.php', '/index.php');

$httpRequest = new HttpRequest($url);
$httpResponse = new Response();

$router = new SimpleRouter();
$request = new Request('Test', HttpRequest::GET, array());

$sessionSection = Mockery::mock('alias:Nette\Http\SessionSection');
$sessionSection->token = 'abcd';

$session = Mockery::mock('Nette\Http\Session');
$session->shouldReceive('getSection')->with('Nextras.Application.UI.SecuredLinksPresenterTrait')->andReturn($sessionSection);
$session->shouldReceive('getId')->times(8)->andReturn('session_id_1');

$presenter = new TestPresenter();
$presenter->autoCanonicalize = FALSE;
$presenter->injectPrimary(NULL, NULL, $router, $httpRequest, $httpResponse, $session, NULL);
$presenter->run($request);


Assert::same( '/index.php?action=default&do=pay&presenter=Test&_sec=7VNmMotk', $presenter->link('pay!') );
Assert::same( '/index.php?amount=200&action=default&do=pay&presenter=Test&_sec=7VNmMotk', $presenter->link('pay!', [200]) );
Assert::same( '/index.php?amount=100&action=default&do=pay2&presenter=Test&_sec=JtQFHCP3', $presenter->link('pay2!', [100]) );
Assert::same( '/index.php?amount=200&action=default&do=pay2&presenter=Test&_sec=S2PM9nnh', $presenter->link('pay2!', [200]) );
Assert::same( '/index.php?sections[0]=a&sections[1]=b&action=default&do=list&presenter=Test&_sec=btNfK0zF', urldecode($presenter->link('list!', [['a', 'b']])) );
Assert::same( '/index.php?sections[0]=a&sections[1]=c&action=default&do=list&presenter=Test&_sec=2oGtxq6E', urldecode($presenter->link('list!', [['a', 'c']])) );

Assert::same( '/index.php?action=default&do=mycontrol-pay&presenter=Test&mycontrol-_sec=_eyaqc4b', $presenter['mycontrol']->link('pay') );
Assert::same( '/index.php?mycontrol-amount=200&action=default&do=mycontrol-pay&presenter=Test&mycontrol-_sec=_eyaqc4b', $presenter['mycontrol']->link('pay', [200]) );


$session->shouldReceive('getId')->times(2)->andReturn('session_id_2');

Assert::same( '/index.php?sections[0]=a&sections[1]=b&action=default&do=list&presenter=Test&_sec=Y3v1C1cr', urldecode($presenter->link('list!', [['a', 'b']])) );
Assert::same( '/index.php?sections[0]=a&sections[1]=c&action=default&do=list&presenter=Test&_sec=kfY-zsLy', urldecode($presenter->link('list!', [['a', 'c']])) );

Mockery::close();
10 changes: 10 additions & 0 deletions tests/cases/SecuredLinksTest.php7.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use Nette\Application\Request;
use Nette\Application\Routers\SimpleRouter;
use Nette\Application\UI\BadSignalException;
use Nette\Application\UI\Presenter;
use Nette\Http\Request as HttpRequest;
use Nette\Http\Response;
Expand Down Expand Up @@ -64,4 +65,13 @@ $presenter->run(new Request('Test', 'GET', [
'_sec' => 'JqCasYHU',
]));

Assert::exception(function () use ($presenter) {
$presenter->run(new Request('Test', 'GET', [
'action' => 'default',
'do' => 'pay',
'value' => '0',
//'_sec' => 'JqCasYHU',
]));
}, BadSignalException::class, "Invalid security token for signal 'pay' in class TestPresenter.");

Mockery::close();