Skip to content

Added support for nette application check #3

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

Merged
merged 2 commits into from
Jul 2, 2024
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
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@
"require" : {
"php": ">=8.1.0",
"ext-openssl": "*",
"contributte/event-dispatcher": "^0.9",
"cweagans/composer-patches": "^1.7",
"fastybird/datetime-factory": "^0.6",
"ipub/doctrine-crud": "^4.0",
"ipub/doctrine-orm-query": "^0.1",
"ipub/slim-router": "^0.2.0",
"lcobucci/jwt": "^4.2",
"nette/application": "^3.1",
"nette/bootstrap": "^3.1",
"nette/di": "^3.0",
"nette/utils": "^3.2||^4.0",
Expand Down
85 changes: 85 additions & 0 deletions src/Application/TSimpleAuth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php declare(strict_types = 1);

/**
* TSimpleAuth.php
*
* @license More in LICENSE.md
* @copyright https://www.fastybird.com
* @author Adam Kadlec <adam.kadlec@fastybird.com>
* @package FastyBird:SimpleAuth!
* @subpackage Application
* @since 1.0.0
*
* @date 01.07.24
*/

namespace FastyBird\SimpleAuth\Application;

use FastyBird\SimpleAuth;
use FastyBird\SimpleAuth\Security;
use Nette\Application;
use ReflectionClass;
use ReflectionMethod;

/**
* Nette's presenters security trait
*
* @package FastyBird:SimpleAuth!
* @subpackage Subscribers
*
* @author Adam Kadlec <adam.kadlec@fastybird.com>
*
* @method Application\IPresenter getPresenter()
* @method string storeRequest(string $expiration = '+ 10 minutes')
*
* @property-read Security\User|null $user;
*/
trait TSimpleAuth
{

protected SimpleAuth\Configuration $simpleAuthConfiguration;

protected Security\AnnotationChecker $annotationChecker;

public function injectSimpleAuth(
Security\AnnotationChecker $annotationChecker,
SimpleAuth\Configuration $configuration,
): void
{
$this->annotationChecker = $annotationChecker;
$this->simpleAuthConfiguration = $configuration;
}

/**
* @param mixed $element
*
* @throws Application\ForbiddenRequestException
* @throws Application\UI\InvalidLinkException
*/
public function checkRequirements(ReflectionClass|ReflectionMethod $element): void
{
$redirectUrl = $this->simpleAuthConfiguration->getRedirectUrl([
'backlink' => $this->storeRequest(),
]);

try {
parent::checkRequirements($element);

if (!$this->annotationChecker->checkAccess(
$this->user,
$element->class,
$element instanceof ReflectionMethod ? $element->name : null,
)) {
throw new Application\ForbiddenRequestException();
}
} catch (Application\ForbiddenRequestException $ex) {
if ($redirectUrl) {
$this->getPresenter()->redirectUrl($redirectUrl);

} else {
throw $ex;
}
}
}

}
94 changes: 94 additions & 0 deletions src/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php declare(strict_types = 1);

/**
* Configuration.php
*
* @license More in LICENSE.md
* @copyright https://www.fastybird.com
* @author Adam Kadlec <adam.kadlec@fastybird.com>
* @package FastyBird:SimpleAuth!
* @subpackage common
* @since 0.1.0
*
* @date 01.07.24
*/

namespace FastyBird\SimpleAuth;

use Nette;
use Nette\Application;

/**
* Simple authentication extension configuration storage.
* Store basic extension settings
*
* @package FastyBird:SimpleAuth!
* @subpackage common
*
* @author Adam Kadlec <adam.kadlec@fastybird.com>
*/
class Configuration
{

use Nette\SmartObject;

public function __construct(
private readonly Application\LinkGenerator $linkGenerator,
private readonly string $tokenIssuer,
private readonly string $tokenSignature,
private readonly bool $enableMiddleware,
private readonly bool $enableDoctrineMapping,
private readonly bool $enableDoctrineModels,
private readonly bool $enableNetteApplication,
private readonly string|null $applicationRedirectUrl = null,
)
{
}

public function getTokenIssuer(): string
{
return $this->tokenIssuer;
}

public function getTokenSignature(): string
{
return $this->tokenSignature;
}

public function isEnableMiddleware(): bool
{
return $this->enableMiddleware;
}

public function isEnableDoctrineMapping(): bool
{
return $this->enableDoctrineMapping;
}

public function isEnableDoctrineModels(): bool
{
return $this->enableDoctrineModels;
}

public function isEnableNetteApplication(): bool
{
return $this->enableNetteApplication;
}

/**
* Build the URL for redirection if is set
*
* @param array<mixed> $params
*
* @throws Application\UI\InvalidLinkException
*/
public function getRedirectUrl(array $params = []): string|null
{
if ($this->applicationRedirectUrl !== null) {
return $this->linkGenerator->link($this->applicationRedirectUrl, $params);
}

return null;
}

}
2 changes: 2 additions & 0 deletions src/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ final class Constants
// Permissions string delimiter
public const PERMISSIONS_DELIMITER = ':';

public const ACCESS_TOKEN_COOKIE = 'token';

/**
* Security tokens
*/
Expand Down
67 changes: 67 additions & 0 deletions src/DI/SimpleAuthExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@
use Doctrine\Persistence;
use FastyBird\SimpleAuth;
use FastyBird\SimpleAuth\Entities;
use FastyBird\SimpleAuth\Events;
use FastyBird\SimpleAuth\Mapping;
use FastyBird\SimpleAuth\Middleware;
use FastyBird\SimpleAuth\Security;
use FastyBird\SimpleAuth\Subscribers;
use IPub\DoctrineCrud;
use Nette;
use Nette\Application as NetteApplication;
use Nette\DI;
use Nette\PhpGenerator;
use Nette\Schema;
use stdClass;
use Symfony\Contracts\EventDispatcher;
use function assert;
use function ucfirst;
use const DIRECTORY_SEPARATOR;
Expand Down Expand Up @@ -66,6 +69,12 @@ public function getConfigSchema(): Schema\Schema
'mapping' => Schema\Expect::bool(false),
'models' => Schema\Expect::bool(false),
]),
'nette' => Schema\Expect::structure([
'application' => Schema\Expect::bool(false),
]),
]),
'application' => Schema\Expect::structure([
'redirectUrl' => Schema\Expect::string(),
]),
'services' => Schema\Expect::structure([
'identity' => Schema\Expect::bool(false),
Expand All @@ -82,6 +91,18 @@ public function loadConfiguration(): void
$builder->addDefinition($this->prefix('auth'), new DI\Definitions\ServiceDefinition())
->setType(SimpleAuth\Auth::class);

$builder->addDefinition($this->prefix('configuration'), new DI\Definitions\ServiceDefinition())
->setType(SimpleAuth\Configuration::class)
->setArguments([
'tokenIssuer' => $configuration->token->issuer,
'tokenSignature' => $configuration->token->signature,
'enableMiddleware' => $configuration->enable->middleware,
'enableDoctrineMapping' => $configuration->enable->doctrine->mapping,
'enableDoctrineModels' => $configuration->enable->doctrine->models,
'enableNetteApplication' => $configuration->enable->nette->application,
'applicationRedirectUrl' => $configuration->application->redirectUrl,
]);

/**
* Token utilities
*/
Expand Down Expand Up @@ -146,6 +167,15 @@ public function loadConfiguration(): void
->setType(SimpleAuth\Models\Tokens\TokensManager::class)
->setArgument('entityCrud', '__placeholder__');
}

/**
* Nette application extension
*/

if ($configuration->enable->nette->application) {
$builder->addDefinition($this->prefix('nette.application'), new DI\Definitions\ServiceDefinition())
->setType(Subscribers\Application::class);
}
}

