diff --git a/.claude/hooks/monitor-gitea-action.sh b/.claude/hooks/monitor-gitea-action.sh
index 7781def..abb5bbb 100755
--- a/.claude/hooks/monitor-gitea-action.sh
+++ b/.claude/hooks/monitor-gitea-action.sh
@@ -8,7 +8,7 @@ set -euo pipefail
# Configuración
GITEA_URL="https://gitea.nucleoriofrio.com"
OWNER="nucleo000"
-REPO="plantillaNuxtAuthentikProxy"
+REPO="perfil"
# Intentar cargar el token desde el entorno o desde ~/.bashrc
GITEA_TOKEN="${GITEA_TOKEN:-}"
diff --git a/.env.example b/.env.example
index 3f3b307..091d454 100644
--- a/.env.example
+++ b/.env.example
@@ -54,3 +54,19 @@ REGISTRY_PASSWORD=mi-password-secreto
# - X-authentik-name: nombre completo
# - X-authentik-groups: grupos del usuario (separados por |)
# - X-authentik-uid: ID único del usuario
+
+# URL pública de Authentik (para redirecciones de login/logout)
+NUXT_PUBLIC_AUTHENTIK_URL=https://authentik.nucleoriofrio.com
+
+# ===========================================
+# AUTHENTIK API (para edición de perfil)
+# ===========================================
+# Token de API de Authentik (SECRETO)
+# Para crear un token:
+# 1. Ve a Authentik Admin → Directory → Tokens & App passwords
+# 2. Crea un nuevo token con el usuario que tendrá permisos para editar usuarios
+# 3. Guarda el token de forma segura
+NUXT_AUTHENTIK_API_TOKEN=tu-token-de-api-aqui
+
+# URL de la API de Authentik (usualmente la misma que NUXT_PUBLIC_AUTHENTIK_URL)
+NUXT_AUTHENTIK_API_URL=https://authentik.nucleoriofrio.com
diff --git a/CONFIGURACION_GITEA.md b/CONFIGURACION_GITEA.md
new file mode 100644
index 0000000..b279a6b
--- /dev/null
+++ b/CONFIGURACION_GITEA.md
@@ -0,0 +1,56 @@
+# Configuración de Variables en Gitea
+
+Para completar la configuración del repositorio, necesitas agregar las siguientes variables en Gitea:
+
+## Cómo configurar
+
+1. Ve a: https://gitea.nucleoriofrio.com/nucleo000/perfil/settings/actions/variables
+2. Para cada variable, haz click en "Add variable"
+3. Ingresa el nombre y valor exactamente como se indica abajo
+
+## Variables a configurar
+
+### REGISTRY_URL
+- **Nombre**: `REGISTRY_URL`
+- **Valor**: `gitea.nucleoriofrio.com`
+- **Descripción**: URL del registro Docker
+
+### APP_NAME
+- **Nombre**: `APP_NAME`
+- **Valor**: `perfil`
+- **Descripción**: Nombre de la aplicación
+
+### APP_DOMAIN
+- **Nombre**: `APP_DOMAIN`
+- **Valor**: `inicio.nucleoriofrio.com`
+- **Descripción**: Dominio donde se desplegará la aplicación
+
+### NUXT_PUBLIC_APP_URL
+- **Nombre**: `NUXT_PUBLIC_APP_URL`
+- **Valor**: `https://inicio.nucleoriofrio.com`
+- **Descripción**: URL pública de la aplicación
+
+### NUXT_PUBLIC_AUTHENTIK_URL
+- **Nombre**: `NUXT_PUBLIC_AUTHENTIK_URL`
+- **Valor**: `https://authentik.nucleoriofrio.com`
+- **Descripción**: URL pública de Authentik
+
+### NUXT_AUTHENTIK_API_URL
+- **Nombre**: `NUXT_AUTHENTIK_API_URL`
+- **Valor**: `https://authentik.nucleoriofrio.com`
+- **Descripción**: URL de la API de Authentik
+
+---
+
+## Secrets ya configurados ✅
+
+Los siguientes secrets ya fueron configurados automáticamente:
+
+- ✅ `REGISTRY_USERNAME`
+- ✅ `REGISTRY_PASSWORD`
+- ✅ `NUXT_AUTHENTIK_API_TOKEN`
+
+## Verificación
+
+Una vez configuradas todas las variables, puedes verificarlas en:
+https://gitea.nucleoriofrio.com/nucleo000/perfil/settings/actions/variables
diff --git a/nuxt4/app/app.vue b/nuxt4/app/app.vue
index e37e66a..b9922f5 100644
--- a/nuxt4/app/app.vue
+++ b/nuxt4/app/app.vue
@@ -26,6 +26,7 @@
+
diff --git a/nuxt4/app/components/auth/EditProfileButton.vue b/nuxt4/app/components/auth/EditProfileButton.vue
new file mode 100644
index 0000000..fb2c200
--- /dev/null
+++ b/nuxt4/app/components/auth/EditProfileButton.vue
@@ -0,0 +1,156 @@
+
+
+ Editar Perfil
+
+
+
+
+
+
+
Editar Perfil
+
+
+
+
+
+
+
+
+
+ Cancelar
+
+
+ Guardar Cambios
+
+
+
+
+
+
+
+
diff --git a/nuxt4/app/server/api/authentik/user.get.ts b/nuxt4/app/server/api/authentik/user.get.ts
new file mode 100644
index 0000000..0e5ec69
--- /dev/null
+++ b/nuxt4/app/server/api/authentik/user.get.ts
@@ -0,0 +1,57 @@
+/**
+ * Obtiene la información del usuario actual desde Authentik
+ */
+export default defineEventHandler(async (event) => {
+ const config = useRuntimeConfig()
+ const headers = getRequestHeaders(event)
+
+ // Obtener el username desde los headers de Authentik
+ const username = headers['x-authentik-username']
+
+ if (!username) {
+ throw createError({
+ statusCode: 401,
+ message: 'Usuario no autenticado'
+ })
+ }
+
+ // Obtener la URL y token de Authentik desde variables de entorno
+ const authentikUrl = config.authentikApiUrl || config.public.authentikUrl
+ const authentikToken = config.authentikApiToken
+
+ if (!authentikToken) {
+ throw createError({
+ statusCode: 500,
+ message: 'Token de Authentik no configurado'
+ })
+ }
+
+ try {
+ // Consultar la API de Authentik para obtener información detallada del usuario
+ const response = await $fetch(`${authentikUrl}/api/v3/core/users/?username=${username}`, {
+ headers: {
+ 'Authorization': `Bearer ${authentikToken}`,
+ 'Content-Type': 'application/json'
+ }
+ })
+
+ // La API devuelve un array de resultados
+ const users = response as any
+
+ if (!users.results || users.results.length === 0) {
+ throw createError({
+ statusCode: 404,
+ message: 'Usuario no encontrado'
+ })
+ }
+
+ // Devolver el primer resultado (debería ser único por username)
+ return users.results[0]
+ } catch (error: any) {
+ console.error('Error al obtener usuario de Authentik:', error)
+ throw createError({
+ statusCode: error.statusCode || 500,
+ message: error.message || 'Error al obtener información del usuario'
+ })
+ }
+})
diff --git a/nuxt4/app/server/api/authentik/user.patch.ts b/nuxt4/app/server/api/authentik/user.patch.ts
new file mode 100644
index 0000000..dd4b627
--- /dev/null
+++ b/nuxt4/app/server/api/authentik/user.patch.ts
@@ -0,0 +1,74 @@
+/**
+ * Actualiza la información del usuario en Authentik
+ */
+export default defineEventHandler(async (event) => {
+ const config = useRuntimeConfig()
+ const headers = getRequestHeaders(event)
+
+ // Obtener el username desde los headers de Authentik
+ const username = headers['x-authentik-username']
+
+ if (!username) {
+ throw createError({
+ statusCode: 401,
+ message: 'Usuario no autenticado'
+ })
+ }
+
+ // Obtener la URL y token de Authentik desde variables de entorno
+ const authentikUrl = config.authentikApiUrl || config.public.authentikUrl
+ const authentikToken = config.authentikApiToken
+
+ if (!authentikToken) {
+ throw createError({
+ statusCode: 500,
+ message: 'Token de Authentik no configurado'
+ })
+ }
+
+ // Leer el body de la petición
+ const body = await readBody(event)
+
+ try {
+ // Primero, obtener el ID del usuario
+ const usersResponse = await $fetch(`${authentikUrl}/api/v3/core/users/?username=${username}`, {
+ headers: {
+ 'Authorization': `Bearer ${authentikToken}`,
+ 'Content-Type': 'application/json'
+ }
+ })
+
+ const users = usersResponse as any
+
+ if (!users.results || users.results.length === 0) {
+ throw createError({
+ statusCode: 404,
+ message: 'Usuario no encontrado'
+ })
+ }
+
+ const userId = users.results[0].pk
+
+ // Actualizar el usuario
+ const updateResponse = await $fetch(`${authentikUrl}/api/v3/core/users/${userId}/`, {
+ method: 'PATCH',
+ headers: {
+ 'Authorization': `Bearer ${authentikToken}`,
+ 'Content-Type': 'application/json'
+ },
+ body: {
+ name: body.name,
+ // Otros campos que se puedan actualizar
+ ...(body.email && { email: body.email })
+ }
+ })
+
+ return updateResponse
+ } catch (error: any) {
+ console.error('Error al actualizar usuario en Authentik:', error)
+ throw createError({
+ statusCode: error.statusCode || 500,
+ message: error.message || 'Error al actualizar información del usuario'
+ })
+ }
+})
diff --git a/nuxt4/nuxt.config.ts b/nuxt4/nuxt.config.ts
index a35fc79..c20a2ce 100644
--- a/nuxt4/nuxt.config.ts
+++ b/nuxt4/nuxt.config.ts
@@ -15,6 +15,11 @@ export default defineNuxtConfig({
css: ['~/assets/css/main.css'],
runtimeConfig: {
+ // Variables privadas del servidor (no expuestas al cliente)
+ authentikApiToken: process.env.NUXT_AUTHENTIK_API_TOKEN || '',
+ authentikApiUrl: process.env.NUXT_AUTHENTIK_API_URL || 'https://authentik.nucleoriofrio.com',
+
+ // Variables públicas (expuestas al cliente)
public: {
authentikUrl: process.env.NUXT_PUBLIC_AUTHENTIK_URL || 'https://authentik.nucleoriofrio.com'
}