hdaklue/porter

Ultra-Minimal Laravel Role Management - Your application's trusted doorkeeper

1.0.10 2025-09-02 11:55 UTC

This package is auto-updated.

Last update: 2025-09-02 20:52:36 UTC


README

Your application's trusted doorkeeper ๐Ÿšช

A lightweight, blazing-fast Laravel role-based access control package that treats roles as what they truly are: domain business logic, not database abstractions. Built for developers who value simplicity, performance, and clean architecture.

"Current RBAC were made for CMSs."

Table of Contents

Why Porter?

"Roles are business logic, not database magic."

Porter was born from the frustration of dealing with bloated RBAC packages that turn simple role assignments into complex database gymnastics. As a fresh package entering the Laravel ecosystem, Porter aims to solve real problems that developers face daily. I believe in providing a solution that is both powerful and elegant, convincing the community that there's a better way to handle role management.

The Problem with Existing Solutions

Most RBAC packages are:

  • Over-engineered - 30+ classes for simple role assignments
  • Database-heavy - Complex joins and foreign key nightmares
  • Performance-blind - Slow queries that don't scale
  • Generic - One-size-fits-all approaches that fit no one

Porter's Approach

Porter treats roles as first-class business entities with their own focused classes, not generic database records.

Porter vs Database-Heavy Approaches

Common question: "Why not use traditional database-based RBAC?"

Feature Database-Heavy RBAC Porter
Role Architecture Database records Individual PHP classes
Permission Storage Database tables PHP class methods
Entity Context Global permissions Entity-specific roles
Type Safety String-based Full PHP type safety
Codebase Size Many classes/tables Minimal architecture
IDE Support Limited Full autocomplete
Performance Multiple DB queries Single table, memory checks

Use Database RBAC if: You need complex global permission matrices
Use Porter if: You need entity-specific roles with type safety and simplicity

Porter's Sweet Spot:

  • SaaS applications with fixed role structures
  • Enterprise applications with well-defined hierarchies
  • Microservices with service-specific roles
  • High-performance applications where DB queries are a bottleneck

Note: For true multi-tenancy (shared codebase, tenant-specific roles), consider database-based RBAC packages like. Porter's class-based approach is optimized for applications where roles are business logic, not tenant-variable data.

Roadmap & Community Input

As a new package, your feedback directly shapes Porter's future! I am actively seeking community input and suggestions to prioritize features and ensure Porter evolves into the most valuable tool for your Laravel projects.

๐ŸŽฏ Potential Features (Vote & Discuss!)

๐Ÿ” Granular Permissions System

Fine-grained permissions with contextual validation.

Benefits:

  • ๐ŸŽฏ Ultra-granular control
  • ๐Ÿ“‹ Context-aware validation
  • ๐Ÿ”„ Dynamic permission evaluation
  • ๐Ÿ› ๏ธ Complex business rules

๐ŸŒ REST API Endpoints

Ready-to-use API endpoints for role management.

Benefits:

  • ๐Ÿ“ฑ Mobile app integration
  • ๐Ÿ”— Third-party service connectivity
  • โšก Frontend SPA support
  • ๐Ÿ“Š External dashboard integration

๐Ÿ—ณ๏ธ Help Me Decide!

I want to build what YOU need most. Please share your feedback on:

  1. Which feature would have the biggest impact on your projects?
  2. What specific use cases do you have in mind?
  3. Are there other features not listed that would be valuable?
  4. What's the best way for the community to provide ongoing feedback?

๐Ÿ’ฌ Community Feedback Options:

We welcome your feedback! Please use:

  • GitHub Discussions for ongoing feature conversations.
  • Project Wiki for collaborative roadmap planning.
  • GitHub Issues for bug reports and feature requests.

๐ŸŽ–๏ธ Recognition

