1. Go to this page and download the library: Download managur/rick-role library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
managur / rick-role example snippets
use RickRole\Rick;
use RickRole\Configuration;
use RickRole\Strategy\DenyWinsStrategy;
use RickRole\Voter\DoctrineDefaultVoter;
use Doctrine\DBAL\DriverManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMSetup;
// Set up Doctrine with SQLite (simplest setup)
$paths = [__DIR__ . '/src/Entity'];
$isDevMode = true;
$dbParams = [
'driver' => 'pdo_sqlite',
'path' => __DIR__ . '/database.sqlite',
];
$doctrineConfig = ORMSetup::createAttributeMetadataConfiguration($paths, $isDevMode);
$connection = DriverManager::getConnection($dbParams, $doctrineConfig);
$entityManager = new EntityManager($connection, $doctrineConfig);
// Configure Rick with a default voter
$rickConfig = new Configuration();
$rickConfig->addVoter(new DoctrineDefaultVoter($entityManager, new DenyWinsStrategy()));
$rick = new Rick($rickConfig);
// Check if a user is allowed to create a post
$userId = 123; // This is just the user ID from your application
$permission = 'create post';
if ($rick->allows($userId, $permission)) {
echo "Permission granted!";
} else {
echo "Access denied!";
}
use RickRole\Strategy\Decision;
use RickRole\Strategy\StrategyInterface;
use RickRole\Voter\VoteResult;
final class LastDenyWinsStrategy implements StrategyInterface
{
public function decide(array $voteResults): Decision
{
$deciding = null;
foreach ($voteResults as $voteResult) {
if ($voteResult->isDeny() || ($voteResult->isAllow() && $deciding === null)) {
$deciding = $voteResult;
}
}
if ($deciding === null) {
return Decision::byStrategy(VoteResult::deny('No voter allowed or denied'));
}
return Decision::byVote($deciding);
}
public function shouldStopVoting(VoteResult $voteResult): bool
{
return false;
}
}
// $post is any subject from your application
$reason = null;
$allowed = $rick->allows(userId: 123, to: 'edit post', onThis: $post, because: $reason);
//--------- More on these ☝️ named parameters later! ---------//
echo $reason->permission; // 'edit post'
echo $reason->userId; // 123
$reason->subject; // $post object
echo $reason->decision; // 'allow' or 'deny'
echo $reason->message; // Human-readable reason from the strategy
$reason->code; // Programmatic code from the deciding vote, or null
echo $reason->given(); // Message given by the deciding vote
$reason->decidingVote; // The Vote that decided, or null if the strategy decided by itself
// Every vote that was cast, in vote order
foreach ($reason->votes as $vote) {
echo $vote->voter . ': [' . $vote->decision . '] ' . $vote->message . "\n";
}
// Or all at once, one line per vote and then the final decision
echo $reason->trace();
enum MfaReason: string
{
case Mandatory = 'mandatory';
case Cleanup = 'cleanup';
}
if ($rick->disallows(userId: $userId, to: 'mfa.disable.submit', because: $reason)) {
if ($reason->is(MfaReason::Mandatory)) {
// Show the control disabled, with an explanation
}
}
// Without named parameters
if ($rick->disallows($userId, 'mfa.disable.submit', null, $reason)) {
if ($reason->wasDecidedBy(MfaVoter::class)) {
echo $reason->given();
}
}
if ($rick->allows(userId: $userId, to: 'mfa.disable.submit', because: $reason)) {
if ($reason->has(MfaReason::Cleanup)) {
// MfaVoter gave the Cleanup code, whatever the order of the voters
}
}
use RickRole\Configuration;
use RickRole\Rick;
use RickRole\Voter\DoctrineDefaultVoter;
use RickRole\Strategy\DenyWinsStrategy;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$config = new Configuration();
// $entityManager is your Doctrine EntityManager (see Database Setup below)
// Add voters to the stack
$config->addVoter(new DoctrineDefaultVoter($entityManager, new DenyWinsStrategy()));
// Configure strategy (optional - DenyWinsStrategy is default)
$config->setStrategy(new DenyWinsStrategy());
// Configure logging (optional - NullLogger is used by default)
$logger = new Logger('rick-role');
$logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
$config->setLogger($logger);
$rick = new Rick($config);
use Doctrine\DBAL\DriverManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMSetup;
$paths = [__DIR__ . '/src/Entity'];
$isDevMode = true;
$dbParams = [
'driver' => 'pdo_sqlite',
'path' => __DIR__ . '/database.sqlite',
];
$config = ORMSetup::createAttributeMetadataConfiguration($paths, $isDevMode);
$connection = DriverManager::getConnection($dbParams, $config);
$entityManager = new EntityManager($connection, $config);
// Simple permission check
if ($rick->allows($userId, 'view dashboard')) {
// Show dashboard
}
// Permission check with subject context
if ($rick->allows($userId, 'edit post', $post)) {
// Allow editing this specific post
}
// Inverse check
if ($rick->disallows($userId, 'delete user')) {
// User cannot delete users
}
// Not using named arguments
if ($rick->allows($userId, $permission, $post)) {
echo "Permission granted!";
}
// Using named arguments
if ($rick->allows(userId: $userId, to: $permission, onThis: $post)) {
echo "Permission granted!";
}
// Mixing named arguments
if ($rick->allows($userId, to: $permission, onThis: $post)) {
echo "Permission granted!";
}
// Mixing named arguments further
if ($rick->allows($userId, $permission, onThis: $post)) {
echo "Permission granted!";
}
use RickRole\Voter\VoterInterface;
use RickRole\Voter\VoteResult;
class BusinessHoursVoter implements VoterInterface
{
public function vote(
string|int $userId,
string|\Stringable $permission,
mixed $subject = null
): VoteResult {
// Only allow access during business hours
$hour = (int) date('H');
if ($hour >= 9 && $hour <= 17) {
return VoteResult::allow('Access granted during business hours');
}
return VoteResult::deny('Access denied outside business hours');
}
}
// Add to configuration
$config->addVoter(new BusinessHoursVoter());
return VoteResult::deny('MFA is mandatory, so it cannot be disabled', code: MfaReason::Mandatory);
// Without named parameters
return VoteResult::deny('MFA is mandatory, so it cannot be disabled', null, MfaReason::Mandatory);
// Check multiple permissions
$canManageUsers = $rick->allows(userId: $userId, to: 'manage users');
$canDeleteUsers = $rick->allows(userId: $userId, to: 'delete user', onThis: $targetUser);
if ($canManageUsers && $canDeleteUsers) {
// User can delete this specific user
}
// Get detailed reasoning for debugging
$reason = null;
$canEdit = $rick->allows(userId: $userId, to: 'edit post', onThis: $post, because: $reason);
if ($canEdit === false) {
error_log((string) $reason);
}
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$logger = new Logger('rick-role');
$logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
$config = new Configuration();
$config->setLogger($logger);
use RickRole\Rick;
use RickRole\Configuration;
use RickRole\Strategy\DenyWinsStrategy;
use RickRole\Voter\DoctrineDefaultVoter;
class CustomPermission implements Stringable {
public function __toString(): string {
return 'custom-permission';
}
}
// $entityManager is your Doctrine EntityManager (see Database Setup)
$config = new Configuration();
$config->addVoter(new DoctrineDefaultVoter($entityManager, new DenyWinsStrategy()));
$rick = new Rick($config);
$permission = new CustomPermission();
if ($rick->allows(123, $permission)) {
// User has the custom permission
}
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use RickRole\Configuration;
use RickRole\Rick;
use RickRole\Strategy\DenyWinsStrategy;
use RickRole\Voter\DoctrineDefaultVoter;
// Create logger with multiple handlers
$logger = new Logger('rick-role');
// Log all levels to rotating file for debugging
$logger->pushHandler(new RotatingFileHandler(
__DIR__ . '/logs/rick-role.log',
30, // Keep 30 days of logs
Logger::DEBUG
));
// Log only INFO and above to stdout for production
$logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
// $entityManager is your Doctrine EntityManager (see Database Setup)
$config = new Configuration();
$config->addVoter(new DoctrineDefaultVoter($entityManager, new DenyWinsStrategy()));
$config->setLogger($logger);
$rick = new Rick($config);
// Now all permission checks will be logged
$rick->allows(123, 'create post');
bash
# Run migrations
vendor/bin/doctrine-migrations migrate --configuration=migrations.php
bash
# Check migration status
vendor/bin/doctrine-migrations status --configuration=migrations.php
# Run migrations
vendor/bin/doctrine-migrations migrate --configuration=migrations.php
# Generate migration diff (shows SQL changes)
vendor/bin/doctrine-migrations diff --configuration=migrations.php
[2025-01-15 10:30:45] rick-role.DEBUG: Voter decision {"user_id":123,"permission":"create post","voter":"RickRole\\Voter\\DefaultVoter","decision":"allow","message":"User has permission through role: editor","code":null}
[2025-01-15 10:30:45] rick-role.INFO: Permission check completed {"user_id":123,"permission":"create post","subject":"Post#123","decision":"allow","allowed":true,"duration_ms":2.45,"voter_count":1,"strategy":"RickRole\\Strategy\\DenyWinsStrategy","reason":"No deny votes found - User has permission through role: editor","code":null}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.