Framework updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-02-01 05:16:45 +00:00
parent f48cda006a
commit 0efdcd4cde
27 changed files with 2970 additions and 153 deletions

View File

@@ -11,6 +11,7 @@ use Illuminate\Console\Command;
use Symfony\Component\Process\Process;
use App\RSpade\Core\Debug\Debugger;
use App\RSpade\Core\Models\Login_User_Model;
use App\RSpade\Core\Portal\Portal_User_Model;
/**
* RSX Route Debug Command
@@ -156,7 +157,9 @@ class Route_Debug_Command extends Command
{--console-list : Alias for --console-log to display all console output}
{--screenshot-width= : Screenshot width (px or preset: mobile, iphone-mobile, tablet, desktop-small, desktop-medium, desktop-large). Defaults to 1920}
{--screenshot-path= : Path to save screenshot file (triggers screenshot capture, max height 5000px)}
{--dump-dimensions= : Add data-dimensions attribute to elements matching selector (for layout debugging)}';
{--dump-dimensions= : Add data-dimensions attribute to elements matching selector (for layout debugging)}
{--portal : Test portal routes (uses /_portal/ prefix and portal authentication)}
{--portal-user= : Test as specific portal user ID or email (requires --portal)}';
/**
* The console command description.
@@ -213,15 +216,46 @@ class Route_Debug_Command extends Command
$url = '/' . $url;
}
// Get portal mode options
$portal_mode = $this->option('portal');
$portal_user_input = $this->option('portal-user');
// Validate portal options
if ($portal_user_input && !$portal_mode) {
$this->error('--portal-user requires --portal flag');
return 1;
}
// Normalize URL for portal mode (strip /_portal/ prefix if present)
if ($portal_mode && str_starts_with($url, '/_portal')) {
$url = substr($url, 8); // Remove '/_portal'
if ($url === '' || $url === false) {
$url = '/';
}
}
// Get user ID from options (accepts ID or email)
$user_id = $this->option('user');
if ($user_id !== null) {
if ($portal_mode) {
$this->error('Use --portal-user instead of --user when --portal flag is set');
return 1;
}
$user_id = $this->resolve_user($user_id);
if ($user_id === null) {
return 1; // Error already displayed
}
}
// Get portal user ID from options (accepts ID or email)
$portal_user_id = null;
if ($portal_user_input !== null) {
$portal_user_id = $this->resolve_portal_user($portal_user_input);
if ($portal_user_id === null) {
return 1; // Error already displayed
}
}
// Get log flag
$show_log = $this->option('log');
@@ -384,16 +418,26 @@ class Route_Debug_Command extends Command
// This prevents unauthorized requests from hijacking sessions via headers
$dev_auth_token = null;
if ($user_id) {
$dev_auth_token = $this->generate_dev_auth_token($url, $user_id);
$dev_auth_token = $this->generate_dev_auth_token($url, $user_id, false);
} elseif ($portal_user_id) {
$dev_auth_token = $this->generate_dev_auth_token($url, $portal_user_id, true);
}
// Build command arguments
$command_args = ['node', $playwright_script, $url];
if ($portal_mode) {
$command_args[] = '--portal';
}
if ($user_id) {
$command_args[] = "--user={$user_id}";
}
if ($portal_user_id) {
$command_args[] = "--portal-user={$portal_user_id}";
}
if ($dev_auth_token) {
$command_args[] = "--dev-auth-token={$dev_auth_token}";
}
@@ -560,6 +604,15 @@ class Route_Debug_Command extends Command
$this->line(' php artisan rsx:debug /admin --user=admin@example.com # Test as user by email');
$this->line('');
$this->comment('PORTAL ROUTES:');
$this->line(' php artisan rsx:debug /dashboard --portal --portal-user=1');
$this->line(' # Test portal as user ID 1');
$this->line(' php artisan rsx:debug /_portal/dashboard --portal --portal-user=1');
$this->line(' # Same (/_portal/ prefix stripped)');
$this->line(' php artisan rsx:debug /mail --portal --portal-user=client@example.com');
$this->line(' # Test portal as user by email');
$this->line('');
$this->comment('TESTING RSX JAVASCRIPT (use return or console.log for output):');
$this->line(' php artisan rsx:debug / --eval="return typeof Rsx_Time" # Check if class exists');
$this->line(' php artisan rsx:debug / --eval="return Rsx_Time.now_iso()" # Get current time');
@@ -677,6 +730,43 @@ class Route_Debug_Command extends Command
return $user_id;
}
/**
* Resolve portal user identifier to user ID
*
* Accepts either a numeric user ID or an email address.
* Validates that the portal user exists in the database.
*
* @param string $user_input Portal user ID or email address
* @return int|null User ID or null if not found (error already displayed)
*/
protected function resolve_portal_user(string $user_input): ?int
{
// Check if input is an email address
if (str_contains($user_input, '@')) {
$portal_user = Portal_User_Model::where('email', $user_input)->first();
if (!$portal_user) {
$this->error("Portal user not found: {$user_input}");
return null;
}
return $portal_user->id;
}
// Input is a user ID - validate it exists
if (!ctype_digit($user_input)) {
$this->error("Invalid portal user identifier: {$user_input} (must be numeric ID or email address)");
return null;
}
$user_id = (int) $user_input;
$portal_user = Portal_User_Model::find($user_id);
if (!$portal_user) {
$this->error("Portal user ID not found: {$user_id}");
return null;
}
return $user_id;
}
/**
* Generate a signed dev auth token for Playwright requests
*
@@ -686,9 +776,10 @@ class Route_Debug_Command extends Command
*
* @param string $url The URL being tested
* @param int $user_id The user ID to authenticate as
* @param bool $is_portal Whether this is a portal user (vs main site user)
* @return string The signed token
*/
protected function generate_dev_auth_token(string $url, int $user_id): string
protected function generate_dev_auth_token(string $url, int $user_id, bool $is_portal = false): string
{
$app_key = config('app.key');
if (!$app_key) {
@@ -700,6 +791,7 @@ class Route_Debug_Command extends Command
$payload = json_encode([
'url' => $url,
'user_id' => $user_id,
'portal' => $is_portal,
]);
// Sign with HMAC-SHA256