test core for configure

This commit is contained in:
2026-10-30 11:01:57 -06:00
parent 38c03b0b69
commit c0df6537ca
2 changed files with 238 additions and 24 deletions
+237 -23
View File
@@ -218,13 +218,24 @@ EOF
echo "Added $CORE_EMAIL to Online Accounts."
}
# Save APP_PASSWORD for davfs2 to mount your files with. davfs2 only reads
# this file if no one else can.
save_files_secret() {
local secret
mkdir -p -m 700 "$HOME/.davfs2"
touch "$HOME/.davfs2/secrets"
chmod 600 "$HOME/.davfs2/secrets"
secret="${APP_PASSWORD//\\/\\\\}"
secret="${secret//\"/\\\"}"
sed -i "\\#^$MOUNT #d" "$HOME/.davfs2/secrets"
printf '%s %s "%s"\n' "$MOUNT" "$CORE_USER" "$secret" >> "$HOME/.davfs2/secrets"
}
# Mount your Nextcloud files at /mnt/<domain> with davfs2. You can mount it
# without sudo once it's in /etc/fstab with "user" and you're in Arch's davfs2
# group (network). It's mounted now and each time you log in.
setup_files() {
[ -n "$APP_PASSWORD" ] || { echo "This needs your Core password, and Nextcloud didn't accept it."; return 1; }
local secret
sudo install -d -o "$USER" -g "$(id -gn)" "$MOUNT" || return 1
if ! grep -qs " $MOUNT davfs " /etc/fstab; then
echo "$WEBDAV $MOUNT davfs rw,user,noauto,uid=$USER,_netdev 0 0" | sudo tee -a /etc/fstab > /dev/null || return 1
@@ -234,15 +245,7 @@ setup_files() {
if ! id -nG "$USER" | grep -qw network; then
sudo usermod -aG network "$USER" || return 1
fi
# davfs2 only reads this file if no one else can
mkdir -p -m 700 "$HOME/.davfs2"
touch "$HOME/.davfs2/secrets"
chmod 600 "$HOME/.davfs2/secrets"
secret="${APP_PASSWORD//\\/\\\\}"
secret="${secret//\"/\\\"}"
sed -i "\\#^$MOUNT #d" "$HOME/.davfs2/secrets"
printf '%s %s "%s"\n' "$MOUNT" "$CORE_USER" "$secret" >> "$HOME/.davfs2/secrets"
save_files_secret || return 1
mkdir -p "$HOME/.config/autostart"
cat > "$HOME/.config/autostart/core-$CORE_DOMAIN-files.desktop" << EOF
@@ -300,6 +303,25 @@ step() {
"setup_$name" || { echo -e "\e[31m$title was not set up.\e[0m"; STATUS=1; }
}
# Ask for your Core password until Nextcloud takes it, and with a name ($1),
# create an app password by that name (APP_PASSWORD). PASSWORD is left empty
# if Nextcloud says it's wrong three times, and kept, unchecked, if Nextcloud
# can't be reached.
ask_password() {
local tries
for tries in 1 2 3; do
read -rsp "Your Core password: " PASSWORD
echo
if [ -n "$1" ]; then nextcloud_app_password "$1"; else nextcloud_sign_in; fi
case $? in
0) return 0 ;;
2) echo "Nextcloud says that password is wrong."; PASSWORD="" ;;
*) echo "Couldn't reach Nextcloud at $NEXTCLOUD; trying the password for email anyway."; return 1 ;;
esac
done
return 1
}
# Set up the Core loaded with load_core, or a new one
setup_core() {
local url
@@ -324,17 +346,7 @@ setup_core() {
# Nextcloud, email and files need your Core password; Nextcloud checks it
if ! nextcloud_done || ! email_done || ! files_done; then
local tries
for tries in 1 2 3; do
read -rsp "Your Core password: " PASSWORD
echo
nextcloud_app_password "CoreDesktop on $HOSTNAME"
case $? in
0) break ;;
2) echo "Nextcloud says that password is wrong."; PASSWORD="" ;;
*) echo "Couldn't reach Nextcloud at $NEXTCLOUD; trying the password for email anyway."; break ;;
esac
done
ask_password "CoreDesktop on $HOSTNAME"
fi
echo
@@ -401,7 +413,7 @@ change_password() {
echo " Nextcloud in Online Accounts: working"
else
echo -e " \e[31mNextcloud in Online Accounts: can't sign in.\e[0m"
echo " Remove it in Settings > Online Accounts, then run: configure core"
echo " To fix it: configure core, then choose t) Test a Core"
STATUS=1
fi
fi
@@ -513,6 +525,204 @@ remove_core() {
fi
}
# Testing a Core checks each part this computer set up for it against the
# Core itself, then offers to fix what doesn't work. A test that fails adds a
# fix, if there is one, to FIXES (with its title in FIX_TITLES).
passed() {
echo -e " $1: \e[32mworking\e[0m"
}
# failed <title> <problem> [fix] [more]
failed() {
echo -e " \e[31m$1: $2\e[0m"
[ -n "$4" ] && echo " $4"
PROBLEMS=$((PROBLEMS + 1))
[ -n "$3" ] && FIXES+=("$3") FIX_TITLES+=("$1")
}
# Test an Online Accounts account: <title> <provider> <identity> <setup> <fix>
test_account() {
local error
if ! "$GOA_ACCOUNT" exists "$2" "$3" 2> /dev/null; then
failed "$1" "not set up" "$4"
elif error="$("$GOA_ACCOUNT" check "$2" "$3" 2>&1)"; then
passed "$1"
else
failed "$1" "can't sign in" "$5" "$error"
fi
}
test_files() {
local title="Nextcloud files at $MOUNT"
files_done || { failed "$title" "not set up" setup_files; return; }
nextcloud_sign_in "$(files_app_password)"
case $? in
0) if mountpoint -q "$MOUNT" && timeout 15 ls "$MOUNT" &> /dev/null; then
passed "$title"
else
failed "$title" "not mounted" remount_files
fi ;;
2) failed "$title" "Nextcloud doesn't accept its app password" fix_files \
"It may have been revoked in Nextcloud under Settings > Security." ;;
*) failed "$title" "couldn't check its app password" ;;
esac
}
test_element() {
local title="Element with your Core's Matrix server"
if ! element_done; then
failed "$title" "Element uses another server" setup_element
elif curl -sf -o /dev/null --max-time 15 "$MATRIX/_matrix/client/versions"; then
passed "$title"
else
failed "$title" "can't reach $MATRIX"
fi
}
test_backups() {
local webdav
webdav="$(source "$BACKUP_CONF" && echo "$BACKUP_WEBDAV")"
nextcloud_sign_in "$(secret-tool lookup coredesktop backup item nextcloud url "$webdav" 2> /dev/null)"
case $? in
0) passed "Backups" ;;
2) failed "Backups" "Nextcloud doesn't accept their app password" fix_backups ;;
*) failed "Backups" "couldn't check their app password" ;;
esac
}
# Test the Core loaded with load_core. Fails if Nextcloud can't be reached,
# as then nothing else can be tested.
test_core() {
local status
FIXES=() FIX_TITLES=() PROBLEMS=0
status="$(curl -sf --max-time 15 "$NEXTCLOUD/status.php")"
if [ -z "$status" ]; then
echo -e " \e[31mCouldn't reach Nextcloud at $NEXTCLOUD.\e[0m"
echo " Check this computer's internet connection, or whether your Core is down."
return 1
fi
if jq -e '.maintenance' <<< "$status" > /dev/null 2>&1; then
echo " Nextcloud is being updated (maintenance mode). Test again when it's done."
return 1
fi
if ! superpanel_done; then
failed "Superpanel in your applications" "not set up" setup_superpanel
elif curl -s -o /dev/null --max-time 15 "https://superpanel.$CORE_DOMAIN/"; then
passed "Superpanel"
else
failed "Superpanel" "can't reach https://superpanel.$CORE_DOMAIN"
fi
test_account "Nextcloud in Online Accounts" owncloud "$CORE_USER@nextcloud.$CORE_DOMAIN" \
setup_nextcloud fix_nextcloud
test_account "Email in Online Accounts" imap_smtp "$CORE_EMAIL" setup_email fix_email
test_files
[ "$CORE_DOMAIN" = "$MAIN_DOMAIN" ] && element_installed && test_element
backup_on "$CORE_DOMAIN" && test_backups
return 0
}
# Online Accounts gets a new app password
fix_nextcloud() {
[ -n "$APP_PASSWORD" ] || { echo "This needs your Core password, and Nextcloud didn't accept it."; return 1; }
jq -n --arg password "$APP_PASSWORD" '{password: $password}' \
| "$GOA_ACCOUNT" update owncloud "$CORE_USER@nextcloud.$CORE_DOMAIN" || return 1
echo "Nextcloud in Online Accounts has a new app password."
}
# Email gets your Core password. If the mail server still says no, its
# settings may have changed, so add it again with the server's settings now.
fix_email() {
[ -n "$PASSWORD" ] || { echo "This needs your Core password."; return 1; }
jq -n --arg password "$PASSWORD" '{"imap-password": $password, "smtp-password": $password}' \
| "$GOA_ACCOUNT" update imap_smtp "$CORE_EMAIL" 2> /dev/null
case $? in
0) echo "Email has your Core password." ;;
3) echo "The mail server still says no; adding your email again with its current settings."
"$GOA_ACCOUNT" remove imap_smtp "$CORE_EMAIL" && setup_email ;;
*) return 1 ;;
esac
}
# Unmount if it's stuck, then mount
remount_files() {
if mountpoint -q "$MOUNT"; then
umount "$MOUNT" 2> /dev/null || sudo umount "$MOUNT" || return 1
fi
mount "$MOUNT" 2> /dev/null || sudo -u "$USER" mount "$MOUNT" || return 1
echo "Your Nextcloud files are at $MOUNT."
}
# davfs2 gets a new app password
fix_files() {
[ -n "$APP_PASSWORD" ] || { echo "This needs your Core password, and Nextcloud didn't accept it."; return 1; }
save_files_secret && remount_files
}
# Backups get their own new app password, as configure backup gives them
fix_backups() {
local APP_PASSWORD webdav
[ -n "$PASSWORD" ] || { echo "This needs your Core password."; return 1; }
webdav="$(source "$BACKUP_CONF" && echo "$BACKUP_WEBDAV")"
nextcloud_app_password "CoreDesktop backup on $HOSTNAME" || return 1
printf '%s' "$APP_PASSWORD" | secret-tool store --label "CoreDesktop backup nextcloud ($webdav)" \
coredesktop backup item nextcloud url "$webdav" || return 1
echo "Backups have a new app password."
}
# Run the fixes test_core found, asking for your Core password once if they
# need it
fix_core() {
local fix i needs=""
for fix in "${FIXES[@]}"; do
case "$fix" in
setup_nextcloud|fix_nextcloud|setup_files|fix_files) needs=app ;;
setup_email|fix_email|fix_backups) needs="${needs:-password}" ;;
esac
done
case "$needs" in
app) ask_password "CoreDesktop on $HOSTNAME" ;;
password) ask_password ;;
esac
STATUS=0
for i in "${!FIXES[@]}"; do
echo
echo "${FIX_TITLES[$i]}:"
"${FIXES[$i]}" || { echo -e "\e[31m${FIX_TITLES[$i]} was not fixed.\e[0m"; STATUS=1; }
done
unset PASSWORD APP_PASSWORD
return $STATUS
}
check_core() {
load_core "$1"
echo "Testing $CORE_DOMAIN..."
test_core || return 1
if [ $PROBLEMS -eq 0 ]; then
echo "Everything works."
return 0
fi
echo
if [ ${#FIXES[@]} -eq 0 ]; then
echo "This computer can't fix that; it's on the Core's side, or the network's."
return 1
fi
confirm_yes "Fix what doesn't work?" || return 1
fix_core
echo
echo "Testing $CORE_DOMAIN again..."
test_core || return 1
if [ $PROBLEMS -eq 0 ]; then
echo "Everything works now."
else
echo "Some of it still doesn't work."
return 1
fi
}
run_configure() {
local choice i state
mapfile -t DOMAINS < <(core_domains)
@@ -536,6 +746,7 @@ run_configure() {
echo " Choose a number to finish or change its setup, or:"
echo " a) Add a Core"
[ ${#DOMAINS[@]} -gt 1 ] && echo " m) Make another Core the main one"
echo " t) Test a Core, and fix what doesn't work"
echo " p) Your Core password changed"
echo " r) Remove a Core"
echo " q) Leave it as it is"
@@ -552,6 +763,9 @@ run_configure() {
p|P)
pick_core "Which Core's password changed?" || { echo "Choose a number from the list."; return 1; }
change_password "$PICKED" ;;
t|T)
pick_core "Which Core should be tested?" || { echo "Choose a number from the list."; return 1; }
check_core "$PICKED" ;;
r|R)
pick_core "Which Core should be removed?" || { echo "Choose a number from the list."; return 1; }
remove_core "$PICKED" ;;