alfred-cerny / nette-security
Compile-time Nette DI access policy based on ComponentAttributes
Installs: 21
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/alfred-cerny/nette-security
Requires
- php: ^8.2
- nette/application: ^3.0
- nette/di: ^3.0
- nette/security: ^3.0
Requires (Dev)
- mockery/mockery: ^1.6
- nette/bootstrap: ^3.0
- nette/tester: ^2.5@dev
- phpstan/phpstan: 2.1.x-dev
- phpstan/phpstan-nette: 2.0.x-dev
README
A robust access control system for Nette Framework applications, leveraging PHP 8+ attributes.
Features
- Attribute-based Access Control: Define access requirements directly on Nette Components and their methods using PHP attributes.
- Authentication Enforcement: Easily require user authentication for components or actions.
- Role-based Access Control (RBAC): Restrict access based on user roles.
- Resource-based Access Control: Implement fine-grained permissions for specific resources and privileges (e.g., ' edit' a 'post').
- Seamless Nette Integration: Integrates with Nette DI and Nette Application lifecycle.
- Extensible: Custom attributes can implement
ComponentAttribute
for extended access checks.
Installation
-
Install via Composer:
composer require alfred-cerny/nette-attributes
-
Register the Nette DI Extension:
In your
config.neon
(orcommon.neon
), register theAccessPolicyExtension
:extensions: accessPolicy: Alfred\Nette\Security\DI\AccessPolicyExtension
-
Ensure your presenters are loaded in the DI
application: scanDirs: - %appDir%/<path_to_your_application_src>
Usage
This library allows you to define access policies directly on your Nette Presenters, Components, and their methods using
the #[Requires]
attribute.
Requiring Authentication
To ensure a user is logged in to access a presenter or its methods:
use Alfred\Nette\Security\Attributes\Requires; use Alfred\Nette\Security\UI\AccessPolicyAwarePresenter; #[Requires(authentication: true)] final class UserSettingsPresenter extends AccessPolicyAwarePresenter { // ... }
Role-based Access
To restrict access to specific roles:
use Alfred\Nette\Security\Attributes\Requires; use Alfred\Nette\Security\UI\AccessPolicyAwarePresenter; #[Requires(roles: 'admin')] final class AdminPresenter extends AccessPolicyAwarePresenter { // ... } // Multiple roles #[Requires(roles: ['editor', 'publisher'])] final class ContentPresenter extends AccessPolicyAwarePresenter { // ... }
Resource-based Access with Privileges
For more granular control, you can specify resources and privileges. This integrates with Nette's
Nette\Security\User::isAllowed()
method.
First, define your privileges using an enum (e.g., Alfred\Nette\Security\Enum\Privilege
):
// src/Enum/Privilege.php namespace App\Enum; // Or use Alfred\Nette\Security\Enum\Privilege; enum Privilege: string { case Create = 'create'; case Read = 'read'; case Update = 'update'; case Delete = 'delete'; }
Then, use it in your presenter:
use Alfred\Nette\Security\Attributes\Requires; use Alfred\Nette\Security\UI\AccessPolicyAwarePresenter; use App\Enum\Privilege; // Assuming you defined your own Privilege enum final class ArticlePresenter extends AccessPolicyAwarePresenter { #[Requires(resources: ['article', Privilege::Read])] public function actionShow(int $id): void { // User must be allowed to 'read' the 'article' resource } #[Requires(resources: ['article', Privilege::Update])] public function actionEdit(int $id): void { // User must be allowed to 'update' the 'article' resource } // You can also specify just the resource, and the default privilege (if defined in your enum) will be used #[Requires(resources: 'dashboard')] public function renderDashboard(): void { // User must be allowed to 'dashboard' resource with default privilege } // Multiple resources/privileges #[Requires(resources: [['product', Privilege::Create], ['category', Privilege::Create]])] public function actionNewProduct(): void { // User must be allowed to create both 'product' and 'category' } }
Applying to Methods
The #[Requires]
attribute can also be applied to individual methods within a presenter or component:
use Alfred\Nette\Security\Attributes\Requires; use Alfred\Nette\Security\UI\AccessPolicyAwarePresenter; use App\Enum\Privilege; final class ProductPresenter extends AccessPolicyAwarePresenter { // This applies to all actions/renders in ProductPresenter #[Requires(authentication: true)] public function actionDefault(): void { // Accessible by any authenticated user } #[Requires(roles: 'manager')] public function actionManage(): void { // Accessible only by authenticated users with 'manager' role } #[Requires(resources: ['product', Privilege::Delete])] public function handleDelete(int $id): void { // Accessible only by authenticated users allowed to delete 'product' } }
Customizing Unauthorized/Forbidden Responses
The Abstract\Requires
class handles redirection for unauthenticated users and throws BadRequestException
(403
Forbidden) for unauthorized roles/resources. You can override processUnauthorizedUser
in a custom Requires
attribute
to change this behavior.
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
License
This project is licensed under the MIT License.