Răsfoiți Sursa

Merge pull request #1117 from hestiacp/fix/2020_08_disable_root_web_login

Disable root web login / Add Administrator role to users
Jaap Marcus 5 ani în urmă
părinte
comite
6825a8e545

+ 4 - 0
CHANGELOG.md

@@ -9,6 +9,10 @@ All notable changes to this project will be documented in this file.
     - `UPGRADE_SEND_EMAIL` = Sends an email notification to admin email address
     - `UPGRADE_SEND_EMAIL_LOG` = Sends installation log output to admin email address
 - Upgrade process will now save logs to the `hst_backups` directory.
+- Add the possibility to assign user "Administrators" rights on login. Replaces "root" login. Notifications are only send towards the "admin" account email
+
+## Buggfixes
+- Removed root login (root / root password )
 
 ## Bugfixes
 

+ 3 - 1
README.md

@@ -6,7 +6,9 @@
 
 **Web:** [www.hestiacp.com](https://www.hestiacp.com/)<br>
 **Documentation:** [docs.hestiacp.com](https://docs.hestiacp.com/)<br>
-**Forums:** [forum.hestiacp.com](https://forum.hestiacp.com/)<br><br>
+**Forums:** [forum.hestiacp.com](https://forum.hestiacp.com/)<br>
+**Discord:** [Join HestiaCP Discord channel](https://discord.gg/nXRUZch)<br />
+<br>
 [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ST87LQH2CHGLA)
 <br>
 

+ 1 - 1
bin/v-add-web-domain

@@ -109,7 +109,7 @@ if [ ! -z "$WEB_BACKEND" ]; then
         fi
     fi
     BACKEND="$BACKEND_TEMPLATE"
-    $BIN/v-add-web-domain-backend "$user" "$domain" $BACKEND_TEMPLATE
+    $BIN/v-add-web-domain-backend "$user" "$domain" $BACKEND_TEMPLATE $restart
     check_result $? "Backend error" >/dev/null
 fi
 

+ 1 - 355
bin/v-backup-user

@@ -20,6 +20,7 @@ notify=${2-no}
 source $HESTIA/func/main.sh
 source $HESTIA/func/domain.sh
 source $HESTIA/func/db.sh
+source $HESTIA/func/backup.sh
 source $HESTIA/conf/hestia.conf
 
 
@@ -524,361 +525,6 @@ time=$(echo "$time_n_date" |cut -f 1 -d \ )
 date=$(echo "$time_n_date" |cut -f 2 -d \ )
 backup_new_date=$(date +"%Y-%m-%d_%H-%M-%S")
 
-# Defining local storage function
-local_backup(){
-
-    rm -f $BACKUP/$user.$backup_new_date.tar
-
-    # Checking retention
-    backup_list=$(ls -lrt $BACKUP/ |awk '{print $9}' |grep "^$user\." | grep ".tar")
-    backups_count=$(echo "$backup_list" |wc -l)
-    if [ "$BACKUPS" -le "$backups_count" ]; then
-        backups_rm_number=$((backups_count - BACKUPS + 1))
-
-        # Removing old backup
-        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do
-            backup_date=$(echo $backup |sed -e "s/$user.//" -e "s/.tar$//")
-            echo -e "$(date "+%F %T") Rotated: $backup_date" |\
-                tee -a $BACKUP/$user.log
-            rm -f $BACKUP/$backup
-        done
-    fi
-
-    # Checking disk space
-    disk_usage=$(df $BACKUP |tail -n1 |tr ' ' '\n' |grep % |cut -f 1 -d %)
-    if [ "$disk_usage" -ge "$BACKUP_DISK_LIMIT" ]; then
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        echo "Not enough disk space" |$SENDMAIL -s "$subj" $email $notify
-        check_result "$E_DISK" "Not enough dsk space"
-    fi
-
-    # Creating final tarball
-    cd $tmpdir
-    tar -cf $BACKUP/$user.$backup_new_date.tar .
-    chmod 640 $BACKUP/$user.$backup_new_date.tar
-    chown admin:$user $BACKUP/$user.$backup_new_date.tar
-    localbackup='yes'
-    echo -e "$(date "+%F %T") Local: $BACKUP/$user.$backup_new_date.tar" |\
-        tee -a $BACKUP/$user.log
-}
-
-
-# Defining ftp command function
-ftpc() {
-    /usr/bin/ftp -np $HOST $PORT <<EOF
-    quote USER $USERNAME
-    quote PASS $PASSWORD
-    binary
-    $1
-    $2
-    $3
-    quit
-EOF
-}
-
-# Defining ftp storage function
-ftp_backup() {
-    # Checking config
-    if [ ! -e "$HESTIA/conf/ftp.backup.conf" ]; then
-        error="ftp.backup.conf doesn't exist"
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$E_NOTEXIST" "$error"
-    fi
-
-    # Parse config
-    source $HESTIA/conf/ftp.backup.conf
-
-    # Set default port
-    if [ -z "$(grep 'PORT=' $HESTIA/conf/ftp.backup.conf)" ]; then
-        PORT='21'
-    fi
-
-    # Checking variables
-    if [ -z "$HOST" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
-        error="Can't parse ftp backup configuration"
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$E_PARSING" "$error"
-    fi
-
-    # Debug info
-    echo -e "$(date "+%F %T") Remote: ftp://$HOST$BPATH/$user.$backup_new_date.tar"
-
-    # Checking ftp connection
-    fconn=$(ftpc)
-    ferror=$(echo $fconn |grep -i -e failed -e error -e "Can't" -e "not conn")
-    if [ ! -z "$ferror" ]; then
-        error="Error: can't login to ftp ftp://$USERNAME@$HOST"
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$E_CONNECT" "$error"
-    fi
-
-    # Check ftp permissions
-    if [ -z $BPATH ]; then
-            ftmpdir="vst.bK76A9SUkt"
-        else
-            ftpc "mkdir $BPATH" > /dev/null 2>&1
-            ftmpdir="$BPATH/vst.bK76A9SUkt"
-    fi
-    ftpc "mkdir $ftmpdir" "rm $ftmpdir"
-    ftp_result=$(ftpc "mkdir $ftmpdir" "rm $ftmpdir" |grep -v Trying)
-    if [ ! -z "$ftp_result" ] ; then
-        error="Can't create ftp backup folder ftp://$HOST$BPATH"
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$E_FTP" "$error"
-    fi
-
-    # Checking retention
-    if [ -z $BPATH ]; then
-        backup_list=$(ftpc "ls" |awk '{print $9}' |grep "^$user\.")
-    else
-        backup_list=$(ftpc "cd $BPATH" "ls" |awk '{print $9}' |grep "^$user\.")
-    fi
-    backups_count=$(echo "$backup_list" |wc -l)
-    if [ "$backups_count" -ge "$BACKUPS" ]; then
-        backups_rm_number=$((backups_count - BACKUPS + 1))
-        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do 
-            backup_date=$(echo $backup |sed -e "s/$user.//" -e "s/.tar$//")
-            echo -e "$(date "+%F %T") Rotated ftp backup: $backup_date" |\
-                tee -a $BACKUP/$user.log
-            if [ -z $BPATH ]; then
-                ftpc "delete $backup"
-            else
-                ftpc "cd $BPATH" "delete $backup"
-            fi
-        done
-    fi
-
-    # Uploading backup archive
-    if [ "$localbackup" = 'yes' ]; then
-        cd $BACKUP
-        if [ -z $BPATH ]; then
-            ftpc "put $user.$backup_new_date.tar"
-         else
-            ftpc "cd $BPATH" "put $user.$backup_new_date.tar"
-        fi
-    else
-        cd $tmpdir
-        tar -cf $BACKUP/$user.$backup_new_date.tar .
-        cd $BACKUP/
-        if [ -z $BPATH ]; then
-            ftpc "put $user.$backup_new_date.tar"
-        else
-            ftpc "cd $BPATH" "put $user.$backup_new_date.tar"
-        fi
-        rm -f $user.$backup_new_date.tar
-    fi
-}
-
-# sftp command function
-sftpc() {
-    expect -f "-" <<EOF "$@"
-        set timeout 60
-        set count 0
-        spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
-            -o Port=$PORT $USERNAME@$HOST
-        expect {
-            "password:" {
-                send "$PASSWORD\r"
-                exp_continue
-            }
-
-            -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
-                set count \$argc
-                set output "Disconnected."
-                set rc $E_FTP
-                exp_continue
-            }
-
-            -re ".*denied.*(publickey|password)." {
-                set output "Permission denied, wrong publickey or password."
-                set rc $E_CONNECT
-            }
-
-            -re "\[0-9]*%" {
-                exp_continue
-            }
-
-            "sftp>" {
-                if {\$count < \$argc} {
-                    set arg [lindex \$argv \$count]
-                    send "\$arg\r"
-                    incr count
-                } else {
-                    send "exit\r"
-                    set output "Disconnected."
-                    if {[info exists rc] != 1} {
-                        set rc $OK
-                    }
-                }
-                exp_continue
-            }
-
-            timeout {
-                set output "Connection timeout."
-                set rc $E_CONNECT
-            }
-        }
-
-        if {[info exists output] == 1} {
-            puts "\$output"
-        }
-
-    exit \$rc
-EOF
-}
-
-sftp_backup() {
-
-    # Checking config
-    if [ ! -e "$HESTIA/conf/sftp.backup.conf" ]; then
-        error="Can't open sftp.backup.conf"
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$E_NOTEXIST" "$error"
-    fi
-
-    # Parse config
-    source $HESTIA/conf/sftp.backup.conf
-
-    # Set default port
-    if [ -z "$(grep 'PORT=' $HESTIA/conf/sftp.backup.conf)" ]; then
-        PORT='22'
-    fi
-
-    # Checking variables
-    if [ -z "$HOST" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
-        error="Can't parse sftp backup configuration"
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$E_PARSING" "$error"
-    fi
-
-    # Debug info
-    echo -e "$(date "+%F %T") Remote: sftp://$HOST/$BPATH/$user.$backup_new_date.tar" |\
-        tee -a $BACKUP/$user.log
-
-    # Checking network connection and write permissions
-    if [ -z $BPATH ]; then
-        sftmpdir="vst.bK76A9SUkt"
-    else
-        sftmpdir="$BPATH/vst.bK76A9SUkt"
-    fi
-    sftpc "mkdir $BPATH" > /dev/null 2>&1
-    sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
-    rc=$?
-    if [[ "$rc" != 0 ]]; then
-        case $rc in
-            $E_CONNECT) error="Can't login to sftp host $HOST" ;;
-            $E_FTP) error="Can't create temp folder on sftp $HOST" ;;
-        esac
-        rm -rf $tmpdir
-        rm -f $BACKUP/$user.log
-        echo "$error" |$SENDMAIL -s "$subj" $email $notify
-        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
-        check_result "$rc" "$error"
-    fi
-
-    # Checking retention
-    if [ -z $BPATH ]; then
-        backup_list=$(sftpc "ls -l" |awk '{print $9}'|grep "^$user\.")
-    else
-        backup_list=$(sftpc "cd $BPATH" "ls -l" |awk '{print $9}'|grep "^$user\.")
-    fi
-    backups_count=$(echo "$backup_list" |wc -l)
-    if [ "$backups_count" -ge "$BACKUPS" ]; then
-        backups_rm_number=$((backups_count - BACKUPS + 1))
-        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do
-            backup_date=$(echo $backup |sed -e "s/$user.//" -e "s/.tar.*$//")
-            echo -e "$(date "+%F %T") Rotated sftp backup: $backup_date" |\
-                tee -a $BACKUP/$user.log
-            if [ -z $BPATH ]; then
-                sftpc "rm $backup" > /dev/null 2>&1
-            else
-                sftpc "cd $BPATH" "rm $backup" > /dev/null 2>&1
-            fi
-        done
-    fi
-
-    # Uploading backup archive
-    echo "$(date "+%F %T") Uploading $user.$backup_new_date.tar"|tee -a $BACKUP/$user.log
-    if [ "$localbackup" = 'yes' ]; then
-        cd $BACKUP
-        if [ -z $BPATH ]; then
-            sftpc "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
-        else
-            sftpc "cd $BPATH" "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
-        fi
-    else
-        cd $tmpdir
-        tar -cf $BACKUP/$user.$backup_new_date.tar .
-        cd $BACKUP/
-        if [ -z $BPATH ]; then
-            sftpc "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
-        else
-            sftpc "cd $BPATH" "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
-        fi
-        rm -f $user.$backup_new_date.tar
-    fi
-}
-
-google_backup() {
-
-    # Defining google settings
-    source $HESTIA/conf/google.backup.conf
-    gsutil="$HESTIA/3rdparty/gsutil/gsutil"
-    export BOTO_CONFIG="$HESTIA/conf/.google.backup.boto"
-
-    # Debug info
-    echo -e "$(date "+%F %T") Remote: gs://$BUCKET/$BPATH/$user.$backup_new_date.tar"
-
-    # Checking retention
-    backup_list=$(${gsutil} ls gs://$BUCKET/$BPATH/$user.* 2>/dev/null)
-    backups_count=$(echo "$backup_list" |wc -l)
-    if [ "$backups_count" -ge "$BACKUPS" ]; then
-        backups_rm_number=$((backups_count - BACKUPS))
-        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do 
-            echo -e "$(date "+%F %T") Rotated gcp backup: $backup"
-            $gsutil rm $backup > /dev/null 2>&1
-        done
-    fi
-
-    # Uploading backup archive
-    echo -e "$(date "+%F %T") Uploading $user.$backup_new_date.tar ..."
-    if [ "$localbackup" = 'yes' ]; then
-        cd $BACKUP
-        ${gsutil} cp $user.$backup_new_date.tar gs://$BUCKET/$BPATH/ > /dev/null 2>&1
-    else
-        cd $tmpdir
-        tar -cf $BACKUP/$user.$backup_new_date.tar .
-        cd $BACKUP/
-        ${gsutil} cp $user.$backup_new_date.tar gs://$BUCKET/$BPATH/ > /dev/null 2>&1
-        rc=$?
-        rm -f $user.$backup_new_date.tar
-        if [ "$rc" -ne 0 ]; then
-            check_result "$E_CONNECT" "gsutil failed to upload $user.$backup_new_date.tar"
-        fi
-    fi
-}
-
-
 echo -e "\n-- SUMMARY --" |tee -a $BACKUP/$user.log
 
 # Switching on backup system types

+ 1 - 0
bin/v-change-user-package

@@ -104,6 +104,7 @@ RKEY='$RKEY'
 TWOFA='$TWOFA'
 QRCODE='$QRCODE'
 PHPCLI='$PHPCLI'
+ROLE='$ROLE'
 SUSPENDED='$SUSPENDED'
 SUSPENDED_USERS='$SUSPENDED_USERS'
 SUSPENDED_WEB='$SUSPENDED_WEB'

+ 42 - 0
bin/v-change-user-role

@@ -0,0 +1,42 @@
+#!/bin/bash
+# info: updates user role
+# options: USER ROLE
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+user=$1
+role=$2
+
+
+# Includes
+source $HESTIA/func/main.sh
+source $HESTIA/conf/hestia.conf
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+# Reading user values
+source $USER_DATA/user.conf
+
+is_format_valid 'user' 'role'
+is_object_valid 'user' 'USER' "$user"
+
+is_object_unsuspended 'user' 'USER' "$user"
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+update_user_value "$user" '$ROLE' "$role"
+
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+exit

+ 17 - 2
bin/v-delete-user-backup

@@ -11,10 +11,12 @@
 
 # Argument definition
 user=$1
-backup=$(echo $2| cut -f 2 -d \.)
+backup=$2
 
 # Includes
 source $HESTIA/func/main.sh
+source $HESTIA/func/backup.sh
+
 source $HESTIA/conf/hestia.conf
 
 
@@ -37,8 +39,21 @@ check_hestia_demo_mode
 #                       Action                             #
 #----------------------------------------------------------#
 
+line=$(grep "BACKUP='$backup'" $USER_DATA/backup.conf)
+parse_object_kv_list "$line"
+
+
+if [[ "$TYPE" =~ "sftp" ]]; then
+    sftp_delete "$backup"
+fi
+if [[ "$TYPE" =~ "ftp" ]] && [ "$deleted" == "0" ]; then
+    ftp_delete "backup"
+fi
+if [[ "$TYPE" =~ "local" ]]; then
+    rm -f $BACKUP/$2
+fi
+
 # Deleting backup
-rm -f $BACKUP/$2
 sed -i "/BACKUP='$2' /d" $USER_DATA/backup.conf
 
 

+ 1 - 105
bin/v-download-backup

@@ -28,111 +28,7 @@ source $HESTIA/func/ip.sh
 source $HESTIA/func/db.sh
 source $HESTIA/func/rebuild.sh
 source $HESTIA/conf/hestia.conf
-
-# Defining FTP command function
-ftpc() {
-    /usr/bin/ftp -n $HOST $PORT <<EOF
-    quote USER $USERNAME
-    quote PASS $PASSWORD
-    lcd $BACKUP
-    binary
-    $1
-    $2
-    $3
-    quit
-EOF
-}
-
-# FTP backup download function
-ftp_download() {
-    source $HESTIA/conf/ftp.backup.conf
-    if [ -z "$PORT" ]; then
-        PORT='21'
-    fi
-    if [ -z $BPATH ]; then
-        ftpc "get $1"
-    else
-        ftpc "cd $BPATH" "get $1"
-    fi
-}
-
-# SFTP command function
-sftpc() {
-    expect -f "-" <<EOF "$@"
-        set timeout 60
-        set count 0
-        spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
-            -o Port=$PORT $USERNAME@$HOST
-        expect {
-            "password:" {
-                send "$PASSWORD\r"
-                exp_continue
-            }
-            -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
-                set count \$argc
-                set output "Disconnected."
-                set rc $E_FTP
-                exp_continue
-            }
-            -re ".*denied.*(publickey|password)." {
-                set output "Permission denied, wrong publickey or password."
-                set rc $E_CONNECT
-            }
-            -re "\[0-9]*%" {
-                exp_continue
-            }
-            "sftp>" {
-                if {\$count < \$argc} {
-                    set arg [lindex \$argv \$count]
-                    send "\$arg\r"
-                    incr count
-                } else {
-                    send "exit\r"
-                    set output "Disconnected."
-                    if {[info exists rc] != 1} {
-                        set rc $OK
-                    }
-                }
-                exp_continue
-            }
-            timeout {
-                set output "Connection timeout."
-                set rc $E_CONNECT
-            }
-        }
-        if {[info exists output] == 1} {
-            puts "\$output"
-        }
-    exit \$rc
-EOF
-}
-
-# SFTP backup download function
-sftp_download() {
-    source $HESTIA/conf/sftp.backup.conf
-    if [ -z "$PORT" ]; then
-        PORT='22'
-    fi
-    cd $BACKUP
-    if [ -z $BPATH ]; then
-        sftpc "get $1" > /dev/null 2>&1
-    else
-        sftpc "cd $BPATH" "get $1" > /dev/null 2>&1
-    fi
-
-}
-
-# Google backup download function
-google_download() {
-    source $HESTIA/conf/google.backup.conf
-    gsutil="$HESTIA/3rdparty/gsutil/gsutil"
-    export BOTO_CONFIG="$HESTIA/conf/.google.backup.boto"
-    ${gsutil} cp gs://$BUCKET/$BPATH/$1 $BACKUP/ > /dev/null 2>&1
-    if [ "$?" -ne 0 ]; then
-        check_result "$E_CONNECT" "gsutil failed to download $1"
-    fi
-}
-
+source $HESTIA/func/backup.sh
 
 #----------------------------------------------------------#
 #                    Verifications                         #

+ 1 - 1
bin/v-get-user-salt

@@ -61,7 +61,7 @@ check_args '1' "$#" 'USER [IP] [SALT]'
 is_format_valid 'user'
 
 # Checking user
-if [ ! -d "$HESTIA/data/users/$user" ] && [ "$user" != 'root' ]; then
+if [ ! -d "$HESTIA/data/users/$user" ]; then
     echo "Error: password missmatch"
     echo "$date $time $user $ip failed to login" >> $HESTIA/log/auth.log
     exit 9

+ 1 - 0
bin/v-list-user

@@ -45,6 +45,7 @@ json_list() {
         "RKEY": "'$RKEY'",
         "TWOFA": "'$TWOFA'",
         "QRCODE": "'$QRCODE'",
+        "ROLE": "'$ROLE'",
         "SUSPENDED": "'$SUSPENDED'",
         "SUSPENDED_USERS": "'$SUSPENDED_USERS'",
         "SUSPENDED_WEB": "'$SUSPENDED_WEB'",

+ 6 - 9
bin/v-rebuild-all

@@ -42,15 +42,12 @@ is_object_unsuspended 'user' 'USER' "$user"
 #----------------------------------------------------------#
 
 # Rebuild loop
-for user in $($HESTIA/bin/v-list-sys-users plain); do
-    $BIN/v-rebuild-web-domains $user $restart
-    $BIN/v-rebuild-dns-domains $user $restart
-    $BIN/v-rebuild-mail-domains $user $restart
-    $BIN/v-rebuild-databases $user $restart
-    $BIN/v-rebuild-cron-jobs $user $restart
-    $BIN/v-rebuild-user $user $restart
-done
-
+$BIN/v-rebuild-web-domains $user $restart
+$BIN/v-rebuild-dns-domains $user $restart
+$BIN/v-rebuild-mail-domains $user $restart
+$BIN/v-rebuild-databases $user $restart
+$BIN/v-rebuild-cron-jobs $user $restart
+$BIN/v-rebuild-user $user $restart
 
 #----------------------------------------------------------#
 #                       Hestia                             #

+ 10 - 111
bin/v-restore-user

@@ -30,122 +30,13 @@ fi
 
 # Includes
 source $HESTIA/func/main.sh
+source $HESTIA/func/backup.sh
 source $HESTIA/func/domain.sh
 source $HESTIA/func/ip.sh
 source $HESTIA/func/db.sh
 source $HESTIA/func/rebuild.sh
 source $HESTIA/conf/hestia.conf
 
-# Defining FTP command function
-ftpc() {
-    /usr/bin/ftp -n $HOST $PORT <<EOF
-    quote USER $USERNAME
-    quote PASS $PASSWORD
-    lcd $BACKUP
-    binary
-    $1
-    $2
-    $3
-    quit
-EOF
-}
-
-# FTP backup download function
-ftp_download() {
-    source $HESTIA/conf/ftp.backup.conf
-    if [ -z "$PORT" ]; then
-        PORT='21'
-    fi
-    if [ -z $BPATH ]; then
-        ftpc "get $1"
-    else
-        ftpc "cd $BPATH" "get $1"
-    fi
-}
-
-# SFTP command function
-sftpc() {
-    expect -f "-" <<EOF "$@"
-        set timeout 60
-        set count 0
-        spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
-            -o Port=$PORT $USERNAME@$HOST
-        expect {
-            "password:" {
-                send "$PASSWORD\r"
-                exp_continue
-            }
-
-            -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
-                set count \$argc
-                set output "Disconnected."
-                set rc $E_FTP
-                exp_continue
-            }
-
-            -re ".*denied.*(publickey|password)." {
-                set output "Permission denied, wrong publickey or password."
-                set rc $E_CONNECT
-            }
-
-            -re "\[0-9]*%" {
-                exp_continue
-            }
-
-            "sftp>" {
-                if {\$count < \$argc} {
-                    set arg [lindex \$argv \$count]
-                    send "\$arg\r"
-                    incr count
-                } else {
-                    send "exit\r"
-                    set output "Disconnected."
-                    if {[info exists rc] != 1} {
-                        set rc $OK
-                    }
-                }
-                exp_continue
-            }
-            timeout {
-                set output "Connection timeout."
-                set rc $E_CONNECT
-            }
-        }
-
-        if {[info exists output] == 1} {
-            puts "\$output"
-        }
-
-    exit \$rc
-EOF
-}
-
-# SFTP backup download function
-sftp_download() {
-    source $HESTIA/conf/sftp.backup.conf
-    if [ -z "$PORT" ]; then
-        PORT='22'
-    fi
-    cd $BACKUP
-    if [ -z $BPATH ]; then
-        sftpc "get $1" > /dev/null 2>&1
-    else
-        sftpc "cd $BPATH" "get $1" > /dev/null 2>&1
-    fi
-
-}
-
-# Google backup download function
-google_download() {
-    source $HESTIA/conf/google.backup.conf
-    gsutil="$HESTIA/3rdparty/gsutil/gsutil"
-    export BOTO_CONFIG="$HESTIA/conf/.google.backup.boto"
-    ${gsutil} cp gs://$BUCKET/$BPATH/$1 $BACKUP/ > /dev/null 2>&1
-    if [ "$?" -ne 0 ]; then
-        check_result "$E_CONNECT" "gsutil failed to download $1"
-    fi
-}
-
 
 #----------------------------------------------------------#
 #                    Verifications                         #
@@ -636,7 +527,11 @@ if [ "$mail" != 'no' ] && [ ! -z "$MAIL_SYSTEM" ]; then
             if [ -e "$USER_DATA/ssl/mail.$domain.ca" ]; then
                 cp -f $USER_DATA/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca
             fi
-
+            
+            if [ ! -d  /etc/dovecot/conf.d/domains ]; then
+                mkdir /etc/dovecot/conf.d/domains
+            fi
+            
             # Add domain SSL configuration to dovecot
             if [ -f /etc/dovecot/conf.d/domains/$domain.conf ]; then
                 rm -f /etc/dovecot/conf.d/domains/$domain.conf
@@ -647,6 +542,10 @@ if [ "$mail" != 'no' ] && [ ! -z "$MAIL_SYSTEM" ]; then
             echo "  ssl_cert = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem" >> /etc/dovecot/conf.d/domains/$domain.conf
             echo "  ssl_key = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key" >> /etc/dovecot/conf.d/domains/$domain.conf
             echo "}" >> /etc/dovecot/conf.d/domains/$domain.conf
+            
+            if [ ! -d /usr/local/hestia/ssl/mail ]; then
+                mkdir /usr/local/hestia/ssl/mail
+            fi
 
             # Add domain SSL configuration to exim4
             # Cleanup broken symlinks

+ 421 - 0
func/backup.sh

@@ -0,0 +1,421 @@
+# Local storage
+# Defining local storage function
+local_backup(){
+
+    rm -f $BACKUP/$user.$backup_new_date.tar
+
+    # Checking retention
+    backup_list=$(ls -lrt $BACKUP/ |awk '{print $9}' |grep "^$user\." | grep ".tar")
+    backups_count=$(echo "$backup_list" |wc -l)
+    if [ "$BACKUPS" -le "$backups_count" ]; then
+        backups_rm_number=$((backups_count - BACKUPS + 1))
+
+        # Removing old backup
+        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do
+            backup_date=$(echo $backup |sed -e "s/$user.//" -e "s/.tar$//")
+            echo -e "$(date "+%F %T") Rotated: $backup_date" |\
+                tee -a $BACKUP/$user.log
+            rm -f $BACKUP/$backup
+        done
+    fi
+
+    # Checking disk space
+    disk_usage=$(df $BACKUP |tail -n1 |tr ' ' '\n' |grep % |cut -f 1 -d %)
+    if [ "$disk_usage" -ge "$BACKUP_DISK_LIMIT" ]; then
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        echo "Not enough disk space" |$SENDMAIL -s "$subj" $email $notify
+        check_result "$E_DISK" "Not enough dsk space"
+    fi
+
+    # Creating final tarball
+    cd $tmpdir
+    tar -cf $BACKUP/$user.$backup_new_date.tar .
+    chmod 640 $BACKUP/$user.$backup_new_date.tar
+    chown admin:$user $BACKUP/$user.$backup_new_date.tar
+    localbackup='yes'
+    echo -e "$(date "+%F %T") Local: $BACKUP/$user.$backup_new_date.tar" |\
+        tee -a $BACKUP/$user.log
+}
+
+# FTP Functions 
+# Defining ftp command function
+ftpc() {
+    /usr/bin/ftp -np $HOST $PORT <<EOF
+    quote USER $USERNAME
+    quote PASS $PASSWORD
+    binary
+    $1
+    $2
+    $3
+    quit
+EOF
+}
+
+# Defining ftp storage function
+ftp_backup() {
+    # Checking config
+    if [ ! -e "$HESTIA/conf/ftp.backup.conf" ]; then
+        error="ftp.backup.conf doesn't exist"
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$E_NOTEXIST" "$error"
+    fi
+
+    # Parse config
+    source $HESTIA/conf/ftp.backup.conf
+
+    # Set default port
+    if [ -z "$(grep 'PORT=' $HESTIA/conf/ftp.backup.conf)" ]; then
+        PORT='21'
+    fi
+
+    # Checking variables
+    if [ -z "$HOST" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
+        error="Can't parse ftp backup configuration"
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$E_PARSING" "$error"
+    fi
+
+    # Debug info
+    echo -e "$(date "+%F %T") Remote: ftp://$HOST$BPATH/$user.$backup_new_date.tar"
+
+    # Checking ftp connection
+    fconn=$(ftpc)
+    ferror=$(echo $fconn |grep -i -e failed -e error -e "Can't" -e "not conn")
+    if [ ! -z "$ferror" ]; then
+        error="Error: can't login to ftp ftp://$USERNAME@$HOST"
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$E_CONNECT" "$error"
+    fi
+
+    # Check ftp permissions
+    if [ -z $BPATH ]; then
+            ftmpdir="vst.bK76A9SUkt"
+        else
+            ftpc "mkdir $BPATH" > /dev/null 2>&1
+            ftmpdir="$BPATH/vst.bK76A9SUkt"
+    fi
+    ftpc "mkdir $ftmpdir" "rm $ftmpdir"
+    ftp_result=$(ftpc "mkdir $ftmpdir" "rm $ftmpdir" |grep -v Trying)
+    if [ ! -z "$ftp_result" ] ; then
+        error="Can't create ftp backup folder ftp://$HOST$BPATH"
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$E_FTP" "$error"
+    fi
+
+    # Checking retention
+    if [ -z $BPATH ]; then
+        backup_list=$(ftpc "ls" |awk '{print $9}' |grep "^$user\.")
+    else
+        backup_list=$(ftpc "cd $BPATH" "ls" |awk '{print $9}' |grep "^$user\.")
+    fi
+    backups_count=$(echo "$backup_list" |wc -l)
+    if [ "$backups_count" -ge "$BACKUPS" ]; then
+        backups_rm_number=$((backups_count - BACKUPS + 1))
+        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do 
+            backup_date=$(echo $backup |sed -e "s/$user.//" -e "s/.tar$//")
+            echo -e "$(date "+%F %T") Rotated ftp backup: $backup_date" |\
+                tee -a $BACKUP/$user.log
+            if [ -z $BPATH ]; then
+                ftpc "delete $backup"
+            else
+                ftpc "cd $BPATH" "delete $backup"
+            fi
+        done
+    fi
+
+    # Uploading backup archive
+    if [ "$localbackup" = 'yes' ]; then
+        cd $BACKUP
+        if [ -z $BPATH ]; then
+            ftpc "put $user.$backup_new_date.tar"
+         else
+            ftpc "cd $BPATH" "put $user.$backup_new_date.tar"
+        fi
+    else
+        cd $tmpdir
+        tar -cf $BACKUP/$user.$backup_new_date.tar .
+        cd $BACKUP/
+        if [ -z $BPATH ]; then
+            ftpc "put $user.$backup_new_date.tar"
+        else
+            ftpc "cd $BPATH" "put $user.$backup_new_date.tar"
+        fi
+        rm -f $user.$backup_new_date.tar
+    fi
+}
+
+# FTP backup download function
+ftp_download() {
+    source $HESTIA/conf/ftp.backup.conf
+    if [ -z "$PORT" ]; then
+        PORT='21'
+    fi
+    if [ -z $BPATH ]; then
+        ftpc "get $1"
+    else
+        ftpc "cd $BPATH" "get $1"
+    fi
+}
+
+#FTP Delete function
+ftp_delete() {
+    source $HESTIA/conf/ftp.backup.conf
+    if [ -z "$PORT" ]; then
+        PORT='21'
+    fi
+    if [ -z $BPATH ]; then
+        ftpc "delete $1"
+    else
+        ftpc "cd $BPATH" "delete $1"
+    fi    
+}
+
+
+# SFTP Functions
+# sftp command function
+sftpc() {
+    expect -f "-" <<EOF "$@"
+        set timeout 60
+        set count 0
+        spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
+            -o Port=$PORT $USERNAME@$HOST
+        expect {
+            "password:" {
+                send "$PASSWORD\r"
+                exp_continue
+            }
+
+            -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
+                set count \$argc
+                set output "Disconnected."
+                set rc $E_FTP
+                exp_continue
+            }
+
+            -re ".*denied.*(publickey|password)." {
+                set output "Permission denied, wrong publickey or password."
+                set rc $E_CONNECT
+            }
+
+            -re "\[0-9]*%" {
+                exp_continue
+            }
+
+            "sftp>" {
+                if {\$count < \$argc} {
+                    set arg [lindex \$argv \$count]
+                    send "\$arg\r"
+                    incr count
+                } else {
+                    send "exit\r"
+                    set output "Disconnected."
+                    if {[info exists rc] != 1} {
+                        set rc $OK
+                    }
+                }
+                exp_continue
+            }
+
+            timeout {
+                set output "Connection timeout."
+                set rc $E_CONNECT
+            }
+        }
+
+        if {[info exists output] == 1} {
+            puts "\$output"
+        }
+
+    exit \$rc
+EOF
+}
+
+# SFTP backup download function
+sftp_download() {
+    source $HESTIA/conf/sftp.backup.conf
+    if [ -z "$PORT" ]; then
+        PORT='22'
+    fi
+    cd $BACKUP
+    if [ -z $BPATH ]; then
+        sftpc "get $1" > /dev/null 2>&1
+    else
+        sftpc "cd $BPATH" "get $1" > /dev/null 2>&1
+    fi
+}
+
+sftp_delete() {
+    echo "$1"
+    source $HESTIA/conf/sftp.backup.conf
+    if [ -z "$PORT" ]; then
+        PORT='22'
+    fi
+    echo $BPATH
+    if [ -z $BPATH ]; then
+        sftpc "rm $1" > /dev/null 2>&1
+    else
+        sftpc "cd $BPATH" "rm $1" > /dev/null 2>&1
+    fi
+    
+}
+
+sftp_backup() {
+    # Checking config
+    if [ ! -e "$HESTIA/conf/sftp.backup.conf" ]; then
+        error="Can't open sftp.backup.conf"
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$E_NOTEXIST" "$error"
+    fi
+
+    # Parse config
+    source $HESTIA/conf/sftp.backup.conf
+
+    # Set default port
+    if [ -z "$(grep 'PORT=' $HESTIA/conf/sftp.backup.conf)" ]; then
+        PORT='22'
+    fi
+
+    # Checking variables
+    if [ -z "$HOST" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
+        error="Can't parse sftp backup configuration"
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$E_PARSING" "$error"
+    fi
+
+    # Debug info
+    echo -e "$(date "+%F %T") Remote: sftp://$HOST/$BPATH/$user.$backup_new_date.tar" |\
+        tee -a $BACKUP/$user.log
+
+    # Checking network connection and write permissions
+    if [ -z $BPATH ]; then
+        sftmpdir="vst.bK76A9SUkt"
+    else
+        sftmpdir="$BPATH/vst.bK76A9SUkt"
+    fi
+    sftpc "mkdir $BPATH" > /dev/null 2>&1
+    sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
+    rc=$?
+    if [[ "$rc" != 0 ]]; then
+        case $rc in
+            $E_CONNECT) error="Can't login to sftp host $HOST" ;;
+            $E_FTP) error="Can't create temp folder on sftp $HOST" ;;
+        esac
+        rm -rf $tmpdir
+        rm -f $BACKUP/$user.log
+        echo "$error" |$SENDMAIL -s "$subj" $email $notify
+        sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+        check_result "$rc" "$error"
+    fi
+
+    # Checking retention
+    if [ -z $BPATH ]; then
+        backup_list=$(sftpc "ls -l" |awk '{print $9}'|grep "^$user\.")
+    else
+        backup_list=$(sftpc "cd $BPATH" "ls -l" |awk '{print $9}'|grep "^$user\.")
+    fi
+    backups_count=$(echo "$backup_list" |wc -l)
+    if [ "$backups_count" -ge "$BACKUPS" ]; then
+        backups_rm_number=$((backups_count - BACKUPS + 1))
+        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do
+            backup_date=$(echo $backup |sed -e "s/$user.//" -e "s/.tar.*$//")
+            echo -e "$(date "+%F %T") Rotated sftp backup: $backup_date" |\
+                tee -a $BACKUP/$user.log
+            if [ -z $BPATH ]; then
+                sftpc "rm $backup" > /dev/null 2>&1
+            else
+                sftpc "cd $BPATH" "rm $backup" > /dev/null 2>&1
+            fi
+        done
+    fi
+
+    # Uploading backup archive
+    echo "$(date "+%F %T") Uploading $user.$backup_new_date.tar"|tee -a $BACKUP/$user.log
+    if [ "$localbackup" = 'yes' ]; then
+        cd $BACKUP
+        if [ -z $BPATH ]; then
+            sftpc "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
+        else
+            sftpc "cd $BPATH" "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
+        fi
+    else
+        cd $tmpdir
+        tar -cf $BACKUP/$user.$backup_new_date.tar .
+        cd $BACKUP/
+        if [ -z $BPATH ]; then
+            sftpc "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
+        else
+            sftpc "cd $BPATH" "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
+        fi
+        rm -f $user.$backup_new_date.tar
+    fi
+}
+
+# Google backup download function
+google_backup() {
+
+    # Defining google settings
+    source $HESTIA/conf/google.backup.conf
+    gsutil="$HESTIA/3rdparty/gsutil/gsutil"
+    export BOTO_CONFIG="$HESTIA/conf/.google.backup.boto"
+
+    # Debug info
+    echo -e "$(date "+%F %T") Remote: gs://$BUCKET/$BPATH/$user.$backup_new_date.tar"
+
+    # Checking retention
+    backup_list=$(${gsutil} ls gs://$BUCKET/$BPATH/$user.* 2>/dev/null)
+    backups_count=$(echo "$backup_list" |wc -l)
+    if [ "$backups_count" -ge "$BACKUPS" ]; then
+        backups_rm_number=$((backups_count - BACKUPS))
+        for backup in $(echo "$backup_list" |head -n $backups_rm_number); do 
+            echo -e "$(date "+%F %T") Rotated gcp backup: $backup"
+            $gsutil rm $backup > /dev/null 2>&1
+        done
+    fi
+
+    # Uploading backup archive
+    echo -e "$(date "+%F %T") Uploading $user.$backup_new_date.tar ..."
+    if [ "$localbackup" = 'yes' ]; then
+        cd $BACKUP
+        ${gsutil} cp $user.$backup_new_date.tar gs://$BUCKET/$BPATH/ > /dev/null 2>&1
+    else
+        cd $tmpdir
+        tar -cf $BACKUP/$user.$backup_new_date.tar .
+        cd $BACKUP/
+        ${gsutil} cp $user.$backup_new_date.tar gs://$BUCKET/$BPATH/ > /dev/null 2>&1
+        rc=$?
+        rm -f $user.$backup_new_date.tar
+        if [ "$rc" -ne 0 ]; then
+            check_result "$E_CONNECT" "gsutil failed to upload $user.$backup_new_date.tar"
+        fi
+    fi
+}
+
+google_download() {
+    source $HESTIA/conf/google.backup.conf
+    gsutil="$HESTIA/3rdparty/gsutil/gsutil"
+    export BOTO_CONFIG="$HESTIA/conf/.google.backup.boto"
+    ${gsutil} cp gs://$BUCKET/$BPATH/$1 $BACKUP/ > /dev/null 2>&1
+    if [ "$?" -ne 0 ]; then
+        check_result "$E_CONNECT" "gsutil failed to download $1"
+    fi
+} 

+ 2 - 0
func/db.sh

@@ -28,6 +28,7 @@ database_set_default_ports() {
 
 # MySQL
 mysql_connect() {
+    unset PORT
     host_str=$(grep "HOST='$1'" $HESTIA/conf/mysql.conf)
     parse_object_kv_list "$host_str"
     if [ -z $PORT ]; then PORT=3306; fi
@@ -100,6 +101,7 @@ mysql_dump() {
 
 # PostgreSQL
 psql_connect() {
+    unset PORT
     host_str=$(grep "HOST='$1'" $HESTIA/conf/pgsql.conf)
     parse_object_kv_list "$host_str"
     export PGPASSWORD="$PASSWORD"

+ 8 - 0
func/main.sh

@@ -890,6 +890,13 @@ is_object_format_valid() {
     fi
 }
 
+# Role validator 
+is_role_valid (){
+    if ! [[ "$1" =~ ^admin|user$ ]]; then
+        check_result $E_INVALID "invalid $2 format :: $1"
+    fi
+}
+
 # Password validator
 is_password_format_valid() {
     if [ "${#1}" -lt '6' ]; then
@@ -979,6 +986,7 @@ is_format_valid() {
                 quota)          is_int_format_valid "$arg" 'quota' ;;
                 record)         is_common_format_valid "$arg" 'record';;
                 restart)        is_boolean_format_valid "$arg" 'restart' ;;
+                role)           is_role_valid "$arg" 'role' ;;
                 rtype)          is_dns_type_format_valid "$arg" ;;
                 rule)           is_int_format_valid "$arg" "rule id" ;;
                 service)        is_service_format_valid "$arg" "$arg_name" ;;

+ 3 - 0
func/rebuild.sh

@@ -31,6 +31,9 @@ rebuild_user_conf() {
     if [ -z "${PHPCLI+x}" ]; then 
         sed -i "/QRCODE/a PHPCLI=''" $USER_DATA/user.conf 
     fi
+    if [ -z "${ROLE+x}" ]; then 
+        sed -i "/PHPCLI/a ROLE='user'" $USER_DATA/user.conf 
+    fi
     # Run template trigger
     if [ -x "$HESTIA/data/packages/$PACKAGE.sh" ]; then
         $HESTIA/data/packages/$PACKAGE.sh "$user" "$CONTACT" "$NAME"

+ 1 - 0
install/deb/filemanager/filegator/configuration.php

@@ -38,6 +38,7 @@ $dist_config['services']['Filegator\Services\Storage\Filesystem']['config']['ada
             'privateKey' => '/home/'.basename($v_user).'/.ssh/hst-filemanager-key',
             'root' => '/',
             'timeout' => 10,
+            'directoryPerm' => 0755,
         ]);
     };
 

+ 1 - 1
install/hst-install-debian.sh

@@ -391,7 +391,7 @@ if [ -z "$withdebs" ] || [ ! -d "$withdebs" ]; then
         echo -e "\e[33mhttps://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh\e[0m"
         echo ""
         echo -e "\e[33mTo test pre-release versions, build the .deb packages and re-run the installer:\e[0m"
-        echo -e "  \e[33m./hst_autocompile.sh \e[1m--hestia no\e[21m\e[0m"
+        echo -e "  \e[33m./hst_autocompile.sh \e[1m--hestia branchname no\e[21m\e[0m"
         echo -e "  \e[33m./hst-install.sh .. \e[1m--with-debs /tmp/hestiacp-src/debs\e[21m\e[0m"
         echo ""
         check_result 1 "Installation aborted"

+ 3 - 3
install/hst-install-ubuntu.sh

@@ -46,7 +46,7 @@ software="apache2 apache2.2-common apache2-suexec-custom apache2-utils
     hestia-nginx hestia-php vim-common vsftpd whois zip acl sysstat setpriv
     ipset libonig5 libzip5 openssh-server ssh"
 
-installer_dependencies="apt-transport-https curl dirmngr gnupg wget"
+installer_dependencies="apt-transport-https curl dirmngr gnupg wget software-properties-common"
 
 # Defining help function
 help() {
@@ -366,7 +366,7 @@ if [ -z "$withdebs" ] || [ ! -d "$withdebs" ]; then
         echo -e "\e[33mhttps://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh\e[0m"
         echo ""
         echo -e "\e[33mTo test pre-release versions, build the .deb packages and re-run the installer:\e[0m"
-        echo -e "  \e[33m./hst_autocompile.sh \e[1m--hestia no\e[21m\e[0m"
+        echo -e "  \e[33m./hst_autocompile.sh \e[1m--hestia branchname no\e[21m\e[0m"
         echo -e "  \e[33m./hst-install.sh .. \e[1m--with-debs /tmp/hestiacp-src/debs\e[21m\e[0m"
         echo ""
         check_result 1 "Installation aborted"
@@ -1449,7 +1449,7 @@ if [ "$postgresql" = 'yes' ]; then
     fi
     cp -f $HESTIA_INSTALL_DIR/pga/config.inc.php /etc/phppgadmin/
 
-    echo "DB_PMA_ALIAS='phppgadmin'" >> $HESTIA/conf/hestia.conf
+    echo "DB_PGA_ALIAS='phppgadmin'" >> $HESTIA/conf/hestia.conf
     $HESTIA/bin/v-change-sys-db-alias 'pga' "phppgadmin"
 fi
 

+ 2 - 1
install/upgrade/manual/migrate_mpm_event.sh

@@ -24,7 +24,7 @@ if ! apache2ctl configtest > /dev/null 2>&1; then
     echo "Apache2 configtest failed" && exit 1
 fi
 
-a2modules="php5.6 php7.0 php7.1 php7.2 php7.3 php7.4 mpm_prefork mpm_itk ruid2"
+a2modules="php5.6 php7.0 php7.1 php7.2 php7.3 php7.4 ruid2 mpm_itk mpm_prefork"
 changed_a2modules=""
 
 for module in $a2modules; do
@@ -39,6 +39,7 @@ cp -f /usr/local/hestia/install/deb/apache2/hestia-event.conf /etc/apache2/conf.
 # Check if all went well
 if ! apache2ctl configtest >/dev/null 2>&1; then
     echo "Something went wrong, rolling back. Please try to migrate manually to mpm_event."
+    a2dismod -q mpm_event
     for module in $changed_a2modules; do
         a2enmod "$module"
     done

+ 8 - 0
web/add/user/index.php

@@ -77,6 +77,14 @@ if (!empty($_POST['ok'])) {
         unset($output);
     }
 
+    // Set Role
+    if (empty($_SESSION['error_msg'])) {
+        $v_role = escapeshellarg($_POST['v_role']);
+        exec (HESTIA_CMD."v-change-user-role ".$v_username." ".$v_role, $output, $return_var);
+        check_return_code($return_var,$output);
+        unset($output);
+    }
+
     // Send email to the new user
     if ((empty($_SESSION['error_msg'])) && (!empty($v_notify))) {
         $to = $_POST['v_notify'];

+ 9 - 1
web/edit/user/index.php

@@ -38,6 +38,7 @@ $v_shell = $data[$v_username]['SHELL'];
 $v_twofa = $data[$v_username]['TWOFA'];
 $v_qrcode = $data[$v_username]['QRCODE'];
 $v_phpcli = $data[$v_username]['PHPCLI'];
+$v_role = $data[$v_username]['ROLE'];
 $v_ns = $data[$v_username]['NS'];
 $nameservers = explode(",", $v_ns);
 $v_ns1 = $nameservers[0];
@@ -157,7 +158,14 @@ if (!empty($_POST['save'])) {
         check_return_code($return_var,$output);
         unset($output);
     }
-
+    // Change Role (admin only)
+    if (($v_role != $_POST['$v_role']) && ($_SESSION['user'] == 'admin') && (empty($_SESSION['error_msg']))) {
+        $v_role = escapeshellarg($_POST['v_role']);
+        exec (HESTIA_CMD."v-change-user-role ".escapeshellarg($v_username)." ".$v_role, $output, $return_var);
+        check_return_code($return_var,$output);
+        unset($output);
+        $v_role = $_POST['v_role'];
+    }
     // Change language
     if (($v_language != $_POST['v_language']) && (empty($_SESSION['error_msg']))) {
         $v_language = escapeshellarg($_POST['v_language']);

+ 1 - 1
web/inc/i18n/en.php

@@ -228,7 +228,7 @@ $LANG['en'] = array(
     'STARTTLS'  => 'STARTTLS',
     'Normal password'  => 'Normal Password',
     'database'  => 'Database',
-    'User'  => 'Username',
+    'User'  => 'User',
     'Host'  => 'Hostname',
     'Charset'  => 'Charset',
     'Min'  => 'Minute',

+ 10 - 7
web/login/index.php

@@ -41,8 +41,9 @@ function authenticate_user(){
         if(!empty($_SERVER['HTTP_CF_CONNECTING_IP'])){
             $v_ip = escapeshellarg($_SERVER['HTTP_CF_CONNECTING_IP']);
         }
-    } 
-     // Get user's salt
+    }    
+    
+    // Get user's salt
     $output = '';
     exec (HESTIA_CMD."v-get-user-salt ".$v_user." ".$v_ip." json" , $output, $return_var);
     $pam = json_decode(implode('', $output), true);
@@ -89,14 +90,10 @@ function authenticate_user(){
                 $error = "<a class=\"error\">".__('Invalid username or password')."</a>";
                 return $error;
             } else {
-
-                // Make root admin user
-                if ($_POST['user'] == 'root') $v_user = 'admin';
-
                 // Get user speciefic parameters
                 exec (HESTIA_CMD . "v-list-user ".$v_user." json", $output, $return_var);
                 $data = json_decode(implode('', $output), true);
-
+                unset($output);
                 // Check if 2FA is active
                 if ($data[$_POST['user']]['TWOFA'] != '') {
                    if (empty($_POST['twofa'])){
@@ -113,6 +110,12 @@ function authenticate_user(){
                         }
                    }
                 }
+                
+                if ($data[$_POST['user']]['ROLE'] == 'admin'){
+                    exec (HESTIA_CMD . "v-list-user admin json", $output, $return_var);
+                    $data = json_decode(implode('', $output), true);
+                    unset($output);
+                }
                 // Define session user
                 $_SESSION['user'] = key($data);
                 $v_user = $_SESSION['user'];

+ 2 - 2
web/src/app/WebApp/Installers/WordpressSetup.php

@@ -13,8 +13,8 @@ class WordpressSetup extends BaseSetup {
             //    'type' => 'select',
             //    'options' => ['http','https'],
             //],
-            'site_name' => ['type'=>'text', 'value'=>'Wordpress Blog'],
-            'site_description' => ['value'=>'Another wordpresss site'],
+            'site_name' => ['type'=>'text', 'value'=>'WordPress Blog'],
+            'site_description' => ['value'=>'Another WordPress site'],
             'wordpress_account_username' => ['value'=>'wpadmin'],
             'wordpress_account_email' => 'text',
             'wordpress_account_password' => 'password',

+ 13 - 0
web/templates/admin/add_user.html

@@ -131,6 +131,19 @@
                                     </select>
                                 </td>
                             </tr>
+                            <tr>
+                                <td class="vst-text input-label">
+                                    <?php print __('Role');?>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td>
+                                    <select class="vst-list" name="v_role">
+                                        <option value="user"><?php print __('User');?>
+                                        <option value="admin" <?php if($v_role == "admin" ){ echo "selected"; } ?> ><?php print __('Administrator');?>
+                                    </select>
+                                </td>
+                            </tr>
                             <tr>
                                 <td class="vst-text input-label">
                                     <?php print __('Language');?>

+ 13 - 0
web/templates/admin/edit_user.html

@@ -138,6 +138,19 @@
                                     </select>
                                 </td>
                             </tr>
+                            <tr>
+                                <td class="vst-text input-label">
+                                    <?php print __('Role');?>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td>
+                                    <select class="vst-list" name="v_role">
+                                        <option value="user"><?php print __('User');?>
+                                        <option value="admin" <?php if($v_role == "admin" ){ echo "selected"; } ?> ><?php print __('Administrator');?>
+                                    </select>
+                                </td>
+                            </tr>
                             <tr>
                                 <td class="vst-text input-label">
                                     <?php print __('Language');?>