/**
Expand All @@ -172,6 +202,10 @@ public function beforeCompile(): void
->setType(Security\User::class);
}

/**
* Doctrine extension
*/

if ($configuration->enable->doctrine->models) {
$ormAttributeDriverService = $builder->getDefinition('nettrineOrmAttributes.attributeDriver');

Expand All @@ -193,6 +227,35 @@ public function beforeCompile(): void
]);
}
}

/**
* Nette application extension
*/

if ($configuration->enable->nette->application) {
if ($builder->getByType(EventDispatcher\EventDispatcherInterface::class) !== null) {
if ($builder->getByType(NetteApplication\Application::class) !== null) {
$dispatcher = $builder->getDefinition(
$builder->getByType(EventDispatcher\EventDispatcherInterface::class),
);

$application = $builder->getDefinition($builder->getByType(NetteApplication\Application::class));
assert($application instanceof DI\Definitions\ServiceDefinition);

$application->addSetup('?->onRequest[] = function() {?->dispatch(new ?(...func_get_args()));}', [
'@self',
$dispatcher,
new PhpGenerator\Literal(Events\Request::class),
]);

$application->addSetup('?->onResponse[] = function() {?->dispatch(new ?(...func_get_args()));}', [
'@self',
$dispatcher,
new PhpGenerator\Literal(Events\Response::class),
]);
}
}
}
}

/**
Expand All @@ -204,6 +267,10 @@ public function afterCompile(PhpGenerator\ClassType $class): void
$configuration = $this->getConfig();
assert($configuration instanceof stdClass);

/**
* Doctrine extension
*/

if ($configuration->enable->doctrine->models) {
$entityFactoryServiceName = $builder->getByType(DoctrineCrud\Crud\IEntityCrudFactory::class, true);

Expand Down
49 changes: 49 additions & 0 deletions src/Events/Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php declare(strict_types = 1);

/**
* Request.php
*
* @license More in LICENSE.md
* @copyright https://www.fastybird.com
* @author Adam Kadlec <adam.kadlec@fastybird.com>
* @package FastyBird:SimpleAuth!
* @subpackage Events
* @since 1.0.0
*
* @date 01.07.24
*/

namespace FastyBird\SimpleAuth\Events;

use Nette\Application;
use Symfony\Contracts\EventDispatcher;

/**
* Application request event
*
* @package FastyBird:SimpleAuth!
* @subpackage Events
*
* @author Adam Kadlec <adam.kadlec@fastybird.com>
*/
class Request extends EventDispatcher\Event
{

public function __construct(
private readonly Application\Application $application,
private readonly Application\Request $request,
)
{
}

public function getApplication(): Application\Application
{
return $this->application;
}

public function getRequest(): Application\Request
{
return $this->request;
}

}
Loading
Loading