Prepare Beta Version

This commit is contained in:
2025-05-29 10:05:27 -06:00
parent a7002701f5
commit ea6b04f3f4
254 changed files with 5653 additions and 6569 deletions

View File

@ -1,9 +1,9 @@
<?php
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Cache;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Cache\KonekoCacheManager;
use Koneko\VuexyAdmin\Application\Cache\Manager\KonekoCacheManager;
class KonekoCacheHelperCommand extends Command
{
@ -14,11 +14,9 @@ class KonekoCacheHelperCommand extends Command
{--show : Muestra la información del cache manager}
{--ttl : Muestra el TTL efectivo}
{--driver : Muestra el driver actual}
{--enabled : Muestra si el cache está habilitado}
{--tags : Muestra las etiquetas asociadas (si el driver lo permite)}
';
{--enabled : Muestra si el cache está habilitado}';
protected $description = 'Gestor de Cache Ecosistema Koneko: TTL, driver, flush, debug, enabled, etiquetas';
protected $description = 'Gestor de Cache Ecosistema Koneko: TTL, driver, flush, enabled';
public function handle(): int
{
@ -49,27 +47,21 @@ class KonekoCacheHelperCommand extends Command
}
if ($this->option('enabled')) {
$this->line("✅ Habilitado: <info>" . ($manager->enabled() ? 'true' : 'false') . "</info>");
$this->line("✅ Habilitado: <info>" . ($manager->isEnabled() ? 'true' : 'false') . "</info>");
}
if ($this->option('ttl')) {
$this->line("🕒 TTL efectivo: <info>{$manager->ttl()} seg</info>");
$this->line("🕒 TTL efectivo: <info>{$manager->resolveTTL()} seg</info>");
}
if ($this->option('driver')) {
$this->line("⚙️ Driver actual: <info>{$manager->driver()}</info>");
}
if ($this->option('tags')) {
$tags = $manager->tags();
$this->line("🏷 Etiquetas: <info>" . implode(', ', $tags) . "</info>");
}
if (! $this->option('show') &&
! $this->option('ttl') &&
! $this->option('enabled') &&
! $this->option('driver') &&
! $this->option('tags') &&
! $this->option('flush')) {
$this->warn("⚠️ No se especificó ninguna acción. Usa --help para ver las opciones disponibles.");

View File

@ -1,6 +1,6 @@
<?php
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Geolocationg;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;

View File

@ -2,12 +2,12 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Layout;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Auth;
use Koneko\VuexyAdmin\Models\User;
use Koneko\VuexyAdmin\Application\UX\Menu\VuexyMenuBuilderService;
use Koneko\VuexyAdmin\Application\UX\Menu\VuexyMenuBuilder;
use Koneko\VuexyAdmin\Application\UX\Menu\VuexyMenuRegistry;
use Symfony\Component\Console\Attribute\AsCommand;
@ -52,7 +52,7 @@ class VuexyMenuBuildCommand extends Command
if ($visitor) {
$this->info('Menú para visitante:');
$menu = app(VuexyMenuBuilderService::class)->getForUser(null);
$menu = app(VuexyMenuBuilder::class)->getForUser(null);
$this->renderMenu($menu, $showJson, $showDump, $summary, $targetId);
return self::SUCCESS;
}
@ -75,8 +75,8 @@ class VuexyMenuBuildCommand extends Command
if ($fresh) {
$user
? VuexyMenuBuilderService::clearCacheForUser($user)
: VuexyMenuBuilderService::clearAllCache();
? VuexyMenuBuilder::clearCacheForUser($user)
: VuexyMenuBuilder::clearAllCache();
$this->info('Caché de menú limpiado.');
}
@ -102,7 +102,7 @@ class VuexyMenuBuildCommand extends Command
}
}
$menu = app(VuexyMenuBuilderService::class)->getForUser($user);
$menu = app(VuexyMenuBuilder::class)->getForUser($user);
$this->renderMenu($menu, $showJson, $showDump, $summary, $targetId);
return self::SUCCESS;
}
@ -206,4 +206,4 @@ class VuexyMenuBuildCommand extends Command
$user->syncRoles($role);
return $user;
}
}
}

View File

