A sophisticated Laravel 12 application implementing enterprise-level flow and task management with advanced role-based access control (RBAC) and multi-tenant architecture.
KluePortal uses a triple-database architecture to separate concerns and optimize performance:
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β RBAC Database β β Business Databaseβ β Original Databaseβ
β (rbac conn) β β (business_db) β β (mysql conn) β
βββββββββββββββββββ€ βββββββββββββββββββ€ βββββββββββββββββββ€
β β’ Users β β β’ Documents β β β’ Flows β
β β’ Tenants β β β’ Feedbacks β β β’ Stages β
β β’ Roles β β β’ Deliverables β β β’ Profiles β
β β’ Permissions β β β’ Versions β β β’ Side Notes β
β β’ Notifications β β β’ Acknowledgmts β β β’ Jobs β
β β’ Login Logs β β β β β
β β’ Invitations β β β β β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
- Multi-tenant RBAC with 1-hour caching (226ms response, 5MB memory)
- Performance optimized role management via hdaklue/marg-rbac package
- Cross-database relationships with proper connection handling
- Production-safe migration commands with environment protection
- ULIDs for all primary keys for better performance
- PHP 8.3+
- Laravel 12.26+
- MySQL 5.7+
- Redis (for caching and sessions)
- Composer
- Clone the repository
git clone <repository-url> klueportal
cd klueportal- Install dependencies
composer install
npm install- Environment setup
cp .env.example .env
php artisan key:generate- Configure environment variables
# Main Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=klueportal
DB_USERNAME=root
DB_PASSWORD=
# Business Database
FEEDBACK_DB_HOST=127.0.0.1
FEEDBACK_DB_PORT=3306
FEEDBACK_DB_DATABASE=klue_portal_business
FEEDBACK_DB_USERNAME=root
FEEDBACK_DB_PASSWORD=
# RBAC Database Configuration
RBAC_DB_CONNECTION=rbac
RBAC_DB_DRIVER=mysql
RBAC_DB_HOST=127.0.0.1
RBAC_DB_PORT=3306
RBAC_DB_DATABASE=marg-rbac
RBAC_DB_USERNAME=root
RBAC_DB_PASSWORD=
# RBAC Session & Cache
RBAC_SESSION_DRIVER=redis
RBAC_SESSION_CONNECTION=default
RBAC_CACHE_ENABLED=true
RBAC_CACHE_TTL=3600
RBAC_CACHE_CONNECTION=default- Setup databases
# Create databases manually in MySQL:
# - klueportal (main)
# - klue_portal_business (business)
# - marg-rbac (RBAC)
# Run complete database setup
php artisan marg:refresh-db --seed- Build assets
npm run buildphp artisan migrate is NOT recommended in this multi-database architecture. Use these specific commands:
# Refresh all databases and seed with test data
php artisan marg:refresh-db --seed
# Refresh all databases without seeding
php artisan marg:refresh-db --force# RBAC database only
php artisan rbac:migrate
php artisan rbac:fresh-migrate --force
php artisan rbac:seed
# Business database only
php artisan migrate --database=business_db --path=database/migrations/business-db
# Original database only
php artisan migrate --database=mysql --path=database/migrations- Environment protection: Destructive commands only work in
local/testingenvironments - No dangerous operations: Uses
migrate:freshinstead ofdb:wipe - Connection isolation: Each database uses its own connection and migrations
Email: test@example.com
Password: password
Role: Admin on 5 tenants
- Authentication data: Stored in RBAC database (
userstable) - Profile data: Stored in main database (
profilestable) - Cross-database relationship: User β Profile via foreign key
βββ ADMIN (Full system access)
βββ MANAGER (Elevated permissions)
βββ USER (Standard permissions)
- Multi-tenant isolation: Users can belong to multiple tenants
- Active tenant switching: Session-based tenant context
- Role assignments: Per-tenant role assignments via
model_has_roles
- 1-hour cache TTL for optimal performance
- Redis-based caching for scalability
- Automatic cache invalidation on role changes
// Extends package User model
class User extends RbacUser implements FilamentUser, HasTenants
{
protected $connection = 'rbac'; // Lives in RBAC database
public function profile(): HasOne
public function getAssignedTenants() // Override for correct morph mapping
public function flows(): MorphToMany
}class Profile extends Model
{
protected $connection = 'mysql'; // Lives in main database
protected $fillable = ['user_id', 'avatar', 'timezone'];
}class Flow extends Model implements RoleableEntity
{
protected $connection = 'mysql'; // Lives in main database
use ManagesParticipants; // RBAC functionality
}The application handles relationships across three databases:
// User (RBAC) β Profile (Main)
$user->profile->avatar
// User (RBAC) β Flows (Main) via RBAC pivot
$user->flows()->where('status', 'active')
// Flow (Main) β Documents (Business)
$flow->documents()->where('type', 'requirement')database/migrations/
βββ / # Main database migrations
βββ business-db/ # Business database migrations
βββ rbac/ # RBAC database migrations (published)
// Database connections via traits
use App\Concerns\Database\LivesInOriginalDB; // mysql connection
use App\Concerns\Database\LivesInBusinessDB; // business_db connection
use Hdaklue\MargRbac\Concerns\Database\LivesInRbacDB; // rbac connection
// RBAC functionality
use Hdaklue\MargRbac\Contracts\Role\RoleableEntity;
use Hdaklue\MargRbac\Concerns\Role\ManagesParticipants;// Application enums (in app/Enums/)
use App\Enums\AssigneeRole; // ASSIGNEE, APPROVER, REVIEWER, OBSERVER
use App\Enums\FlowStage; // Flow workflow stages
// Package enums (from marg-rbac package)
use Hdaklue\MargRbac\Enums\Role\RoleEnum; // ADMIN, MANAGER, USER- Laravel Livewire 3 - Server-side reactivity
- Alpine.js 3 - Client-side interactivity
- Tailwind CSS 4 - Utility-first styling
- Filament 4 - Admin interface
- Hero Icons - SVG icon set
- Use
zincinstead ofgray,skyinstead ofblue - Alpine event syntax:
@click,.stop,.prevent,.window - Components:
x-tooltip,x-anchorfor dropdowns - Color palette: Sky (primary), Zinc (gray), Indigo (secondary)
- hdaklue/marg-rbac - Multi-tenant RBAC system
- lorisleiva/laravel-actions - Single-purpose action classes
- filament/filament - Admin interface framework
- Package config: Published to
config/margrbac.php - Environment overrides: All settings configurable via
.env - No hardcoded values: Everything uses environment variables
# Run all tests
php artisan test
# Run specific tests
php artisan test tests/Feature/ExampleTest.php
# Filter by test name
php artisan test --filter=testName// Factory usage
$user = User::factory()->create();
$user = User::factory()->admin()->create(); // With admin role
// Tenant assignments
$tenant = Tenant::factory()->create();
$tenant->addParticipant($user, RoleEnum::ADMIN);- Production safety: Destructive commands disabled in production
- Database separation: Ensure all three databases exist
- Redis configuration: Required for caching and sessions
- Queue workers: Recommended for background processing
- RBAC caching: 1-hour TTL with Redis
- Database indexing: Proper indexes on foreign keys and polymorphic relationships
- ULID usage: Better performance than UUID for primary keys
- RBAC response time: 226ms average
- Memory usage: ~5MB for role resolution
- Cache hit ratio: >90% for role assignments
- Database connections: Optimized connection pooling
- Notification errors: Ensure notifications table exists in RBAC database
- Tenant access issues: Check user has proper tenant assignments
- Migration conflicts: Use database-specific migration commands
- Cache issues: Clear RBAC cache with
php artisan cache:clear
# Check database connections
php artisan tinker
> config('database.connections')
# Verify user tenant assignments
> $user = User::find(1)
> $user->getAssignedTenants()
# Test RBAC functionality
> $user->isAssignedTo($tenant)This project is proprietary software. All rights reserved.
- Follow existing code conventions
- Use database-specific migration commands
- Test across all three databases
- Maintain RBAC performance standards
- Document any architectural changes
Built with β€οΈ using Laravel 12, Livewire 3, and the power of multi-tenant RBAC.