Updates to the TUI. Need to continue working on a unified input validation function.

This commit is contained in:
Raphaël Billet
2026-04-28 09:00:24 +02:00
parent baa6bdd28b
commit 72668492f5
+80 -135
View File
@@ -17,6 +17,45 @@ ssh_to_host() {
ssh -i "${EXTRA_FILES_PATH}/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" "${COMMAND}" ssh -i "${EXTRA_FILES_PATH}/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" "${COMMAND}"
} }
get_valid_input() {
local VAR_NAME="${1}"
local HEADER="${2}"
local PLACEHOLDER="${3}"
local REGEX="${4}"
local MANDATORY="${5:-false}"
local SENSITIVE="${6:-false}"
while true; do
local input
# --value pre-fills the input for easy editing
input=$(gum input --header "${HEADER}" --placeholder "${PLACEHOLDER}" --width 50)
# Handle empty input
if [[ -z "$input" ]]; then
if [[ "$is_mandatory" == true ]]; then
gum style --foreground "#ff0000" -- "✖ This field is mandatory."
continue
else
return_var=""
break
fi
fi
# Handle Regex Validation
if [[ -n "$regex" ]]; then
if [[ "$input" =~ $regex ]]; then
return_var="$input"
break
else
gum style --foreground "#ff0000" -- "✖ Invalid format. Please try again."
fi
else
return_var="$input"
break
fi
done
}
user_input() { user_input() {
local VAR_NAME="${1}" local VAR_NAME="${1}"
local HEADER="${2}" local HEADER="${2}"
@@ -428,92 +467,27 @@ services_selection() {
return 0 return 0
} }
users_and_groups() {
declare -A ACL_GROUPS
declare -A ACL_USERS
compute_acl_services() {
EXCLUDED_SERVICES=( "clamav" ) # Those are the services that don't have a web page or don't support SSO
local ALL_SERVICES=("${SELECTED_DNS_SERVICE[@]}" "${SELECTED_WEB_APPLICATIONS[@]}" "${SELECTED_SYSTEM_SERVICES[@]}")
for i in "${!ALL_SERVICES[@]}"; do
for excluded in "${EXCLUDED_SERVICES[@]}"; do
if [[ "${ALL_SERVICES[${i}]}" == "${excluded}" ]]; then
unset "ALL_SERVICES[${i}]"
#############################################################################
declare -A ACL_GROUPS
declare -A ACL_USERS
ACL_SERVICES=()
compute_acl_services() {
local all_services=("${SELECTED_DNS_SERVICE[@]}" "${SELECTED_WEB_APPLICATIONS[@]}" "${SELECTED_SYSTEM_SERVICES[@]}")
ACL_SERVICES=() # Reset to prevent duplicates on reload
for svc in "${all_services[@]}"; do
local excluded=false
for ex in "${EXCLUDED_ACL_SERVICES[@]}"; do
if [[ "$svc" == "$ex" ]]; then
excluded=true
break
fi fi
done done
if [[ "$excluded" == false ]]; then
ACL_SERVICES+=("$svc")
fi
done done
} }
# Upgraded to support default values for editing, and '--' for gum style
get_valid_input() {
local -n return_var=$1
local prompt_text=$2
local regex=$3
local is_mandatory=$4
local default_value=$5
while true; do
local val
# --value pre-fills the input for easy editing
val=$(gum input --prompt "$prompt_text: " --width 50 --value "$default_value")
# Handle empty input show_groups_table() {
if [[ -z "$val" ]]; then
if [[ "$is_mandatory" == true ]]; then
gum style --foreground "#ff0000" -- "✖ This field is mandatory."
continue
else
return_var=""
break
fi
fi
# Handle Regex Validation
if [[ -n "$regex" ]]; then
if [[ "$val" =~ $regex ]]; then
return_var="$val"
break
else
gum style --foreground "#ff0000" -- "✖ Invalid format. Please try again."
fi
else
return_var="$val"
break
fi
done
}
# ==========================================
# 4. GROUP MANAGEMENT
# ==========================================
show_groups_table() {
if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then
gum style --italic --foreground "#6272a4" -- "No groups configured." gum style --italic --foreground "#6272a4" -- "No groups configured."
return return
@@ -526,9 +500,9 @@ show_groups_table() {
done done
printf "%b" "$csv" | gum table printf "%b" "$csv" | gum table
} }
add_group() { add_group() {
if [[ ${#ACL_GROUPS[@]} -ge 10 ]]; then if [[ ${#ACL_GROUPS[@]} -ge 10 ]]; then
gum style --foreground "#ffb86c" -- "⚠ Maximum of 10 groups reached." gum style --foreground "#ffb86c" -- "⚠ Maximum of 10 groups reached."
sleep 2; return sleep 2; return
@@ -549,9 +523,9 @@ add_group() {
ACL_GROUPS["$group_name"]="$chosen_services" ACL_GROUPS["$group_name"]="$chosen_services"
gum style --foreground "#50fa7b" -- "✔ Group '$group_name' created." gum style --foreground "#50fa7b" -- "✔ Group '$group_name' created."
sleep 1 sleep 1
} }
edit_group() { edit_group() {
if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then return; fi if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then return; fi
local group_keys=("${!ACL_GROUPS[@]}") local group_keys=("${!ACL_GROUPS[@]}")
@@ -570,9 +544,9 @@ edit_group() {
ACL_GROUPS["$group_name"]="$chosen_services" ACL_GROUPS["$group_name"]="$chosen_services"
gum style --foreground "#50fa7b" -- "✔ Group '$group_name' updated." gum style --foreground "#50fa7b" -- "✔ Group '$group_name' updated."
sleep 1 sleep 1
} }
remove_group() { remove_group() {
if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then return; fi if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then return; fi
local group_keys=("${!ACL_GROUPS[@]}") local group_keys=("${!ACL_GROUPS[@]}")
@@ -591,9 +565,9 @@ remove_group() {
gum style --foreground "#50fa7b" -- "✔ Group deleted." gum style --foreground "#50fa7b" -- "✔ Group deleted."
sleep 1 sleep 1
fi fi
} }
manage_groups_menu() { manage_groups_menu() {
while true; do while true; do
clear clear
gum style --border double --margin "1" --padding "0 1" --border-foreground "#8be9fd" -- "Group Management (${#ACL_GROUPS[@]}/10)" gum style --border double --margin "1" --padding "0 1" --border-foreground "#8be9fd" -- "Group Management (${#ACL_GROUPS[@]}/10)"
@@ -607,13 +581,9 @@ manage_groups_menu() {
"Back"|"") break ;; "Back"|"") break ;;
esac esac
done done
} }
# ========================================== show_users_table() {
# 5. USER MANAGEMENT
# ==========================================
show_users_table() {
if [[ ${#ACL_USERS[@]} -eq 0 ]]; then if [[ ${#ACL_USERS[@]} -eq 0 ]]; then
gum style --italic --foreground "#6272a4" -- "No users configured." gum style --italic --foreground "#6272a4" -- "No users configured."
return return
@@ -621,14 +591,14 @@ show_users_table() {
local csv="Username,Name,Email,Health Alerts,ACL Type,ACL Value\n" local csv="Username,Name,Email,Health Alerts,ACL Type,ACL Value\n"
for u in "${!ACL_USERS[@]}"; do for u in "${!ACL_USERS[@]}"; do
IFS='|' read -r name email phone health type val <<< "${ACL_USERS[$u]}" IFS='|' read -r name email phone health type input <<< "${ACL_USERS[$u]}"
csv+="\"$u\",\"$name\",\"$email\",\"$health\",\"$type\",\"$val\"\n" csv+="\"$u\",\"$name\",\"$email\",\"$health\",\"$type\",\"$input\"\n"
done done
printf "%b" "$csv" | gum table printf "%b" "$csv" | gum table
} }
add_user() { add_user() {
if [[ ${#ACL_USERS[@]} -ge 20 ]]; then if [[ ${#ACL_USERS[@]} -ge 20 ]]; then
gum style --foreground "#ffb86c" -- "⚠ Maximum of 20 users reached." gum style --foreground "#ffb86c" -- "⚠ Maximum of 20 users reached."
sleep 2; return sleep 2; return
@@ -665,9 +635,9 @@ add_user() {
ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value" ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value"
gum style --foreground "#50fa7b" -- "✔ User '$username' created." gum style --foreground "#50fa7b" -- "✔ User '$username' created."
sleep 1 sleep 1
} }
edit_user() { edit_user() {
if [[ ${#ACL_USERS[@]} -eq 0 ]]; then return; fi if [[ ${#ACL_USERS[@]} -eq 0 ]]; then return; fi
local user_keys=("${!ACL_USERS[@]}") local user_keys=("${!ACL_USERS[@]}")
@@ -712,9 +682,9 @@ edit_user() {
ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value" ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value"
gum style --foreground "#50fa7b" -- "✔ User '$username' updated." gum style --foreground "#50fa7b" -- "✔ User '$username' updated."
sleep 1 sleep 1
} }
remove_user() { remove_user() {
if [[ ${#ACL_USERS[@]} -eq 0 ]]; then return; fi if [[ ${#ACL_USERS[@]} -eq 0 ]]; then return; fi
local user_keys=("${!ACL_USERS[@]}") local user_keys=("${!ACL_USERS[@]}")
@@ -733,9 +703,9 @@ remove_user() {
gum style --foreground "#50fa7b" -- "✔ User deleted." gum style --foreground "#50fa7b" -- "✔ User deleted."
sleep 1 sleep 1
fi fi
} }
manage_users_menu() { manage_users_menu() {
while true; do while true; do
clear clear
gum style --border double --margin "1" --padding "0 1" --border-foreground "#ff79c6" -- "User Management (${#ACL_USERS[@]}/20)" gum style --border double --margin "1" --padding "0 1" --border-foreground "#ff79c6" -- "User Management (${#ACL_USERS[@]}/20)"
@@ -749,13 +719,9 @@ manage_users_menu() {
"Back"|"") break ;; "Back"|"") break ;;
esac esac
done done
} }
# ========================================== setup_admin_user() {
# 6. SETUP & EXPORT
# ==========================================
setup_admin_user() {
if [[ -n "${ACL_USERS["admin"]}" ]]; then return; fi if [[ -n "${ACL_USERS["admin"]}" ]]; then return; fi
gum style --border rounded --padding "1 2" --margin "1" --border-foreground "#ff79c6" -- "Initial Setup: Administrator User" gum style --border rounded --padding "1 2" --margin "1" --border-foreground "#ff79c6" -- "Initial Setup: Administrator User"
@@ -768,9 +734,9 @@ setup_admin_user() {
ACL_USERS["admin"]="$name|$email|$phone|true|group|admin" ACL_USERS["admin"]="$name|$email|$phone|true|group|admin"
gum style --foreground "#50fa7b" -- "✔ Administrator configured." gum style --foreground "#50fa7b" -- "✔ Administrator configured."
sleep 1 sleep 1
} }
export_data() { export_data() {
clear clear
gum style --foreground "#50fa7b" --bold -- "--- Provisioning Data Payload ---" gum style --foreground "#50fa7b" --bold -- "--- Provisioning Data Payload ---"
echo "GROUPS:" echo "GROUPS:"
@@ -782,20 +748,19 @@ export_data() {
for user in "${!ACL_USERS[@]}"; do for user in "${!ACL_USERS[@]}"; do
echo " $user -> ${ACL_USERS[$user]}" echo " $user -> ${ACL_USERS[$user]}"
done done
} }
main_menu() {
compute_acl_services compute_acl_services
ACL_GROUPS["admin"]=$(printf "%s," "${ACL_SERVICES[@]}" | sed 's/,$//') ACL_GROUPS["admin"]=$(printf "%s," "${ACL_SERVICES[@]}" | sed 's/,$//')
setup_admin_user setup_admin_user
while true; do while true; do
clear clear
gum style --border double --margin "1" --padding "1 2" --border-foreground "#bd93f9" -- "Server Deployment - Access Management" gum style --border double --margin "1" --padding "1 2" --border-foreground "#bd93f9" -- "Numbus Deployment - Access Management"
gum style -- "Current state: ${#ACL_GROUPS[@]}/10 Groups | ${#ACL_USERS[@]}/20 Users" gum style -- "Current state: ${#ACL_GROUPS[@]}/10 Groups | ${#ACL_USERS[@]}/20 Users"
echo "" echo ""
local choice=$(gum choose "1. Manage Groups" "2. Manage Users" "3. Finish & Apply Configuration" "4. Exit without saving") local choice=$(gum choose "1. Manage Groups" "2. Manage Users" "3. Finish & Apply Configuration")
case "$choice" in case "$choice" in
"1. Manage Groups") manage_groups_menu ;; "1. Manage Groups") manage_groups_menu ;;
@@ -804,32 +769,10 @@ main_menu() {
export_data export_data
break break
;; ;;
"4. Exit without saving"|"")
echo "Aborting..."
exit 1
;;
esac esac
done done
} }
########################################################################""
disks_selection() { disks_selection() {
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 " gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "
⚠️ $(gum style --foreground 212 'WARNING:') You will choose the disks to install NixOS on. ⚠️ $(gum style --foreground 212 'WARNING:') You will choose the disks to install NixOS on.
@@ -1399,6 +1342,8 @@ EMAIL_REGEX='^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
PORT_REGEX='^[0-9]{1,5}$' PORT_REGEX='^[0-9]{1,5}$'
SSH_KEY_REGEX='^ssh-[a-z0-9]+ [A-Za-z0-9+/]+.*' SSH_KEY_REGEX='^ssh-[a-z0-9]+ [A-Za-z0-9+/]+.*'
PHONE_REGEX='^\+[1-9][0-9]{7,14}$' PHONE_REGEX='^\+[1-9][0-9]{7,14}$'
# --- DEFAULTS VARIABLES ---< # --- DEFAULTS VARIABLES ---<