@ -2,11 +2,11 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Layout;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Bootstrap\Registry\KonekoModuleRegistry;
use Koneko\VuexyAdmin\Application\UX\Menu\VuexyMenuRegistry;
use Koneko\VuexyAdmin\Application\Bootstrap\KonekoModuleRegistry;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'vuexy:menu:list-modules')]

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Notifications;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Models\DeviceToken;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Koneko\VuexyApisAndIntegrations\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Orquestator;
use Illuminate\Console\Command;
use Symfony\Component\Console\Helper\Table;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Orquestator;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Bootstrap\Extenders\Catalog\CatalogModuleRegistry;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Orquestator;
use Illuminate\Console\Command;
use Symfony\Component\Process\Process;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\Orquestator;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Seeding\SeederOrchestrator;

View File

@ -1,12 +1,12 @@
<?php
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\RBAC;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Koneko\VuexyAdmin\Application\Bootstrap\KonekoModuleBootManager;
use Koneko\VuexyAdmin\Application\Bootstrap\KonekoModuleRegistry;
use Koneko\VuexyAdmin\Application\RBAC\KonekoRbacSyncManager;
use Koneko\VuexyAdmin\Application\Bootstrap\Manager\KonekoModuleBootManager;
use Koneko\VuexyAdmin\Application\Bootstrap\Registry\KonekoModuleRegistry;
use Koneko\VuexyAdmin\Application\RBAC\Sync\KonekoRbacSyncManager;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'vuexy:rbac')]

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
namespace Koneko\VuexyAdmin\Console\Commands\UI;
use Illuminate\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;

View File