Contributors who provide valuable feedback will be:

  • ๐Ÿ“œ Credited in release notes
  • ๐Ÿท๏ธ Mentioned as community advisors
  • ๐Ÿš€ Early access to beta features
  • ๐Ÿ’ฌ Direct input on API design decisions

Core Features

  • ๐ŸŽฏ Individual Role Classes: Each role is its own focused class extending BaseRole
  • ๐Ÿš€ Ultra-Minimal Architecture: Just 3 core components for role management
  • ๐Ÿ”ฅ Blazing Performance: Optimized for speed with minimal database interaction and built-in caching
  • ๐Ÿ†• Latest Features: Dynamic role factory, config-driven architecture, and enhanced Roster model
  • ๐ŸŽจ Perfect Laravel Integration: Seamlessly works with Gates, Policies, and Blade

๐Ÿ”— Complete Core Features Guide โ†’

Learn about individual role classes, ultra-minimal architecture, blazing performance optimizations, latest features, and perfect Laravel integration.

Suggested Usage

Quick Start

use Hdaklue\Porter\Facades\Porter;

// Basic role operations
Porter::assign($user, $project, 'admin');
$isAdmin = $user->hasRoleOn($project, 'admin');
Porter::changeRoleOn($user, $project, 'editor');

Create Role Classes

# Interactive role creation with guided setup
php artisan porter:create

# Or use the dynamic role factory
$admin = RoleFactory::admin();

๐Ÿ”— Complete Usage Guide โ†’

Learn about role creation methods, real-world examples (SaaS, E-commerce, Healthcare), advanced patterns, testing strategies, and configuration best practices.

Installation

composer require hdaklue/porter

Flexible installation with automatic setup:

# Basic installation - creates Porter directory with BaseRole only
php artisan porter:install

# Full installation - includes 6 default role classes with proper hierarchy
php artisan porter:install --roles

The install command: โœ… Publishes configuration file โœ… Publishes and runs migrations โœ… Creates Porter directory with configurable namespace โœ… Optionally creates 6 default role classes (Admin, Manager, Editor, Contributor, Viewer, Guest) โœ… Provides contextual next-step guidance โœ… Blocks installation in production environment for safety

Advanced Features

Role Hierarchy & Smart Comparisons

use App\Porter\{Admin, ProjectManager, Developer, Viewer};

$admin = new Admin();           // Level 10
$manager = new ProjectManager(); // Level 7
$developer = new Developer();    // Level 3
$viewer = new Viewer();         // Level 1

// Intelligent role comparisons
$admin->isHigherThan($manager);     // true
$manager->isHigherThan($developer); // true
$developer->isLowerThan($admin);    // true
$admin->equals(new Admin());        // true

// Business logic in your controllers
public function canManageProject(User $user, Project $project): bool
{
    $userRole = RoleManager::getRoleOn($user, $project);
    $requiredRole = new ProjectManager();

    return $userRole && $userRole->isHigherThanOrEqual($requiredRole);
}

Enhanced Roster Model with Scopes

use Hdaklue\Porter\Models\Roster;

// Query role assignments with new scopes
$userAssignments = Roster::forAssignable(User::class, $user->id)->get();
$projectRoles = Roster::forRoleable(Project::class, $project->id)->get();
$adminAssignments = Roster::withRoleName('admin')->get();

// Timestamps for audit trails
$assignment = Roster::create([...]);
echo "Assigned on: " . $assignment->created_at;

// Human-readable descriptions
foreach ($assignments as $assignment) {
    echo $assignment->description;
    // Output: "User #123 has role 'admin' on Project #456"
}

Custom Role Classes with Business Logic

final class RegionalManager extends BaseRole
{
    public function getName(): string { return 'regional_manager'; }
    public function getLevel(): int { return 8; }

    public function getRegions(): array
    {
        return ['north', 'south', 'east', 'west'];
    }

    public function canAccessRegion(string $region): bool
    {
        return in_array($region, $this->getRegions());
    }

