Download the PHP package drago-ex/permission without Composer
On this page you can find all versions of the php package drago-ex/permission. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download drago-ex/permission
More information about drago-ex/permission
Files in drago-ex/permission
Package permission
Short Description Lightweight ACL and role management.
License MIT
Informations about the package permission
Drago Permission
Lightweight ACL and role management. The package provides a central ACL factory, modular permission registration per module, and automatic authorization checks in presenters.
Requirements
- PHP >= 8.3, < 9
- Nette Framework
- Composer
Installation
Features
- Central ACL creation
- Modular permission providers per module
- Default roles: guest, user, admin
- Automatic presenter authorization
- Action and signal based privileges
- Role switch panel for Tracy
Roles
Default roles:
- guest
- user (inherits from guest)
- admin (inherits from user)
Roles are registered automatically.
Permission Factory
PermissionFactory creates a Nette\Security\Permission instance, registers default roles, and runs all registered permission providers.
Providers are collected via DI tags.
Permission Providers
Each module registers its own permissions using a Provider implementation.
Providers:
- register ACL resources
- define allow / deny rules
- live inside the module they belong to
Typical resource naming:
- Backend:Sign
- Frontend:Article
Example provider for a Sign module:
This registers the Backend:Sign resource and grants access to guests (unauthenticated users),
which is the minimum required for the login page to be accessible.
Permission Generator (CLI)
The package provides a generator for module providers:
General usage:
When you use the shared PermissionProvider class name, pass the resource and output directory explicitly.
The class name is intentionally the same in every module and the namespace decides where the provider belongs.
Example for a Sign module:
Example for an Admin module:
Options
--allow-role=<RoleConstant>defaultRoleGuest--allow-privilege=<string>optional privilege argument forallow()--add-resource=<0|1>default1(generate$acl->addResource(...))--allow-with-resource=<0|1>default1(generateallow(..., self::Resource))--allow=<rule>repeatable, custom allow rules--forceoverwrite existing file
--allow formats:
--allow=RoleAdmin--allow=RoleUser,self::Resource--allow=RoleUser,self::Resource,default
Multi-rule example:
Generated register() example:
Providers of Packages
A package that needs providers ships a script that calls create-permission with its arguments and lists it
in composer.json; vendor/bin/drago-commands of drago-ex/project-tools
runs the scripts of all installed packages:
DI Configuration
The package contains a ready configuration in vendor/drago-ex/permission/src/Permission/conf.neon.
It is not loaded automatically; include it in your configuration, or copy its content:
The search section needs nette/robot-loader, which this package requires. The bundled config contains:
permissionFactoryservice registration- automatic
searchregistration forPermissionProviderclasses in%appDir%/Presentation
Permission factory:
Module provider:
For larger applications with many providers, you can use the search section to register all matching classes automatically instead of listing each one individually:
Presenter Authorization
Authorization is handled by the Authorization trait.
- runs automatically on presenter startup
- checks ACL using presenter name and resolved privilege
To activate authorization in a presenter, include the trait:
All presenters extending BasePresenter will then have automatic authorization checks applied.
Unauthorized access:
- not logged in: redirect to
:Sign:inwith a backlink (overridesignInDestination()to change the target); only a plain GET page is stored, a signal or a form is not replayed after signing in - logged in but forbidden: HTTP 403
- a presenter without a registered ACL resource is denied the same way, so forgetting a provider never opens a page
Privilege resolution
The trait automatically resolves which ACL privilege to check based on the current request:
| Situation | Resolved privilege |
|---|---|
| Page load (no signal) | {action}-read |
| Signal from a read-only receiver | {component}-read |
| Signal listed as read-only | {component}-read |
| Any other signal | {component}-write |
| Direct presenter signal (no component) | {signal} |
For component signals, Nette returns a pair from Presenter::getSignal():
The receiver is the component path joined by hyphens. For example, if a presenter has a roles
component and that component contains a dataGrid component with a paginator subcomponent,
Nette can produce a signal like:
This is resolved as:
The authorization trait uses the first receiver segment as the privilege group:
So the signal above resolves to:
when it is configured as read-only, otherwise it resolves to:
Read-only signals
Override readOnlySignals() to declare signal names that should be treated as read operations.
This checks only the signal name, not the component path.
Examples:
| Nette signal | Receiver | Signal | Resolved privilege |
|---|---|---|---|
roles-dataGrid:sort |
roles-dataGrid |
sort |
roles-read |
roles-dataGrid-paginator:page |
roles-dataGrid-paginator |
page |
roles-read |
roles-dataGrid:action |
roles-dataGrid |
action |
roles-write |
Read-only receivers
Override readOnlyReceivers() to declare component path substrings whose signals should always
resolve to read privilege. This checks the receiver path, not the signal name.
Any signal whose receiver name contains one of these strings will be resolved as {component}-read regardless of the signal name.
This is useful for nested controls where the signal name is generic, for example a filter form submit:
The signal name is submit, but the receiver contains Grid-filters, so it resolves to:
Be careful with broad receiver masks such as Grid. They make every signal from that receiver read-only,
including row actions like:
Use broad receiver masks only when the whole component is read-only.
Deciding in code
For more than name lists, override isReadOnlySignal(). It receives the receiver path and the signal
name and replaces both lists. Drago DataGrid knows its own read-only signals (sorting, filters, paging,
page size), so a presenter with grids can simply ask it:
The grid looks the receiver up in the presenter: it does not depend on the name of the grid component,
and a sort signal of another component stays a write. Row actions (roles-dataGrid:action)
stay roles-write.
Full example
With this configuration:
| Nette signal | Resolved privilege |
|---|---|
roles-dataGrid:sort |
roles-read |
roles-dataGrid-paginator:page |
roles-read |
roles-dataGrid-filters:resetFilters |
roles-read |
roles-dataGrid-filters-form:submit |
roles-read |
roles-dataGrid-pageSize:setPageSize |
roles-read |
roles-dataGrid:action |
roles-write |
If you are not sure what Nette produces for a specific request, temporarily inspect:
or log the value inside resolveAclResource().
Write Buttons
The WriteAccess trait lets a component show its add, edit and delete buttons only to those who may use them.
isWriteAllowed() asks for the same {component}-write privilege that the Authorization trait checks for the
component's signals, so it works with static providers as well as with roles from the database:
Hiding a button is only for comfort; the signal itself is still checked by the Authorization trait.
Role Switch in Tracy
While developing, the Tracy bar can switch the roles of the signed-in user, so you can try the application as
another role without a test account. Register the panel (requires tracy/tracy):
The tab shows the current roles (red while they are switched). The panel lists the roles of the ACL, from static providers as well as from the database; My roles brings the real ones back, and signing out forgets the switch. Nette adds bar panels only in debug mode, so the panel never runs in production.
Optional add-ons
The package works without them. Set them up by hand as described below when the project needs them.
Related Package: Dynamic Role Management
For dynamic role and access management, use:
drago-ex/project-permission: https://github.com/drago-ex/project-permission
This package is built on top of drago-ex/permission and provides:
- role creation
- assigning roles to users
- allowing or denying access per role
All versions of permission with dependencies
nette/robot-loader Version ^4.1
nette/security Version ^3.1
nette/application Version ^3.2
nette/http Version ^3.3
nette/di Version ^3.1