Skip to content
Snippets Groups Projects
Select Git revision
  • dd9b2ff7a90bddac0e4b92162a6ebf97b77763bc
  • master default protected
  • update-appmonitor
3 results

index.php

Blame
  • user.class.php 9.23 KiB
    <?php
    
    /**
     * user class contains username and its roles
     * This class is used in the base class
     *
     * @author hahn
     * 
     * Axel <axel.hahn@unibe.ch>
     * 2024-08-29  Axel php8 only; added variable types; use short array syntax
     */
    class user
    {
    
        /**
         * login name of the current user
         * @var string
         */
        private string $_sUsername = '';
    
        /**
         * list of groups of the current user
         * @var array
         */
        private array $_aUserGroups = [];
    
        /**
         * list of roles based on the groups
         * @var array
         */
        private array $_aUserPermmissions = [];
    
        /**
         * list of projects the current user is involved in
         * @var array
         */
        private $_aProjects = [];
    
        /**
         * name of the last checked role
         * @var string
         */
        private $_sLastCheckedPermission = false;
    
        /**
         * Constructor
         * init user with optional given user
         * 
         * @param string $sUser  username to set
         */
        public function __construct(string $sUser = '')
        {
            $this->setUser($sUser);
        }
    
    
        // ----------------------------------------------------------------------
        // private functions
        // ----------------------------------------------------------------------
    
    
        /**
         * Get string with detected user from current session / basic auth / cli access
         * 
         * @return string
         */
        private function _autoDetectUser(): string
        {
            $sUser = '';
            if (isset($_SESSION) && isset($_SESSION["PHP_AUTH_USER"])) {
                $sUser = $_SESSION["PHP_AUTH_USER"];
            }
            if (!$sUser && isset($_SERVER["PHP_AUTH_USER"])) {
                $sUser = $_SERVER["PHP_AUTH_USER"];
            }
            if (php_sapi_name() == "cli") {
                $sUser = "cliadmin";
            }
            return $sUser;
        }
    
        /**
         * UNUSED SO FAR
         * Idea: limit user access to a set of projects
         */
        private function _getUser2Projects()
        {
            $sFile = __DIR__ . '/../../../config/inc_user2projects.php';
            return file_exists($sFile)
                ? require $sFile
                : []
            ;
        }
    
        /**
         * Load roles per user from config
         * @return array
         */
        private function _getUser2Roles(): array
        {
            $sFile = __DIR__ . '/../../../config/inc_user2roles.php';
            return file_exists($sFile)
                ? require $sFile
                : ['admin' => ['admin']]
            ;
        }
    
        /**
         * TODO: reimplement
         * get the user groups of the current user from an internal source.
         * The function returns a flat aray with names of the groups
         * @return array
         */
        private function _getUserGroups(): array
        {
            $aGroups = [];
            if ($this->_sUsername) {
                $aGroups[] = "authenticated";
                // $aGroups[]='#'.$this->_sUsername;
                $aUserDefinitions = $this->_getUser2Roles();
                foreach (array_keys($aUserDefinitions) as $sGroup) {
                    if (array_search($this->_sUsername, $aUserDefinitions[$sGroup]) !== false) {
                        $aGroups[] = $sGroup;
                    }
                }
            }
            $this->_aUserGroups = $aGroups;
            return $this->_aUserGroups;
        }
    
        /**
         * TODO: reimplement
         * get the user roles of the current user from an internal source.
         * The function returns a flat aray with names of the roles
         * @return array
         */
        private function _getUserPermission(): array
        {
            $aRoles = [];
            $aRolesDefinitions = require(__DIR__ . '/../../../config/inc_roles.php');
    
            // anonymous roles:
            $aRoles = array_merge($aRoles, $aRolesDefinitions['all']);
    
            foreach (array_keys($aRolesDefinitions) as $sGroup) {
                if ($this->hasGroup($sGroup)) {
                    $aRoles = array_merge($aRoles, $aRolesDefinitions[$sGroup]);
                }
            }
    
            $this->_aUserPermmissions = array_unique($aRoles);
            return $this->_aUserPermmissions;
        }
    
    
        // ----------------------------------------------------------------------
        // public ACTIONS
        // ----------------------------------------------------------------------
    
    
        /**
         * authenticate a user with the configured methods
         * 
         * @global array  $aConfig  global config
         * @global array  $aParams  params (i.e. GET and POST)
         * 
         * @return boolean
         */
        public function authenticate(): bool
        {
            global $aConfig, $aParams;
            if (!isset($aConfig['auth']) || !is_array($aConfig['auth']) || !count($aConfig['auth']) || !isset($aParams['user'])) {
                return false;
            }
            $sUser = $aParams['user'];
            $sPassword = isset($aParams['password']) ? $aParams['password'] : false;
    
            foreach (array_keys($aConfig['auth']) as $sAuthMethod) {
                $oUserAuth = false;
                switch ($sAuthMethod) {
                    case 'ldap':
                        require_once("userauth.ldap.class.php");
                        $oUserAuth = new userauthLdap($aConfig['auth']['ldap']);
                        break;
                    // implement other methods here
                    // see userauth.ldap.class.php as simple example
    
                    default:
                        echo 'WARNING: authmethod ' . $sAuthMethod . ' in your config is not implemented in ' . basename(__FILE__) . ' and is useless so far.<br>';
                }
                // if authentication fails then continue and try next method
                if ($oUserAuth && $oUserAuth->authenticate($sUser, $sPassword)) {
    
                    // set a session - it must correspondent with _autoDetectUser()
                    // $_SESSION["PHP_AUTH_USER"]=$sUser;
                    $this->setUser($sUser);
                    return true;
                }
                // if authentication fails then continue and try next method
                if (!$oUserAuth) {
                    echo "DEBUG: ERROR oUserAuth waasn't initialized for [$sAuthMethod].<br>";
                }
            }
            return false;
        }
    
        /**
         * logoff user
         * @return boolean
         */
        public function logoff(): bool
        {
            unset($_SESSION["PHP_AUTH_USER"]);
            $this->setUser();
            return true;
        }
    
        /**
         * set an authenticated user and get its roles
         * @param string  $sUser  optional: set a given username
         * @return void
         */
        public function setUser(string $sUser = ''): void
        {
            if ($sUser) {
                $this->_sUsername = $sUser;
                $_SESSION["PHP_AUTH_USER"] = $sUser;
            } else {
                // check user from basic auth or cli
                $this->_sUsername = $this->_autoDetectUser();
            }
            $this->_getUserGroups();
            $this->_getUserPermission();
        }
    
        /**
         * Get html code to display a denied message
         * @return string
         */
        public function showDenied(): string
        {
            return '<div class="alert alert-danger" role="alert">'
                . ($this->_sUsername
                    ? t("class-user-error-deny-no-role") . '<br>' . $this->_sUsername . ' --> (' . $this->_sLastCheckedPermission . ')<br>'
                    : t("class-user-error-login-required")
                )
                . '</div><br>'
                . '<a href="/deployment/all/login/" class="btn btn-primary">' . t('menu-login') . '</a>'
            ;
        }
    
        // ----------------------------------------------------------------------
        // public GETTER
        // ----------------------------------------------------------------------
    
    
        /**
         * UNUSED SO FAR
         * Idea: limit user access to a set of projects
         */
        public function getUser2Projects()
        {
            return $this->_getUser2Projects();
        }
    
        /**
         * Get a list of all roles for the current user
         * @return array
         */
        public function getUser2Roles(): array
        {
            return $this->_getUser2Roles();
        }
    
        /**
         * Get the current username
         * @return string
         */
        public function getUsername(): string
        {
            return $this->_sUsername;
        }
    
        /**
         * Get a flat array with roles of the current user
         * @return array
         */
        public function getUserGroups(): array
        {
            return $this->_aUserGroups;
        }
        /**
         * Get a flat array with roles of the current user
         * @return array
         */
        public function getUserPermission(): array
        {
            return $this->_aUserPermmissions;
        }
    
        /**
         * check if the current user has a given role name
         * @param string  $sGroupname  name of the role to check
         * @return bool
         */
        public function hasGroup($sGroupname)
        {
            return !!(array_search($sGroupname, $this->_aUserGroups) !== false);
        }
        /**
         * check if the current user has a given role name
         * @param string  $sPermission  name of the role to check
         * @return boolean
         */
        public function hasPermission($sPermission): bool
        {
            $this->_sLastCheckedPermission = $sPermission;
            $bReturn = !!(array_search($sPermission, $this->_aUserPermmissions) !== false);
            // $this->log(__FUNCTION__ . "($sRolename) -> " . $bReturn ? 'true' : 'false');
            return $bReturn;
        }
    
    }