Это модуль разрешений, который можно использовать в ваших проектах, если у вас есть несколько ролей в вашем приложении, и каждая роль имеет немного разную функциональность. Этот модуль позволяет определить разрешения для каждой роли, а затем проверить, имеет ли текущий пользователь разрешение на доступ к определенной странице или выполнение определенного действия.
Нажмите сюда для репозитория на GitHub.
Запустите composer require flightphp/permissions и вы готовы к работе!
composer require flightphp/permissions
Сначала вам нужно настроить ваши разрешения, затем сообщить вашему приложению, что означают эти разрешения. В конечном итоге вы проверите ваши разрешения с помощью $Permissions->has(), ->can() или is(). has() и can() имеют одинаковую функциональность, но названы по-разному, чтобы сделать ваш код более читаемым.
$Permissions->has()
->can()
is()
has()
can()
Давайте предположим, что у вас есть функция в вашем приложении, которая проверяет, вошел ли пользователь в систему. Вы можете создать объект разрешений следующим образом:
// index.php require 'vendor/autoload.php'; // некоторый код // затем у вас вероятно есть что-то, что говорит вам, какая текущая роль у человека // скорее всего у вас есть что-то, откуда вы извлекаете текущую роль // из переменной сеанса, которая определяет это // после входа в систему у кого-то должна быть роль 'guest' или 'public'. $current_role = 'admin'; // настройка разрешений $permission = new \flight\Permission($current_role); $permission->defineRule('loggedIn', function($current_role) { return $current_role !== 'guest'; }); // Вам вероятно захочется сохранить этот объект где-то в Flight Flight::set('permission', $permission);
Затем в контроллере где-то вы можете иметь что-то вроде этого.
<?php // некоторый контроллер class SomeController { public function someAction() { $permission = Flight::get('permission'); if ($permission->has('loggedIn')) { // сделать что-то } else { // сделать что-то другое } } }
Вы также можете использовать это для отслеживания, есть ли у них разрешение на выполнение определенного действия в вашем приложении. Например, если у вас есть способ, как пользователи могут взаимодействовать с публикацией в вашем программном обеспечении, вы можете проверить, имеют ли они разрешение на выполнение определенных действий.
$current_role = 'admin'; // настройка разрешений $permission = new \flight\Permission($current_role); $permission->defineRule('post', function($current_role) { if($current_role === 'admin') { $permissions = ['create', 'read', 'update', 'delete']; } else if($current_role === 'editor') { $permissions = ['create', 'read', 'update']; } else if($current_role === 'author') { $permissions = ['create', 'read']; } else if($current_role === 'contributor') { $permissions = ['create']; } else { $permissions = []; } return $permissions; }); Flight::set('permission', $permission);
Затем где-то в контроллере...
class PostController { public function create() { $permission = Flight::get('permission'); if ($permission->can('post.create')) { // сделать что-то } else { // сделать что-то еще } } }
Вы можете внедрять зависимости в замыкание, которое определяет разрешения. Это полезно, если у вас есть какой-то переключатель, идентификатор или любая другая точка данных, которую вы хотите проверить. То же самое работает для вызовов вида Class->Method, за исключением того, что аргументы определяются в методе.
$Permission->defineRule('order', function(string $current_role, MyDependency $MyDependency = null) { // ... код }); // в вашем файле контроллера public function createOrder() { $MyDependency = Flight::myDependency(); $permission = Flight::get('permission'); if ($permission->can('order.create', $MyDependency)) { // сделать что-то } else { // сделать что-то еще } }
namespace MyApp; class Permissions { public function order(string $current_role, MyDependency $MyDependency = null) { // ... код } }
Вы также можете использовать классы для определения ваших разрешений. Это полезно, если у вас много разрешений, и вы хотите, чтобы ваш код был чистым. Вы можете сделать что-то вроде этого:
<?php // код инициализации $Permissions = new \flight\Permission($current_role); $Permissions->defineRule('order', 'MyApp\Permissions->order'); // myapp/Permissions.php namespace MyApp; class Permissions { public function order(string $current_role, int $user_id) { // Предположим, что вы это настроили заранее /** @var \flight\database\PdoWrapper $db */ $db = Flight::db(); $allowed_permissions = [ 'read' ]; // каждый может просматривать заказ if($current_role === 'manager') { $allowed_permissions[] = 'create'; // менеджеры могут создавать заказы } $some_special_toggle_from_db = $db->fetchField('SELECT some_special_toggle FROM settings WHERE id = ?', [ $user_id ]); if($some_special_toggle_from_db) { $allowed_permissions[] = 'update'; // если у пользователя есть особый переключатель, он может обновлять заказы } if($current_role === 'admin') { $allowed_permissions[] = 'delete'; // администраторы могут удалять заказы } return $allowed_permissions; } }
Здесь примечательно то, что есть также сокращение, которое можно использовать (которое также может быть кешировано!!!), где вы просто говорите классу разрешений сопоставить все методы в классе в разрешения. Поэтому, если у вас есть метод с именем order() и метод с именем company(), они будут автоматически сопоставлены, и вы сможете просто выполнить $Permissions->has('order.read') или $Permissions->has('company.read'), и это сработает. Определение этого очень сложно, так что держитесь здесь со мной. Просто вам нужно сделать это:
order()
company()
$Permissions->has('order.read')
$Permissions->has('company.read')
Создайте класс разрешений, которые вы хотите сгруппировать вместе.
class MyPermissions { public function order(string $current_role, int $order_id = 0): array { // код определения разрешений return $permissions_array; } public function company(string $current_role, int $company_id): array { // код определения разрешений return $permissions_array; } }
Затем сделайте разрешения обнаруживаемыми с использованием этой библиотеки.
$Permissions = new \flight\Permission($current_role); $Permissions->defineRulesFromClassMethods(MyApp\Permissions::class); Flight::set('permissions', $Permissions);
Наконец, вызовите разрешение в вашей кодовой базе, чтобы проверить, разрешено ли пользователю выполнение заданного разрешения.
class SomeController { public function createOrder() { if(Flight::get('permissions')->can('order.create') === false) { die('Вы не можете создать заказ. Извините!'); } } }
Для включения кэширования, см. простую библиотеку wruczak/phpfilecache. Пример включения приведен ниже.
// этот $app может быть частью вашего кода, или // вы можете просто передать null, и он извлечет из Flight::app() в конструкторе $app = Flight::app(); // Теперь для этого принимается файловое кэширование. Другие могут легко // быть добавлены в будущем. $Cache = new Wruczek\PhpFileCache\PhpFileCache; $Permissions = new \flight\Permission($current_role, $app, $Cache); $Permissions->defineRulesFromClassMethods(MyApp\Permissions::class, 3600); // 3600 - это сколько секунд кэшировать это. Оставьте это, чтобы не использовать кэширование
И впереди!