@ -1,9 +1,9 @@
<?php
namespace Koneko\VuexyAdmin\Console\Commands\Security;
namespace Koneko\VuexyAdmin\Console\Commands\Vault;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Security\VaultKeyService;
use Koneko\VuexyAdmin\Application\Vault\VaultKeyService;
class VaultKeyCommand extends Command
{
@ -69,7 +69,7 @@ class VaultKeyCommand extends Command
protected function listKeys(VaultKeyService $service): void
{
$keys = \Koneko\VuexyAdmin\Models\VaultKey::all(['alias', 'owner_project', 'algorithm', 'is_active', 'rotated_at']);
$keys = VaultClientKey::all(['alias', 'owner_project', 'algorithm', 'is_active', 'rotated_at']);
if ($keys->isEmpty()) {
$this->info('📭 No hay claves registradas.');

View File

@ -0,0 +1,48 @@
<?php
namespace Koneko\VuexyAdmin\Console\Commands\Vault;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Vault\VaultKeyService;
class VaultKeyInfoCommand extends Command
{
protected $signature = 'vault:info {alias : Alias de la clave}
{--project= : Código del proyecto}
{--namespace= : Namespace (opcional)}
{--client= : ID de cliente (UUID o int)}';
protected $description = '📌 Muestra información detallada de una clave del vault.';
public function handle(): void
{
$alias = $this->argument('alias');
$project = $this->option('project') ?? config('settings.project.code');
$namespace = $this->option('namespace') ?? 'default';
$clientId = $this->option('client') ?? null;
$vault = VaultKeyService::make()
->project($project)
->namespace($namespace)
->useClient($clientId);
$key = $vault->raw($alias);
if (!$key) {
$this->error("❌ Clave '{$alias}' no encontrada.");
return;
}
$this->info("🔐 Información de clave:");
$this->line("Alias: {$key->alias}");
$this->line("Proyecto: {$key->project_code}");
$this->line("Cliente ID: {$key->client_id}");
$this->line("Namespace: {$key->namespace}");
$this->line("Activo: " . ($key->is_active ? 'Sí' : 'No'));
$this->line("Algoritmo: {$key->algorithm}");
$this->line("Sensitiva: " . ($key->is_sensitive ? 'Sí' : 'No'));
$this->line("Rotaciones: {$key->rotation_count}");
$this->line("Última rotación: " . ($key->rotated_at ?? 'Nunca'));
$this->line("Creada en: {$key->created_at}");
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace Koneko\VuexyAdmin\Console\Commands\Vault;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Vault\VaultKeyService;
class VaultKeyRotateCommand extends Command
{
protected $signature = 'vault:rotate {alias : Alias de la clave a rotar}
{--project= : Código del proyecto}
{--namespace= : Namespace (opcional)}
{--client= : ID de cliente (UUID o int)}
{--length=32 : Longitud de la nueva clave}';
protected $description = '🔄 Rota una clave del vault generando un nuevo valor aleatorio.';
public function handle(): void
{
$alias = $this->argument('alias');
$project = $this->option('project') ?? config('settings.project.code');
$namespace = $this->option('namespace') ?? 'default';
$clientId = $this->option('client') ?? null;
$length = (int) $this->option('length');
$newKey = VaultKeyService::generateRandomKey($length);
$success = VaultKeyService::make()
->project($project)
->namespace($namespace)
->useClient($clientId)
->rotate($alias, $newKey);
if ($success) {
$this->info("✅ Clave '{$alias}' rotada exitosamente.");
} else {
$this->error("❌ No se encontró la clave '{$alias}'.");
}
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands\Vault;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'vault:reset', description: 'Elimina la tabla de claves del vault si el entorno lo permite.')]
class VaultResetCommand extends Command
{
protected $signature = 'vault:reset {--force : Ejecutar sin confirmación}';
//protected $description = 'Elimina la tabla de claves del vault si el entorno lo permite.';
public function handle(): void
{
// Seguridad: Confirmar que está habilitado
if (!Config::get('settings.security.key_vault.reset_enabled', false)) {
$this->warn('❌ Vault reset está deshabilitado por configuración. Revisa KONEKO_KEY_VAULT_RESET_ENABLED.');
return;
}
// Confirmación interactiva
if (!$this->option('force') && !$this->confirm('¿Seguro que deseas eliminar todas las claves del vault?')) {
$this->info('⛔ Operación cancelada.');
return;
}
$connection = Config::get('settings.security.key_vault.drivers.database.connection', 'vault');
$table = Config::get('settings.security.key_vault.drivers.database.table', 'vault_keys');
if (!Schema::connection($connection)->hasTable($table)) {
$this->warn("⚠️ La tabla `{$table}` no existe en la conexión [{$connection}].");
return;
}
Schema::connection($connection)->dropIfExists($table);
$this->info("✅ Tabla `{$table}` eliminada correctamente de la conexión [{$connection}].");
}
}

View File

@ -1,89 +0,0 @@
<?php
declare(strict_types=1);
namespace Koneko\VuexyAdmin\Console\Commands;
use Illuminate\Console\Command;
use Koneko\VuexyAdmin\Application\Bootstrap\KonekoModuleRegistry;
use Koneko\VuexyAdmin\Application\System\RbacManagerService;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'vuexy:rbac')]
class __VuexyRbacCommand extends Command
{
protected $signature = 'vuexy:rbac
{--sync : Importa permisos y roles desde archivos}
{--export : Exporta permisos y roles a archivos}
{--publish : Publica los archivos de configuración de roles y permisos}
{--module= : Especifica un módulo a procesar}
{--roles-only : Limita la operación solo a roles}
{--permissions-only : Limita la operación solo a permisos}
{--overwrite : Sobrescribe roles existentes (solo en sync)}
{--force : Fuerza publicación aunque ya existan los archivos}';
protected $description = '🔐 Sincroniza, exporta o publica los roles y permisos RBAC de Vuexy por módulo';
public function handle()
{
$moduleName = $this->option('module');
$sync = $this->option('sync');
$export = $this->option('export');
$publish = $this->option('publish');
$rolesOnly = $this->option('roles-only');
$permissionsOnly = $this->option('permissions-only');
$overwrite = $this->option('overwrite');
$force = $this->option('force');
if (!($sync || $export || $publish)) {
$this->error('Debes especificar al menos una opción: --sync, --export o --publish');
return 1;
}
$modules = $moduleName
? [KonekoModuleRegistry::get($moduleName)]
: KonekoModuleRegistry::enabled();
foreach ($modules as $module) {
if (!$module) {
$this->warn("⚠️ Módulo no encontrado: {$moduleName}");
continue;
}
$this->info("🎯 Procesando módulo: {$module->name}");
if ($sync) {
if (!$rolesOnly) {
$this->line(" 📥 Importando permisos...");
RbacManagerService::importPermissions($module);
}
if (!$permissionsOnly) {
$this->line(" 🔐 Importando roles...");
RbacManagerService::importRoles($module, $overwrite);
}
}
if ($export) {
if (!$rolesOnly) {
$this->line(" 📤 Exportando permisos...");
RbacManagerService::exportPermissions($module);
}
if (!$permissionsOnly) {
$this->line(" 🔐 Exportando roles...");
RbacManagerService::exportRoles($module);
}
}
if ($publish) {
// Puedes definir aquí lógica futura si decides generar archivos
// en `base_path('database/data/vuexy-x/rbac.json')` en lugar de sobrescribir los originales
$this->comment("🚧 Publish: aún no implementado. Usa export + config para lograrlo.");
}
}
$this->info('✅ Comando RBAC finalizado.');
return 0;
}
}