From 23edc5828c731e4b418ef26382c642011da1c170 Mon Sep 17 00:00:00 2001 From: Christoph Date: Sun, 20 Apr 2025 02:07:01 +0200 Subject: [PATCH] Add script 'add-new-account.sh'. --- add-new-account.sh | 747 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 747 insertions(+) create mode 100755 add-new-account.sh diff --git a/add-new-account.sh b/add-new-account.sh new file mode 100755 index 0000000..cc4d359 --- /dev/null +++ b/add-new-account.sh @@ -0,0 +1,747 @@ +#!/usr/bin/env bash + +CUR_IFS=$IFS + +script_name="$(basename $(realpath $0))" +script_dir="$(dirname $(realpath $0))" + +conf_dir="${script_dir}/conf" +snippet_dir="${script_dir}/snippets" + +declare -a unsorted_website_arr +declare -a website_arr + +declare -a unsorted_account_arr +declare -a account_arr + +declare -a unsorted_group_arr +declare -a group_arr + +log_file="$(mktemp)" + +backup_date=$(date +%Y-%m-%d-%H%M) + + +# ============= +# --- Some functions +# ============= + +clean_up() { + + + if [[ -f "$_backup_crontab_file" ]]; then + + echononl "(Re)Install previously saved crontab from '$_backup_crontab_file'.." + + crontab $_backup_crontab_file >> $log_file 2>&1 + + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + error "$(cat $log_file)" + fi + + fi + + # Perform program exit housekeeping + rm -f $log_file + blank_line + exit $1 +} + +is_number() { + + return $(test ! -z "${1##*[!0-9]*}" > /dev/null 2>&1); + + # - also possible + # - + #[[ ! -z "${1##*[!0-9]*}" ]] && return 0 || return 1 + #return $([[ ! -z "${1##*[!0-9]*}" ]]) +} + +echononl(){ + echo X\\c > /tmp/shprompt$$ + if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then + echo -e -n "$*\\c" 1>&2 + else + echo -e -n "$*" 1>&2 + fi + rm /tmp/shprompt$$ +} +echo_done() { + if $terminal ; then + echo -e "\033[75G[ \033[32mdone\033[m ]" + else + echo " [ done ]" + fi +} +echo_ok() { + if $terminal ; then + echo -e "\033[75G[ \033[32mok\033[m ]" + else + echo " [ ok ]" + fi +} +echo_warning() { + if $terminal ; then + echo -e "\033[75G[ \033[33m\033[1mwarn\033[m ]" + else + echo " [ warning ]" + fi +} +echo_failed(){ + if $terminal ; then + echo -e "\033[75G[ \033[1;31mfailed\033[m ]" + else + echo ' [ failed! ]' + fi +} +echo_skipped() { + if $terminal ; then + echo -e "\033[75G[ \033[37mskipped\033[m ]" + else + echo " [ skipped ]" + fi +} +fatal (){ + echo "" + echo "" + if $terminal ; then + echo -e "\t[ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m" + echo "" + echo -e "\t\033[31m\033[1m Script will be interrupted..\033[m\033[m" + else + echo "fatal: $*" + echo "Script will be interrupted.." + fi + clean_up 1 +} + +error(){ + echo "" + if $terminal ; then + echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*" + else + echo "Error: $*" + fi + echo "" +} + +warn (){ + echo "" + if $terminal ; then + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + else + echo "Warning: $*" + fi + echo "" +} + +info (){ + echo "" + if $terminal ; then + echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" + else + echo "Info: $*" + fi + echo "" +} + +detect_os_1 () { + + if $(which lsb_release > /dev/null 2>&1) ; then + + os_dist="$(lsb_release -i | awk '{print tolower($3)}')" + os_version="$(lsb_release -r | awk '{print tolower($2)}')" + os_codename="$(lsb_release -c | awk '{print tolower($2)}')" + + if [[ "$os_dist" = "debian" ]]; then + if $(echo "$os_version" | grep -q '\.') ; then + os_version=$(echo "$os_version" | cut --delimiter='.' -f1) + fi + fi + + elif [[ -e "/etc/os-release" ]]; then + + . /etc/os-release + + os_dist=$ID + os_version=${VERSION_ID} + + fi + + # remove whitespace from os_dist and os_version + os_dist="${os_dist// /}" + os_version="${os_version// /}" + +} + +# - Remove leading/trailling whitespaces +# - +trim() { + local var="$*" + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +## - Check if a given array (parameter 2) contains a given string (parameter 1) +## - +containsElement () { + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done + return 1 +} + +random_char() { + local chars="$1" + echo -n "${chars:RANDOM%${#chars}:1}" +} + +# Funktion zur Generierung eines zufälligen Strings mit den angegebenen Anforderungen +generate_random_string() { + local length="$1" + + # Überprüfen, ob die Länge größer als 8 ist + if [[ "$length" -le 8 ]]; then + echo "Fehler: Die Länge muss größer als 8 Zeichen sein." + return 1 + fi + + # Zeichenmengen + + # not allowed: 0ODl18B + + local lower="abcdefghijkmnopqrstuvwxyz" + #local upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ" + local upper="ACEFGHIJKLMNPQRSTUVWXYZ" + #local digits="0123456789" + local digits="2345679" + #local special="!@#$%^&*()_+-=[]{}|;:,.<>?/" + local special="__+---///...." + + # Generiere mindestens ein Zeichen aus jeder Kategorie + local random_string=$(random_char "$lower") + random_string+=$(random_char "$upper") + random_string+=$(random_char "$digits") + random_string+=$(random_char "$special") + random_string+=$(random_char "$special") + + # Fülle den Rest der Zeichenkette mit zufälligen Zeichen aus allen Kategorien + local all_chars="$lower$upper$digits$special" + for (( i=${#random_string}; i ${log_file} | awk -F'[:[:space:]]+' '{print $3}' 2>> ${log_file} ) + +# Oder Methode 2: while-Schleife +# +#while IFS= read -r line; do +# unsorted_account_arr+=("$(echo "$line" | awk -F'[:[:space:]]+' '{print $3}' 2>> ${log_file})") +#done <<< "$(su -c "${PHP_BIN} ${WEB_BASE_DIR}/htdocs/occ user:list" -s /bin/bash $HTTP_USER 2> ${log_file})" + +if [[ $? -gt 0 ]] || [[ -s "${log_file}" ]] ; then + echo_failed + error "$(cat $log_file)\n" +else + echo_ok +fi + +echononl " Get list of current groups.." + +mapfile -t unsorted_group_arr < <(su -c "${PHP_BIN} ${WEB_BASE_DIR}/htdocs/occ group:list" -s /bin/bash $HTTP_USER 2> ${log_file} | awk '/^\s*-\s[^:]+:$/{gsub(/^\s*-\s|:$/, ""); print}' 2>> ${log_file} ) + +#su -c "${PHP_BIN} ${WEB_BASE_DIR}/htdocs/occ user:list" -s /bin/bash $HTTP_USER | \ +# | awk -F'[:[:space:]]+' '{print $3}' + + + +echo "" +echo "" +echo -e "\033[32m-----\033[m" +echo "" +echo -e " Which \033[1muser\033[m would you like to add?" +echo "" +NEW_ACCOUNT= +while [[ -z "$(trim ${NEW_ACCOUNT})" ]] ; do + + echononl " New NC accoun name: " + read NEW_ACCOUNT + + if containsElement "${NEW_ACCOUNT}" "${unsorted_account_arr[@]}" ; then + echo -e "\n\t\033[33m\033[1mAccount \033[m\033[1m${NEW_ACCOUNT}\033[33m already exists! \033[m- Try again\n" + NEW_ACCOUNT="" + #echononl " New NC accoun name: " + continue + + fi + + if [[ -z "$(trim ${NEW_ACCOUNT})" ]] ; then + echo -e "\n\t\033[33m\033[1mAccount name must be given.\033[m\n" + fi +done + + +echo "" +echo "" +echo -e "\033[32m-----\033[m" +echo "" +echo -e " Enter the display name for the account \033[1m${NEW_ACCOUNT}\033[m" +echo "" +echo -e " Type \033[33mNone\033[m to not assign a display name" +echo "" +DISPLAY_NAME= +while [[ -z "$(trim ${DISPLAY_NAME})" ]] ; do + + echononl " Display name for he account \033[1m${DISPLAY_NAME}\033[m: " + read DISPLAY_NAME + + if [[ "${DISPLAY_NAME,,}" = "none" ]] ; then + DISPLAY_NAME="" + break + fi + + if [[ -z "$(trim ${DISPLAY_NAME})" ]] ; then + echo -e "\n\t\033[33m\033[1mEntry must not be empty. Type \033[m\033[1mNone\033[33m for not assigning a display name.\033[m\n" + fi + +done + + +blank_line +blank_line +echo -e " Present groups on NC Cloud instance \033[1m${WEBSITE}\033[m\n" +echo -en "\033[33m" +printf " %s\n" "${unsorted_group_arr[@]}" +echo -en "\033[m" +blank_line + + +echo "" +echo "" +echo -e "\033[32m-----\033[m" +echo "" +echo -e " Which groups should the new account belong to?" +echo "" +echo " - enter a list separated by spaces" +echo -e " - or type \033[33mNone\033[m to not assign the account to any group" +echo "" +ASSIGNED_GROUPS= +while [[ -z "$(trim ${ASSIGNED_GROUPS})" ]] ; do + + echononl " Groups to which the new account should belong: " + read ASSIGNED_GROUPS + + if [[ "${ASSIGNED_GROUPS,,}" = "none" ]] ; then + ASSIGNED_GROUPS="" + break + fi + + if [[ -z "$(trim ${ASSIGNED_GROUPS})" ]] ; then + echo -e "\n\t\033[33m\033[1mEntry must not be empty. Type \033[m\033[1mNone\033[33m for not assigning a group.\033[m\n" + continue + fi + + IFS=' ' read -ra assigned_groups_arr <<< "${ASSIGNED_GROUPS}" + + for _group in "${assigned_groups_arr[@]}" ; do + if ! containsElement "${_group}" "${unsorted_group_arr[@]}" ; then + echo -e "\n\t\033[33m\033[1m No group \033[m\033[1m${_group}\033[33m present!\033[m - Try again..\n" + ASSIGNED_GROUPS="" + break + fi + done + + # - Sort array +# - + IFS=$'\n' assigned_groups_arr=($(sort <<<"${assigned_groups_arr[*]}")) + +done + + +echo "" +echo "" +echo -e "\033[32m-----\033[m" +echo "" +echo -e " Enter a password for the new account \033[1m${NEW_ACCOUNT}\033[m" +echo "" +echo " Some random genaerated Passwords:" +echo "" +for ((i=0; i<=9; i++)); do + + echo -en " $i: " + echo -e "\033[33m$(generate_random_string 12)\033[m" + +done +echo "" +_PW1="X" +_PW2="Y" +while [ "$_PW1" != "$_PW2" ] +do + echononl "Password: " + #read -s _PW1 + read _PW1 + echo + if [ "X$_PW1" = "X" ]; then + echo -e "\n\t\033[33m\033[1mA password is required!\033[m\n" + continue + fi + echononl "Repeat the password: " + #read -s _PW2 + read _PW2 + echo + if [ "$_PW1" != "$_PW2" ];then + echo -e "\n\t\033[33m\033[1mpassword entries are NOT identical!\033[m\n" + else + PASSWORD=$_PW1 + fi +done + + +regex_email="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" +echo "" +echo "" +echo -e "\033[32m-----\033[m" +echo "" +echo -e " Enter an e-mail address for the new account \033[1m${NEW_ACCOUNT}\033[m" +echo "" +echo -e " Type \033[33mNone\033[m to not assign an e-mail address" +echo "" +E_MAIL= +while [[ -z "$(trim ${E_MAIL})" ]] ; do + + echononl " E-Mail address for the new account \033[1m${E_MAIL}\033[m: " + read E_MAIL + + if [[ "${E_MAIL,,}" = "none" ]] ; then + E_MAIL="" + break + fi + + if [[ ! "${E_MAIL,,}" =~ ${regex_email} ]]; then + echo -e "\n\t\033[m\033[1m${E_MAIL}\033[33m is not a valid e-mail address\033[m - Try again..\n" + E_MAIL="" + continue + fi + + + if [[ -z "$(trim ${E_MAIL})" ]] ; then + echo -e "\n\t\033[33m\033[1mEntry must not be empty. Type \033[m\033[1mNone\033[33m for not assigning an e-mail address.\033[m\n" + fi + +done + + + +echo "" +echo "" +echo "" +echo -e "\033[1;32mStarting Script for \033[1;37m${WEBSITE}\033[m" +echo "" +echo -e " Cloud instance to be changed.........: ${WEBSITE}" +echo "" +echo -e " Current version of nextcloud.........: $CURRENT_VERSION" +echo "" +echo "" +echo -e " New Account..........................: ${NEW_ACCOUNT}" +if [[ -z "${DISPLAY_NAME}" ]] ; then + echo -e " Display Name.........................: \033[33mNone\033[m" +else + echo -e " Display Name.........................: ${DISPLAY_NAME}" +fi +if [[ -z "${E_MAIL}" ]] ; then + echo -e " E-Mail Address.......................: \033[33mNone\033[m" +else + echo -e " E-Mail Address.......................: ${E_MAIL}" +fi +echo "" +echo -e " Password.............................: ${PASSWORD}" +echo "" +if [[ -z "${ASSIGNED_GROUPS}" ]] ; then + echo -e " Group(s) assigned to the new account.: \033[33mNone\033[m" +else + declare -i index=0 + for _group in "${assigned_groups_arr[@]}" ; do + if [[ ${index} -lt 1 ]] ; then + echo -e " Group(s) assigned to the new account.: \033[33m${_group}\033[m" + else + echo -e " \033[33m${_group}\033[m" + fi + (( index++ )) + done +fi +echo "" +echo "" +echo -e " Web base directory...................: $WEB_BASE_DIR" +echo "" +echo -e " Webserver user.......................: $HTTP_USER" +echo -e " Webserver group......................: $HTTP_GROUP" +echo "" +echo -e " PHP version..........................: $PHP_VERSION" +echo -e " PHP Engine...........................: $PHP_ENGINE" +echo "" +echo -e " PHP command..........................: $PHP_BIN" +echo "" +echo -e " Databse name.........................: $DATABASE_NAME" +echo -e " Database type........................: $DATABASE_TYPE" +echo "" +if [[ "$DATABASE_TYPE" = "mysql" ]] ; then + echo -e " Mysql Credentials....................: $MYSQL_CREDENTIALS" +fi +echo "" + +echo "" +echo -n " Type upper case 'YES' to continue executing with this parameters: " +read OK +if [[ "$OK" = "YES" ]] ; then + echo "" + echo "" + echo -e "\033[1;32mGoing to create new account \033[1;37m${NEW_ACCOUNT}\033[1;32m on \033[1;37m${WEBSITE}\033[m" + echo "" +else + fatal "Abort by user request - Answer as not 'YES'" +fi + + +echo "" + + +# ----- +# - Main part of the script +# ----- + +echo "" +echo "" +echo -e "\033[37m\033[1mMain part of the script\033[m" +echo "" + +occ_arg_string="user:add --password-from-env" +echononl " Create Parametwer String.." + +[[ -n "${DISPLAY_NAME}" ]] && occ_arg_string="${occ_arg_string} --display-name='${DISPLAY_NAME}'" + +if [[ ${#assigned_groups_arr[@]} -gt 0 ]] ; then + for _group in "${assigned_groups_arr[@]}" ; do + occ_arg_string="${occ_arg_string} --group='${_group}'" + done +fi + +[[ -n "${E_MAIL}" ]] && occ_arg_string="${occ_arg_string} --email=${E_MAIL}" + +occ_arg_string="${occ_arg_string} ${NEW_ACCOUNT}" + +echo_done + + +# - Create new account +# - +echononl " Create new account \033[1;37m${NEW_ACCOUNT}\033[m on \033[1;37m${WEBSITE} \033[m".."" +su -c "OC_PASS='${PASSWORD}' ${PHP_BIN} ${WEB_BASE_DIR}/htdocs/occ ${occ_arg_string}" -s /bin/bash ${HTTP_USER} \ + > $log_file 2>&1 +if [[ $? -eq 0 ]]; then + echo_ok + blank_line + echo -e "\033[37m\033[1mCommand output was:\033[m" + blank_line + cat ${log_file} + + blank_line + echo -e "Password set to '${PASSWORD}'" + +else + echo_failed + blank_line + echo "" + echo -e "\033[37m\033[1mCommandline was:\033[m" + echo -e " +su -c \"OC_PASS='${PASSWORD}' ${PHP_BIN} ${WEB_BASE_DIR}/htdocs/occ ${occ_arg_string}\" -s /bin/bash ${HTTP_USER} +" + blank_line + error "\n\n$(cat $log_file)" +fi + +blank_line +clean_up 0