From b42756277ae12ac8b12029e782f83b7038f51309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Domingo=20Agust=C3=AD?= Date: Tue, 22 Sep 2026 22:05:49 +0200 Subject: [PATCH] feat(frontend): opciones de LUKS y snapshots en el formulario + CI build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Añade toggles de cifrado LUKS2 y snapshots btrfs en HomePage. - Permite elegir método keyfile/passphrase para LUKS. - Actualiza tipos InstallRequest con encryption y snapshots. - Test verifica que el POST incluye encryption/snapshots por defecto. - Nuevo job build-frontend en .github/workflows/ci.yml. --- .github/workflows/ci.yml | 19 +++++ portal/frontend/src/pages/HomePage.test.tsx | 7 ++ portal/frontend/src/pages/HomePage.tsx | 78 ++++++++++++++++++++- portal/frontend/src/types.ts | 7 ++ 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6792d22..632473a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,3 +100,22 @@ jobs: - name: Run frontend tests run: cd portal/frontend && npm test + + build-frontend: + runs-on: ubuntu-latest + needs: validate + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: portal/frontend/package-lock.json + + - name: Install frontend dependencies + run: cd portal/frontend && npm ci + + - name: Build frontend for production + run: make build-frontend diff --git a/portal/frontend/src/pages/HomePage.test.tsx b/portal/frontend/src/pages/HomePage.test.tsx index 758084e..28182b7 100644 --- a/portal/frontend/src/pages/HomePage.test.tsx +++ b/portal/frontend/src/pages/HomePage.test.tsx @@ -59,5 +59,12 @@ describe('HomePage', () => { expect(screen.getByText('URL de arranque iPXE')).toBeInTheDocument(); expect(screen.getByText(/boot\/tokentest/i)).toBeInTheDocument(); }); + + // Verifica que el POST incluye encryption y snapshots por defecto + const calls = (globalThis.fetch as any).mock.calls; + const postCall = calls.find((c: any[]) => c[1]?.method === 'POST'); + const body = JSON.parse(postCall[1].body); + expect(body.encryption).toEqual({ enabled: true, method: 'keyfile' }); + expect(body.snapshots).toEqual({ enabled: true }); }); }); diff --git a/portal/frontend/src/pages/HomePage.tsx b/portal/frontend/src/pages/HomePage.tsx index fd7aa3f..0aa1022 100644 --- a/portal/frontend/src/pages/HomePage.tsx +++ b/portal/frontend/src/pages/HomePage.tsx @@ -14,7 +14,7 @@ import { } from '@/components/ui/select'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; -import { CheckCircle, Copy, Server, Terminal, Wifi } from 'lucide-react'; +import { CheckCircle, Copy, Server, Terminal, Wifi, Shield, History } from 'lucide-react'; const statusColors: Record = { pending: 'bg-cyan-500/10 text-cyan-400 border-cyan-500/20', @@ -29,6 +29,9 @@ export function HomePage() { const [submitting, setSubmitting] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); + const [enableEncryption, setEnableEncryption] = useState(true); + const [encryptionMethod, setEncryptionMethod] = useState<'keyfile' | 'passphrase'>('keyfile'); + const [enableSnapshots, setEnableSnapshots] = useState(true); useEffect(() => { loadInstallations(); @@ -61,6 +64,13 @@ export function HomePage() { .filter(Boolean), }; + if (enableEncryption) { + body.encryption = { enabled: true, method: encryptionMethod }; + } + if (enableSnapshots) { + body.snapshots = { enabled: true }; + } + try { const data = await api.install(body); setResult(data); @@ -129,6 +139,72 @@ export function HomePage() { +
+

+ + Opciones avanzadas +

+ +
+ setEnableEncryption(e.target.checked)} + className="mt-1 h-4 w-4 rounded border-border bg-background text-cyan-400 focus:ring-cyan-400" + /> +
+ + {enableEncryption && ( + + )} +

+ {enableEncryption + ? encryptionMethod === 'keyfile' + ? 'Arranque zero-touch. Cambia la llave tras la instalación para mayor seguridad física.' + : 'El arranque pedirá la contraseña en cada reinicio. Rompe el despliegue desatendido.' + : 'Las particiones raíz y home se formatearán sin cifrado.'} +

+
+
+ +
+ setEnableSnapshots(e.target.checked)} + className="mt-1 h-4 w-4 rounded border-border bg-background text-cyan-400 focus:ring-cyan-400" + /> +
+ +

+ Instala snapper + snap-pac para snapshots pre/post actualización y rollback. +

+
+
+
+ diff --git a/portal/frontend/src/types.ts b/portal/frontend/src/types.ts index cf8c68b..0590201 100644 --- a/portal/frontend/src/types.ts +++ b/portal/frontend/src/types.ts @@ -16,6 +16,13 @@ export interface InstallRequest { username?: string; desktop?: string; packages?: string[]; + encryption?: { + enabled: boolean; + method?: 'keyfile' | 'passphrase'; + }; + snapshots?: { + enabled: boolean; + }; } export interface InstallResponse {