    public function getMaxBudgetApproval(): int
    {
        return 100000; // $100k approval limit
    }
}

// Usage in business logic
if ($user->hasRoleOn($company, 'regional_manager')) {
    $role = Porter::getRoleOn($user, $company);

    if ($role->canAccessRegion('north') && $budget <= $role->getMaxBudgetApproval()) {
        // Approve the budget for northern region
    }
}

Configuration

The config/porter.php file contains all package settings with configurable options:

return [
    // ID Strategy - Works with your existing models
    'id_strategy' => env('PORTER_ID_STRATEGY', 'ulid'),

    // Database connection
    'database_connection' => env('PORTER_DB_CONNECTION'),

    // Role Directory & Namespace Configuration
    'directory' => env('PORTER_DIRECTORY', app_path('Porter')),
    'namespace' => env('PORTER_NAMESPACE', 'App\\Porter'),

    // Your role classes (auto-populated by porter:install --roles)
    'roles' => [
        App\Porter\Admin::class,
        App\Porter\Manager::class,
        App\Porter\Editor::class,
        // ... add your custom roles here
    ],

    // Security settings
    'security' => [
        'assignment_strategy' => env('PORTER_ASSIGNMENT_STRATEGY', 'replace'), // 'replace' or 'add'
        'key_storage' => env('PORTER_KEY_STORAGE', 'hashed'),  // 'hashed' or 'plain'
        'auto_generate_keys' => env('PORTER_AUTO_KEYS', true),
    ],

    // Caching
    'cache' => [
        'enabled' => env('PORTER_CACHE_ENABLED', true),
        'ttl' => env('PORTER_CACHE_TTL', 3600), // 1 hour
    ],
];

Security Configuration

// .env file
PORTER_ASSIGNMENT_STRATEGY=replace  # Default: Replaces existing roles
PORTER_ASSIGNMENT_STRATEGY=add      # Adds new roles alongside existing ones

PORTER_KEY_STORAGE=hashed     # Secure (default) - SHA256 hashed role keys
PORTER_KEY_STORAGE=plain      # Debug mode - Plain text role keys

PORTER_AUTO_KEYS=true         # Auto-generate keys from class names
PORTER_AUTO_KEYS=false        # Manual key definition required

Laravel Integration

Porter integrates seamlessly with Laravel's authorization system - Gates, Policies, Blade directives, and middleware all work naturally with Porter's entity-specific roles.

// In your Policy
public function update(User $user, Project $project)
{
    return $user->hasRoleOn($project, 'admin');
}

// In your Controller
$this->authorize('update', $project);

// In your Blade templates
@can('update', $project)
    <button>Edit Project</button>
@endcan

๐Ÿ”— Complete Laravel Integration Guide โ†’

Learn about Policies, Middleware, Blade directives, Form Requests, API Resources, Event Listeners, and Testing with Porter.

Migration Strategy

"Porter adapts to YOUR existing models - no changes required!"

Zero-Downtime Migration Strategy

Porter works parallel to your existing role system:

// Phase 1: Install Porter (zero risk)
composer require hdaklue/porter
php artisan porter:install
php artisan migrate  // Just adds the `roaster` table

// Phase 2: Add traits to existing models (optional)
class User extends Authenticatable
{
    use HasUlids;  // Add this trait for modern ID strategy

    // All existing code works unchanged!
}

// Phase 3: Gradually migrate role checks
// Old system keeps working:
if ($user->hasRole('admin')) { /* existing code */ }

// New Porter system runs parallel:
if ($user->hasRoleOn($project, 'admin')) { /* Porter */ }

// Phase 4: Switch over when ready (no rush!)

Flexible ID Strategy

// config/porter.php
'id_strategy' => 'integer',  // For auto-increment IDs (default Laravel)
// OR
'id_strategy' => 'ulid',     // For modern ULID IDs
// OR
'id_strategy' => 'uuid',     // For UUID IDs

