Updates to the TUI. Need to continue working on a unified input validation function.
This commit is contained in:
@@ -17,6 +17,45 @@ ssh_to_host() {
|
||||
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() {
|
||||
local VAR_NAME="${1}"
|
||||
local HEADER="${2}"
|
||||
@@ -428,95 +467,30 @@ services_selection() {
|
||||
return 0
|
||||
}
|
||||
|
||||
users_and_groups() {
|
||||
|
||||
declare -A ACL_GROUPS
|
||||
declare -A ACL_USERS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############################################################################
|
||||
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
|
||||
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 svc in "${all_services[@]}"; do
|
||||
local excluded=false
|
||||
for ex in "${EXCLUDED_ACL_SERVICES[@]}"; do
|
||||
if [[ "$svc" == "$ex" ]]; then
|
||||
excluded=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$excluded" == false ]]; then
|
||||
ACL_SERVICES+=("$svc")
|
||||
for i in "${!ALL_SERVICES[@]}"; do
|
||||
for excluded in "${EXCLUDED_SERVICES[@]}"; do
|
||||
if [[ "${ALL_SERVICES[${i}]}" == "${excluded}" ]]; then
|
||||
unset "ALL_SERVICES[${i}]"
|
||||
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
|
||||
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() {
|
||||
show_groups_table() {
|
||||
if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then
|
||||
gum style --italic --foreground "#6272a4" -- "No groups configured."
|
||||
return
|
||||
gum style --italic --foreground "#6272a4" -- "No groups configured."
|
||||
return
|
||||
fi
|
||||
|
||||
# We use CSV format with quotes to handle comma-separated services correctly
|
||||
@@ -526,20 +500,20 @@ show_groups_table() {
|
||||
done
|
||||
|
||||
printf "%b" "$csv" | gum table
|
||||
}
|
||||
}
|
||||
|
||||
add_group() {
|
||||
add_group() {
|
||||
if [[ ${#ACL_GROUPS[@]} -ge 10 ]]; then
|
||||
gum style --foreground "#ffb86c" -- "⚠ Maximum of 10 groups reached."
|
||||
sleep 2; return
|
||||
gum style --foreground "#ffb86c" -- "⚠ Maximum of 10 groups reached."
|
||||
sleep 2; return
|
||||
fi
|
||||
|
||||
local group_name
|
||||
get_valid_input group_name "Group Name" "^[a-zA-Z0-9_-]+$" true ""
|
||||
|
||||
if [[ -n "${ACL_GROUPS[$group_name]}" ]]; then
|
||||
gum style --foreground "#ff0000" -- "✖ Group already exists."
|
||||
sleep 2; return
|
||||
gum style --foreground "#ff0000" -- "✖ Group already exists."
|
||||
sleep 2; return
|
||||
fi
|
||||
|
||||
gum style --foreground "#50fa7b" -- "Select services for $group_name (Space to select, Enter to confirm):"
|
||||
@@ -549,9 +523,9 @@ add_group() {
|
||||
ACL_GROUPS["$group_name"]="$chosen_services"
|
||||
gum style --foreground "#50fa7b" -- "✔ Group '$group_name' created."
|
||||
sleep 1
|
||||
}
|
||||
}
|
||||
|
||||
edit_group() {
|
||||
edit_group() {
|
||||
if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then return; fi
|
||||
|
||||
local group_keys=("${!ACL_GROUPS[@]}")
|
||||
@@ -570,9 +544,9 @@ edit_group() {
|
||||
ACL_GROUPS["$group_name"]="$chosen_services"
|
||||
gum style --foreground "#50fa7b" -- "✔ Group '$group_name' updated."
|
||||
sleep 1
|
||||
}
|
||||
}
|
||||
|
||||
remove_group() {
|
||||
remove_group() {
|
||||
if [[ ${#ACL_GROUPS[@]} -eq 0 ]]; then return; fi
|
||||
|
||||
local group_keys=("${!ACL_GROUPS[@]}")
|
||||
@@ -581,65 +555,61 @@ remove_group() {
|
||||
|
||||
if [[ -z "$group_name" ]]; then return; fi
|
||||
if [[ "$group_name" == "admin" ]]; then
|
||||
gum style --foreground "#ff0000" -- "✖ The admin group cannot be removed."
|
||||
sleep 2; return
|
||||
gum style --foreground "#ff0000" -- "✖ The admin group cannot be removed."
|
||||
sleep 2; return
|
||||
fi
|
||||
|
||||
gum style --foreground "#ff5555" --bold -- "Are you sure you want to delete '$group_name'?"
|
||||
if gum confirm; then
|
||||
unset ACL_GROUPS["$group_name"]
|
||||
gum style --foreground "#50fa7b" -- "✔ Group deleted."
|
||||
sleep 1
|
||||
unset ACL_GROUPS["$group_name"]
|
||||
gum style --foreground "#50fa7b" -- "✔ Group deleted."
|
||||
sleep 1
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
manage_groups_menu() {
|
||||
manage_groups_menu() {
|
||||
while true; do
|
||||
clear
|
||||
gum style --border double --margin "1" --padding "0 1" --border-foreground "#8be9fd" -- "Group Management (${#ACL_GROUPS[@]}/10)"
|
||||
show_groups_table
|
||||
|
||||
local action=$(gum choose "Add Group" "Edit Group" "Remove Group" "Back")
|
||||
case "$action" in
|
||||
"Add Group") add_group ;;
|
||||
"Edit Group") edit_group ;;
|
||||
"Remove Group") remove_group ;;
|
||||
"Back"|"") break ;;
|
||||
esac
|
||||
clear
|
||||
gum style --border double --margin "1" --padding "0 1" --border-foreground "#8be9fd" -- "Group Management (${#ACL_GROUPS[@]}/10)"
|
||||
show_groups_table
|
||||
|
||||
local action=$(gum choose "Add Group" "Edit Group" "Remove Group" "Back")
|
||||
case "$action" in
|
||||
"Add Group") add_group ;;
|
||||
"Edit Group") edit_group ;;
|
||||
"Remove Group") remove_group ;;
|
||||
"Back"|"") break ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
# ==========================================
|
||||
# 5. USER MANAGEMENT
|
||||
# ==========================================
|
||||
|
||||
show_users_table() {
|
||||
show_users_table() {
|
||||
if [[ ${#ACL_USERS[@]} -eq 0 ]]; then
|
||||
gum style --italic --foreground "#6272a4" -- "No users configured."
|
||||
return
|
||||
gum style --italic --foreground "#6272a4" -- "No users configured."
|
||||
return
|
||||
fi
|
||||
|
||||
local csv="Username,Name,Email,Health Alerts,ACL Type,ACL Value\n"
|
||||
for u in "${!ACL_USERS[@]}"; do
|
||||
IFS='|' read -r name email phone health type val <<< "${ACL_USERS[$u]}"
|
||||
csv+="\"$u\",\"$name\",\"$email\",\"$health\",\"$type\",\"$val\"\n"
|
||||
IFS='|' read -r name email phone health type input <<< "${ACL_USERS[$u]}"
|
||||
csv+="\"$u\",\"$name\",\"$email\",\"$health\",\"$type\",\"$input\"\n"
|
||||
done
|
||||
|
||||
printf "%b" "$csv" | gum table
|
||||
}
|
||||
}
|
||||
|
||||
add_user() {
|
||||
add_user() {
|
||||
if [[ ${#ACL_USERS[@]} -ge 20 ]]; then
|
||||
gum style --foreground "#ffb86c" -- "⚠ Maximum of 20 users reached."
|
||||
sleep 2; return
|
||||
gum style --foreground "#ffb86c" -- "⚠ Maximum of 20 users reached."
|
||||
sleep 2; return
|
||||
fi
|
||||
|
||||
local name username email phone health_alert acl_type acl_value
|
||||
|
||||
get_valid_input username "Username" "^[a-z0-9_-]+$" true ""
|
||||
if [[ -n "${ACL_USERS[$username]}" ]]; then
|
||||
gum style --foreground "#ff0000" -- "✖ Username already exists."
|
||||
sleep 2; return
|
||||
gum style --foreground "#ff0000" -- "✖ Username already exists."
|
||||
sleep 2; return
|
||||
fi
|
||||
|
||||
get_valid_input name "Full Name" "" true ""
|
||||
@@ -653,21 +623,21 @@ add_user() {
|
||||
acl_type=$(gum choose "Assign to Group" "Manual Service Selection")
|
||||
|
||||
if [[ "$acl_type" == "Assign to Group" ]]; then
|
||||
acl_type="group"
|
||||
local group_keys=("${!ACL_GROUPS[@]}")
|
||||
acl_value=$(gum choose "${group_keys[@]}")
|
||||
acl_type="group"
|
||||
local group_keys=("${!ACL_GROUPS[@]}")
|
||||
acl_value=$(gum choose "${group_keys[@]}")
|
||||
else
|
||||
acl_type="manual"
|
||||
gum style --foreground "#50fa7b" -- "Select services for $username:"
|
||||
acl_value=$(gum choose --no-limit "${ACL_SERVICES[@]}" | paste -sd "," -)
|
||||
acl_type="manual"
|
||||
gum style --foreground "#50fa7b" -- "Select services for $username:"
|
||||
acl_value=$(gum choose --no-limit "${ACL_SERVICES[@]}" | paste -sd "," -)
|
||||
fi
|
||||
|
||||
ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value"
|
||||
gum style --foreground "#50fa7b" -- "✔ User '$username' created."
|
||||
sleep 1
|
||||
}
|
||||
}
|
||||
|
||||
edit_user() {
|
||||
edit_user() {
|
||||
if [[ ${#ACL_USERS[@]} -eq 0 ]]; then return; fi
|
||||
|
||||
local user_keys=("${!ACL_USERS[@]}")
|
||||
@@ -686,35 +656,35 @@ edit_user() {
|
||||
get_valid_input phone "Phone Number" "$PHONE_REGEX" false "$curr_phone"
|
||||
|
||||
if [[ "$username" == "admin" ]]; then
|
||||
gum style --foreground "#ffb86c" -- "Admin health alerts and ACL settings cannot be changed."
|
||||
health_alert="true"
|
||||
acl_type="group"
|
||||
acl_value="admin"
|
||||
sleep 2
|
||||
gum style --foreground "#ffb86c" -- "Admin health alerts and ACL settings cannot be changed."
|
||||
health_alert="true"
|
||||
acl_type="group"
|
||||
acl_value="admin"
|
||||
sleep 2
|
||||
else
|
||||
gum style -- "Inform about server health? (Currently: $curr_health)"
|
||||
if gum confirm; then health_alert="true"; else health_alert="false"; fi
|
||||
gum style -- "Inform about server health? (Currently: $curr_health)"
|
||||
if gum confirm; then health_alert="true"; else health_alert="false"; fi
|
||||
|
||||
gum style -- "How should ACL be managed? (Currently: $curr_type)"
|
||||
acl_type=$(gum choose "Assign to Group" "Manual Service Selection")
|
||||
|
||||
if [[ "$acl_type" == "Assign to Group" ]]; then
|
||||
acl_type="group"
|
||||
local group_keys=("${!ACL_GROUPS[@]}")
|
||||
acl_value=$(gum choose "${group_keys[@]}")
|
||||
acl_type="group"
|
||||
local group_keys=("${!ACL_GROUPS[@]}")
|
||||
acl_value=$(gum choose "${group_keys[@]}")
|
||||
else
|
||||
acl_type="manual"
|
||||
gum style --foreground "#50fa7b" -- "Select services for $username:"
|
||||
acl_value=$(gum choose --no-limit "${ACL_SERVICES[@]}" | paste -sd "," -)
|
||||
acl_type="manual"
|
||||
gum style --foreground "#50fa7b" -- "Select services for $username:"
|
||||
acl_value=$(gum choose --no-limit "${ACL_SERVICES[@]}" | paste -sd "," -)
|
||||
fi
|
||||
fi
|
||||
|
||||
ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value"
|
||||
gum style --foreground "#50fa7b" -- "✔ User '$username' updated."
|
||||
sleep 1
|
||||
}
|
||||
fi
|
||||
|
||||
ACL_USERS["$username"]="$name|$email|$phone|$health_alert|$acl_type|$acl_value"
|
||||
gum style --foreground "#50fa7b" -- "✔ User '$username' updated."
|
||||
sleep 1
|
||||
}
|
||||
|
||||
remove_user() {
|
||||
remove_user() {
|
||||
if [[ ${#ACL_USERS[@]} -eq 0 ]]; then return; fi
|
||||
|
||||
local user_keys=("${!ACL_USERS[@]}")
|
||||
@@ -723,39 +693,35 @@ remove_user() {
|
||||
|
||||
if [[ -z "$username" ]]; then return; fi
|
||||
if [[ "$username" == "admin" ]]; then
|
||||
gum style --foreground "#ff0000" -- "✖ The admin user cannot be removed."
|
||||
sleep 2; return
|
||||
gum style --foreground "#ff0000" -- "✖ The admin user cannot be removed."
|
||||
sleep 2; return
|
||||
fi
|
||||
|
||||
gum style --foreground "#ff5555" --bold -- "Are you sure you want to delete '$username'?"
|
||||
if gum confirm; then
|
||||
unset ACL_USERS["$username"]
|
||||
gum style --foreground "#50fa7b" -- "✔ User deleted."
|
||||
sleep 1
|
||||
unset ACL_USERS["$username"]
|
||||
gum style --foreground "#50fa7b" -- "✔ User deleted."
|
||||
sleep 1
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
manage_users_menu() {
|
||||
manage_users_menu() {
|
||||
while true; do
|
||||
clear
|
||||
gum style --border double --margin "1" --padding "0 1" --border-foreground "#ff79c6" -- "User Management (${#ACL_USERS[@]}/20)"
|
||||
show_users_table
|
||||
|
||||
local action=$(gum choose "Add User" "Edit User" "Remove User" "Back")
|
||||
case "$action" in
|
||||
"Add User") add_user ;;
|
||||
"Edit User") edit_user ;;
|
||||
"Remove User") remove_user ;;
|
||||
"Back"|"") break ;;
|
||||
esac
|
||||
clear
|
||||
gum style --border double --margin "1" --padding "0 1" --border-foreground "#ff79c6" -- "User Management (${#ACL_USERS[@]}/20)"
|
||||
show_users_table
|
||||
|
||||
local action=$(gum choose "Add User" "Edit User" "Remove User" "Back")
|
||||
case "$action" in
|
||||
"Add User") add_user ;;
|
||||
"Edit User") edit_user ;;
|
||||
"Remove User") remove_user ;;
|
||||
"Back"|"") break ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
# ==========================================
|
||||
# 6. SETUP & EXPORT
|
||||
# ==========================================
|
||||
|
||||
setup_admin_user() {
|
||||
setup_admin_user() {
|
||||
if [[ -n "${ACL_USERS["admin"]}" ]]; then return; fi
|
||||
|
||||
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"
|
||||
gum style --foreground "#50fa7b" -- "✔ Administrator configured."
|
||||
sleep 1
|
||||
}
|
||||
}
|
||||
|
||||
export_data() {
|
||||
export_data() {
|
||||
clear
|
||||
gum style --foreground "#50fa7b" --bold -- "--- Provisioning Data Payload ---"
|
||||
echo "GROUPS:"
|
||||
@@ -782,54 +748,31 @@ export_data() {
|
||||
for user in "${!ACL_USERS[@]}"; do
|
||||
echo " $user -> ${ACL_USERS[$user]}"
|
||||
done
|
||||
}
|
||||
|
||||
compute_acl_services
|
||||
ACL_GROUPS["admin"]=$(printf "%s," "${ACL_SERVICES[@]}" | sed 's/,$//')
|
||||
setup_admin_user
|
||||
|
||||
while true; do
|
||||
clear
|
||||
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"
|
||||
echo ""
|
||||
|
||||
local choice=$(gum choose "1. Manage Groups" "2. Manage Users" "3. Finish & Apply Configuration")
|
||||
|
||||
case "$choice" in
|
||||
"1. Manage Groups") manage_groups_menu ;;
|
||||
"2. Manage Users") manage_users_menu ;;
|
||||
"3. Finish & Apply Configuration")
|
||||
export_data
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu() {
|
||||
compute_acl_services
|
||||
ACL_GROUPS["admin"]=$(printf "%s," "${ACL_SERVICES[@]}" | sed 's/,$//')
|
||||
setup_admin_user
|
||||
|
||||
while true; do
|
||||
clear
|
||||
gum style --border double --margin "1" --padding "1 2" --border-foreground "#bd93f9" -- "Server Deployment - Access Management"
|
||||
gum style -- "Current state: ${#ACL_GROUPS[@]}/10 Groups | ${#ACL_USERS[@]}/20 Users"
|
||||
echo ""
|
||||
|
||||
local choice=$(gum choose "1. Manage Groups" "2. Manage Users" "3. Finish & Apply Configuration" "4. Exit without saving")
|
||||
|
||||
case "$choice" in
|
||||
"1. Manage Groups") manage_groups_menu ;;
|
||||
"2. Manage Users") manage_users_menu ;;
|
||||
"3. Finish & Apply Configuration")
|
||||
export_data
|
||||
break
|
||||
;;
|
||||
"4. Exit without saving"|"")
|
||||
echo "Aborting..."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
########################################################################""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
disks_selection() {
|
||||
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.
|
||||
@@ -1399,6 +1342,8 @@ EMAIL_REGEX='^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||
PORT_REGEX='^[0-9]{1,5}$'
|
||||
SSH_KEY_REGEX='^ssh-[a-z0-9]+ [A-Za-z0-9+/]+.*'
|
||||
PHONE_REGEX='^\+[1-9][0-9]{7,14}$'
|
||||
|
||||
|
||||
# --- DEFAULTS VARIABLES ---<
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user