#!/bin/bash # ------------------------------------------------------------------ # [Author] Cortana Rosero One # [Title] versadm_token.sh - Administrador de Tokens para Control de Versiones # [Generated] Created by Claude Code (claude-3-7-sonnet-20250219) # # AGPL License # Modified date: 14/03/2025 # ------------------------------------------------------------------ # Directorios base SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BASE_DIR="$(dirname "$SCRIPT_DIR")" CONFIG_DIR="$SCRIPT_DIR/config" LIB_DIR="$SCRIPT_DIR/lib" MSG_DIR="$SCRIPT_DIR/msg" DEVELOPER_DIR="$HOME/.developer" # Cargar libraries source "$LIB_DIR/base.lib" source "$LIB_DIR/console.lib" source "$MSG_DIR/head.es" # Variables globales title="ADMINISTRADOR DE TOKENS PARA CONTROL DE VERSIONES" apps_title="Gestión de Tokens Git" SOPS_CONFIG_DIR="$DEVELOPER_DIR" # Opciones de sistemas de control de versiones VCS_TYPES=("GitHub" "GitLab" "Forgejo/Codeberg") VCS_COMMANDS=("gh" "glab" "berg") VCS_TOKENS=("github.sops.yaml" "gitlab.sops.yaml" "forgejo.sops.yaml") VCS_INSTALLERS=("ghcli_install.sh" "glcli_install.sh" "fjcli_install.sh") VCS_TOKEN_URLS=("https://github.com/settings/tokens" "https://gitlab.com/-/profile/personal_access_tokens" "Sección Aplicaciones en su perfil de usuario") # Verificar que SOPS esté instalado check_sops() { if ! command -v sops &> /dev/null; then dialog --backtitle "${title}" --title "${head_error}" --msgbox "El programa 'sops' no está instalado. Es necesario para encriptar tokens." 7 60 exit 1 fi } # Verificar que dialog esté instalado check_dialog() { if ! command -v dialog &> /dev/null; then echo -e "${head_001}" exit 1 fi } # Crear directorio para tokens si no existe check_token_directory() { if [ ! -d "$SOPS_CONFIG_DIR" ]; then mkdir -p "$SOPS_CONFIG_DIR" fi # Asegurar que el directorio tenga permisos adecuados chmod 700 "$SOPS_CONFIG_DIR" } # Mostrar ayuda detallada sobre tokens show_token_help() { local vcs_index=$1 local vcs_name=${VCS_TYPES[$vcs_index]} local help_text="" case "$vcs_index" in 0) # GitHub help_text="AYUDA PARA TOKENS DE GITHUB\n\n" help_text+="Para generar un token personal en GitHub:\n\n" help_text+="1. Inicie sesión en GitHub y vaya a Configuración -> Configuración de desarrollador -> Tokens de acceso personal\n" help_text+=" URL: ${VCS_TOKEN_URLS[$vcs_index]}\n\n" help_text+="2. Haga clic en 'Generar nuevo token'\n\n" help_text+="3. Proporcione una nota descriptiva para el token\n\n" help_text+="4. Seleccione los permisos necesarios:\n" help_text+=" - Para uso general: repo, workflow, read:org\n" help_text+=" - Para acceso más limitado, solo seleccione lo que necesite\n\n" help_text+="5. Haga clic en 'Generar token'\n\n" help_text+="6. Copie el token inmediatamente (solo se muestra una vez)" ;; 1) # GitLab help_text="AYUDA PARA TOKENS DE GITLAB\n\n" help_text+="Para generar un token personal en GitLab:\n\n" help_text+="1. Inicie sesión en GitLab y vaya a Preferencias -> Tokens de acceso\n" help_text+=" URL: ${VCS_TOKEN_URLS[$vcs_index]}\n\n" help_text+="2. Proporcione un nombre para el token\n\n" help_text+="3. Opcionalmente, establezca una fecha de vencimiento\n\n" help_text+="4. Seleccione los permisos necesarios:\n" help_text+=" - Para uso general: api, read_repository, write_repository\n" help_text+=" - Para acceso más limitado, solo seleccione lo que necesite\n\n" help_text+="5. Haga clic en 'Crear token de acceso personal'\n\n" help_text+="6. Copie el token inmediatamente (solo se muestra una vez)" ;; 2) # Forgejo/Codeberg help_text="AYUDA PARA TOKENS DE FORGEJO/CODEBERG\n\n" help_text+="Para generar un token personal en Forgejo o Codeberg:\n\n" help_text+="1. Inicie sesión en su instancia de Forgejo o en Codeberg\n\n" help_text+="2. Vaya a Configuración -> Aplicaciones\n\n" help_text+="3. En la sección 'Generar nuevo token', proporcione un nombre\n\n" help_text+="4. Seleccione los permisos necesarios (alcances):\n" help_text+=" - Para uso general: repo, repo:status\n" help_text+=" - Para acceso más limitado, solo seleccione lo que necesite\n\n" help_text+="5. Haga clic en 'Generar token'\n\n" help_text+="6. Copie el token inmediatamente (solo se muestra una vez)" ;; esac dialog --backtitle "${title}" --title "Ayuda sobre tokens de $vcs_name" --msgbox "$help_text" 22 75 } # Diálogo para solicitar token utilizando console.lib request_token_with_help() { local vcs_index=$1 local vcs_name=${VCS_TYPES[$vcs_index]} local prompt="Ingrese su token personal de $vcs_name:" local helper="Puede generar un nuevo token en: ${VCS_TOKEN_URLS[$vcs_index]}" local token="" local continue_loop=true while $continue_loop; do # Mostrar diálogo de contraseña usando console.lib dialog_input_pass "$prompt" "$helper" # Verificar resultado if [ $codex -ne 0 ]; then # Usuario canceló return 1 fi token="$value" # Validar el token if [ -z "$token" ]; then dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "${head_error}" --msgbox "El token no puede estar vacío. Por favor ingrese un token válido." 7 60 continue fi if [ ${#token} -lt 20 ]; then dialog_yesno "El token parece ser demasiado corto. Verifique que haya copiado el token completo.\n\n¿Desea continuar de todas formas?" 10 70 if [ $? -ne 0 ]; then continue fi fi # Mostrar opción de ayuda dialog_yesno "¿Necesita ayuda para obtener un token de $vcs_name?\n\nSeleccione 'Sí' para ver instrucciones detalladas o 'No' para continuar." 10 70 if [ $? -eq 0 ]; then show_token_help "$vcs_index" # Preguntar si desea intentar nuevamente dialog_yesno "¿Desea ingresar un token diferente?" 7 60 if [ $? -eq 0 ]; then continue fi fi # Token válido, salir del bucle continue_loop=false done # Devolver el token echo "$token" return 0 } # Verificar e instalar CLI si es necesario check_and_install_cli() { local vcs_index=$1 local command=${VCS_COMMANDS[$vcs_index]} local vcs_name=${VCS_TYPES[$vcs_index]} local installer="$SCRIPT_DIR/${VCS_INSTALLERS[$vcs_index]}" if ! command -v "$command" &> /dev/null; then dialog_yesno "El CLI de $vcs_name ($command) no está instalado.\n¿Desea instalarlo ahora?" 8 60 if [ $? -eq 0 ]; then if [ -f "$installer" ]; then clear echo "Instalando CLI de $vcs_name..." bash "$installer" local result=$? echo "Presione Enter para continuar..." read return $result else dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "${head_error}" --msgbox "No se encontró el script de instalación para $vcs_name:\n$installer" 8 70 return 1 fi else dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "${head_info}" \ --msgbox "El CLI es necesario para interactuar completamente con $vcs_name.\nEl token se guardará de todas formas, pero no podrá verificar la conexión automáticamente." 9 70 return 0 fi fi return 0 } # Guardar token cifrado con SOPS save_encrypted_token() { local vcs_index=$1 local token=$2 local vcs_name=${VCS_TYPES[$vcs_index]} local token_file="$SOPS_CONFIG_DIR/${VCS_TOKENS[$vcs_index]}" # Crear archivo YAML y encriptarlo con SOPS echo "creating_token: \"$token\"" > "/tmp/token_temp.yaml" sops --encrypt "/tmp/token_temp.yaml" > "$token_file" 2>/dev/null # Eliminar archivo temporal rm -f "/tmp/token_temp.yaml" # Verificar resultado de la encriptación if [ $? -eq 0 ]; then # Establecer permisos adecuados chmod 600 "$token_file" dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "Encriptación Exitosa" \ --msgbox "El token de $vcs_name ha sido encriptado exitosamente en:\n$token_file" 8 70 return 0 else dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "${head_error}" \ --msgbox "Falló la encriptación del token de $vcs_name." 7 50 return 1 fi } # Probar conexión con el servicio test_connection() { local vcs_index=$1 local vcs_name=${VCS_TYPES[$vcs_index]} local command=${VCS_COMMANDS[$vcs_index]} local token_file="$SOPS_CONFIG_DIR/${VCS_TOKENS[$vcs_index]}" local connection_status="" local connection_message="" # Usar dialog en modo compatible con console.lib dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "Prueba de conexión" --infobox "Probando conexión con $vcs_name..." 5 60 case "$vcs_index" in 0) # GitHub if command -v $command &> /dev/null; then connection_status=$(gh api user 2>&1) if [ $? -eq 0 ]; then local username=$(echo "$connection_status" | grep '"login"' | cut -d'"' -f4) connection_message="Conexión exitosa con GitHub.\nUsuario autenticado: $username" else connection_message="Error al conectar con GitHub:\n$connection_status" fi else connection_message="CLI de GitHub no está instalado." fi ;; 1) # GitLab if command -v $command &> /dev/null; then connection_status=$(glab api user 2>&1) if [ $? -eq 0 ]; then local username=$(echo "$connection_status" | grep '"username"' | cut -d'"' -f4) connection_message="Conexión exitosa con GitLab.\nUsuario autenticado: $username" else connection_message="Error al conectar con GitLab:\n$connection_status" fi else connection_message="CLI de GitLab no está instalado." fi ;; 2) # Forgejo/Codeberg if command -v $command &> /dev/null; then # Intentar usar el token de SOPS para la autenticación if [ -f "$token_file" ]; then local token=$(sops --decrypt "$token_file" 2>/dev/null | grep 'creating_token' | cut -d'"' -f2) if [ -n "$token" ]; then connection_status=$(curl -s -H "Authorization: token $token" "https://codeberg.org/api/v1/user" 2>&1) if echo "$connection_status" | grep -q '"username"'; then local username=$(echo "$connection_status" | grep '"username"' | cut -d'"' -f4) connection_message="Conexión exitosa con Forgejo/Codeberg.\nUsuario autenticado: $username" else connection_message="Error al conectar con Forgejo/Codeberg:\n$connection_status" fi else connection_message="No se pudo extraer el token del archivo cifrado." fi else connection_message="No se encontró un token configurado para Forgejo/Codeberg." fi else connection_message="CLI de Forgejo/Codeberg no está instalado." fi ;; esac # Usar dialog en modo compatible con console.lib dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "Resultado de la prueba" --msgbox "$connection_message" 15 70 } # Función principal para gestionar tokens manage_vcs_token() { # Construir opciones para el menú - solo nombres de plataformas local menu_options="" for i in "${!VCS_TYPES[@]}"; do menu_options+="$((i+1)) \"${VCS_TYPES[$i]}\" " done # Mostrar menú de selección dialog_input_menu "Seleccione la plataforma de control de versiones:" \ "Seleccione la plataforma para la cual desea gestionar el token" \ "$menu_options" \ 15 70 if [ $codex -ne 0 ]; then return 1 fi # Calcular índice (0-based) a partir de la selección (1-based) local selection=$((value-1)) # Verificar índice válido if [ $selection -lt 0 ] || [ $selection -ge ${#VCS_TYPES[@]} ]; then dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "${head_error}" --msgbox "Selección inválida." 7 50 return 1 fi local vcs_name=${VCS_TYPES[$selection]} local token_file="$SOPS_CONFIG_DIR/${VCS_TOKENS[$selection]}" # Mostrar menú de acciones local action_menu="1 \"Configurar token\" " if [ -f "$token_file" ]; then action_menu+="2 \"Probar conexión\" " action_menu+="3 \"Eliminar token\" " fi dialog_input_menu "Acciones para $vcs_name:" \ "Seleccione la acción que desea realizar" \ "$action_menu" \ 12 70 if [ $codex -ne 0 ]; then return 1 fi case "$value" in 1) # Configurar token # Verificar si ya existe un token if [ -f "$token_file" ]; then dialog_yesno "Ya existe un token configurado para $vcs_name.\n¿Desea reemplazarlo?" 8 60 if [ $? -ne 0 ]; then return 0 fi fi # Verificar e instalar CLI si es necesario check_and_install_cli "$selection" # Solicitar token local token=$(request_token_with_help "$selection") if [ $? -ne 0 ]; then return 1 fi # Guardar token save_encrypted_token "$selection" "$token" # Preguntar si desea probar la conexión if command -v "${VCS_COMMANDS[$selection]}" &> /dev/null; then dialog_yesno "¿Desea probar la conexión con $vcs_name usando el token configurado?" 8 60 if [ $? -eq 0 ]; then test_connection "$selection" fi fi ;; 2) # Probar conexión test_connection "$selection" ;; 3) # Eliminar token dialog_yesno "¿Está seguro de que desea eliminar el token de $vcs_name?\nEsta acción no se puede deshacer." 8 60 if [ $? -eq 0 ]; then rm -f "$token_file" dialog --keep-window --begin ${CX} ${CY} --backtitle "${title}" --title "Token eliminado" --msgbox "El token de $vcs_name ha sido eliminado." 7 50 fi ;; esac return 0 } # Función principal main() { # Verificar requisitos check_dialog check_sops check_token_directory while true; do # Ejecutar la función principal manage_vcs_token # Preguntar si desea continuar o salir dialog_yesno "¿Desea volver al menú principal?" 7 60 if [ $? -ne 0 ]; then break fi done } # Ejecutar función principal main exit 0