Performance

Single Table Architecture

Porter uses exactly ONE database table (roaster) for all role assignments:

-- The ENTIRE role system in one table:
CREATE TABLE roaster (
    id bigint PRIMARY KEY,
    assignable_type varchar(255),  -- 'App\Models\User'  
    assignable_id varchar(255),    -- ULID: '01HBQM5F8G9YZ2XJKPQR4VWXYZ'
    roleable_type varchar(255),    -- 'App\Models\Project'
    roleable_id varchar(255),      -- ULID: '01HBQM6G9HAZB3YLKQRS5WXYZA' 
    role_key varchar(255),         -- 'admin'
    created_at timestamp,
    updated_at timestamp,

    -- Prevents duplicate assignments
    UNIQUE KEY porter_unique (assignable_type, assignable_id, roleable_type, roleable_id, role_key)
);

Performance Benefits:

  • ๐Ÿš€ Fewer database queries - single table operations
  • ๐Ÿƒ Fast role assignments - simple database operations
  • ๐Ÿ’พ Minimal codebase - focused architecture with 8 core classes
  • ๐Ÿง  Efficient memory usage - individual role classes
  • โšก No foreign key overhead - polymorphic relationships

CLI Commands

Porter provides several Artisan commands for role management:

Installation Commands

# Basic installation (config, migrations, Porter directory)
php artisan porter:install

# Full installation with default roles
php artisan porter:install --roles

# Force overwrite existing files
php artisan porter:install --roles --force

Role Management Commands

# Interactive role creation with guided setup
php artisan porter:create

# Create specific role with description
php artisan porter:create ProjectManager --description="Manages development projects"

# List all available roles
php artisan porter:list

# Validate Porter setup and configuration  
php artisan porter:doctor

Command Features

  • Interactive Mode: Guided role creation with automatic level calculation
  • Smart Level Management: Automatic hierarchy management (lowest, highest, lower, higher)
  • Config-Driven: Uses directory and namespace from configuration
  • Production Safe: Install command blocks execution in production
  • Force Override: --force flag for overwriting existing files
  • Type Safety: All generated roles implement RoleContract

Testing

Porter features comprehensive testing with 78 tests and 354 assertions covering real-world scenarios and edge cases.

# Run complete test suite
vendor/bin/pest

# Run with coverage reporting
vendor/bin/pest --coverage

# Test specific components
vendor/bin/pest tests/Feature/RoleValidatorTest.php    # Performance & caching
vendor/bin/pest tests/Feature/RoleManagerDatabaseTest.php  # Database operations
vendor/bin/pest tests/Feature/CreateRoleCommandTest.php    # Interactive commands

Test Coverage

  • RoleValidator (24 tests) - Caching, validation, and hierarchy calculations
  • Commands (17 tests) - Interactive role creation and installation
  • Database (16 tests) - Role assignments and model relationships
  • Unit Tests (15 tests) - Core role logic and factory methods
  • Edge Cases (20+ scenarios) - File corruption, invalid states, race conditions

Requirements

  • PHP 8.1+ - Modern language features
  • Laravel 11.0+ | 12.0+ - Framework compatibility
  • Database with JSON support - MySQL 5.7+, PostgreSQL 9.5+, SQLite 3.1+

Contributing

I welcome contributions! Please see our Contributing Guide for details.

Ways to help:

  • ๐Ÿ› Report bugs and edge cases
  • ๐Ÿ“ Improve documentation
  • ๐Ÿงช Write additional tests
  • ๐Ÿ’ก Suggest new features
  • ๐ŸŒŸ Share your use cases
  • ๐Ÿ—ณ๏ธ Vote on roadmap features

License

MIT License. Free for commercial and personal use.

Porter - Keep it simple, keep it fast, keep it focused. ๐Ÿšช

Built with โค๏ธ for developers who appreciate clean architecture and domain-driven design.