Skip to content
Snippets Groups Projects
Select Git revision
  • 1cb328ab5a58034d9545d0353843e3aaae210ef3
  • main default
  • SimpleSamlPHP
  • testing
  • test_env
5 results

Model.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    user_visible.inc.php 17.16 KiB
    <?php
    # Lifter002: TODO
    # Lifter007: TODO
    # Lifter003: TEST
    # Lifter010: TODO
    /*
    user_visible.inc.php - Functions for determining a users visibility
    Copyright (C) 2004 Till Glöggler <virtuos@snowysoft.de>
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    */
    
    // Define constants for visibility states.
    define('VISIBILITY_ME', 1);
    define('VISIBILITY_BUDDIES', 2);
    define('VISIBILITY_DOMAIN', 3);
    define('VISIBILITY_STUDIP', 4);
    define('VISIBILITY_EXTERN', 5);
    
    /*
     * A function to determine a users visibility
     *
     * @param   $user_id    user-id
     * @returns boolean true: user is visible, false: user is not visible
     */
    function get_visibility_by_id ($user_id)
    {
        if ($GLOBALS['perm']->have_perm('root')) {
            return true;
        }
    
        $query = "SELECT visible FROM auth_user_md5 WHERE user_id = ?";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([$user_id]);
        $visible = $statement->fetchColumn();
    
        return get_visibility_by_state($visible, $user_id);
    }
    
    /*
     * A function to determine a users visibility
     *
     * @param   $username   username
     * @returns boolean true: user is visible, false: user is not visible
     */
    function get_visibility_by_username($username)
    {
        if ($GLOBALS['perm']->have_perm('root')) {
            return true;
        }
    
        $query = "SELECT visible, user_id FROM auth_user_md5 WHERE username = ?";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([$username]);
        $temp = $statement->fetch(PDO::FETCH_ASSOC);
    
        return get_visibility_by_state($temp['visible'], $temp['user_id']);
    }
    
    /*
     * A function to determine, whether a given state means 'visible' or 'invisible'
     *
     * @param   $stat   ['global', 'always', 'yes', 'unknown', 'no', 'never']
     * @param   $user_id        id of user that should be checked
     * @returns boolean true: state means 'visible', false: state means 'invisible'
     */
    function get_visibility_by_state ($state, $user_id) {
        // Globally visible, no need for futher checks.
        if ($state === 'global') {
            return true;
        }
    
        $same_domain = UserDomain::checkUserVisibility(
            User::find($user_id)->domains,
            User::findCurrent()->domains
        );
    
        switch ($state) {
            case 'yes':
            case 'always':
                return $same_domain;
            case 'unknown':
                return $same_domain && Config::get()->USER_VISIBILITY_UNKNOWN;
        }
    
        return false;
    }
    
    /*
     * This function returns a query-snip for selecting with current visibility rights
     * @returns string  returns a query string
     */
    function get_vis_query($table_alias = 'auth_user_md5', $context = '') {
        global $auth, $perm;
    
        if ($GLOBALS['perm']->have_perm('root')) {
            return '1';
        }
    
        $query = "{$table_alias}.visible = 'global'";
    
        /*
         *  Check if the user has set own visibilities or if the system default
         *  should be used.
         */
        if ($context) {
            $context_default = (int) Config::get()->getValue(mb_strtoupper($context) . '_VISIBILITY_DEFAULT');
            $contextQuery = " AND (IFNULL(user_visibility.{$context}, {$context_default}) = 1
                                   OR {$table_alias}.visible = 'always')";
        } else {
            $contextQuery = '';
        }
    
        $my_domains = UserDomain::getUserDomainsForUser($GLOBALS['user']->id);
        $restricted = count($my_domains) > 0;
    
        $my_domain_ids = [];
        foreach ($my_domains as $domain) {
            if (!$domain->restricted_access) {
                $restricted = false;
            } else {
                $my_domain_ids[] = $domain->id;
            }
        }
    
        if (!$restricted) {
            $query .= " OR (
                        (NOT EXISTS (
                         SELECT *
                         FROM user_userdomains
                         JOIN userdomains USING (userdomain_id)
                         WHERE user_id = {$table_alias}.user_id
                      ) OR EXISTS (
                          SELECT *
                          FROM user_userdomains
                          JOIN userdomains USING (userdomain_id)
                          WHERE user_id = {$table_alias}.user_id
                          AND restricted_access = 0
                      )
                      ";
        }
        if (count($my_domain_ids) > 0) {
            if ($restricted) {
                $query .= " OR ( ( ";
            } else {
                $query .= " OR  ";
            }
            $query .= " EXISTS (SELECT *
                         FROM user_userdomains
                         WHERE user_id = {$table_alias}.user_id
                           AND userdomain_id IN (" . DBManager::get()->quote($my_domain_ids) . ")
                       )
                       )";
        } else {
            $query .= " ) ";
        }
    
    
        $allowed = ['always', 'yes'];
        if (Config::get()->USER_VISIBILITY_UNKNOWN) {
            // users with visibility "unknown" are treated as visible
            $allowed[] = 'unknown';
        }
        $quoted = DBManager::get()->quote($allowed);
        $query .= " AND {$table_alias}.visible IN ({$quoted}) )";
    
        return "($query) $contextQuery";
    }
    
    function get_ext_vis_query($table_alias = 'aum') {
        $allowed = ['global', 'always', 'yes'];
        if (Config::get()->USER_VISIBILITY_UNKNOWN) {
            $allowed[] = 'unknown';
        }
    
        $quoted = DBManager::get()->quote($allowed);
        return "({$table_alias}.visible IN ({$quoted}))";
    }
    
    /*
     * A function to create a chooser for a users visibility
     *
     * @param   $vis    visibility-state
     * @returns string  gives back a string with the chooser
     */
    function vis_chooser($vis, $new = false, $id = false) {
        if ($vis == '') {
            $vis = 'unknown';
        }
        $txt = [];
        $txt[] = sprintf('<select name="visible"%s>', $id ? 'id="' . htmlReady($id) . '"' : '');
        $txt[] = '<option value="global"'.($vis === "global" ? " selected" : "").'>'._("global").'</option>';
        $txt[] = '<option value="always"'.($vis === "always" ? " selected" : "").'>'._("immer").'</option>';
        $txt[] = '<option value="yes"'.($vis === "yes" ? " selected" : "").'>'._("ja").'</option>';
        $txt[] = '<option value="unknown"'.(($new || $vis === "unknown") ? ' selected="selected"':'').'>'._("unbekannt").'</option>';
        $txt[] = '<option value="no"'.($vis === "no" ? " selected" : "").'>'._("nein").'</option>';
        $txt[] = '<option value="never"'.($vis === "never" ? " selected" : "").'>'._("niemals").'</option>';
        $txt[] = '</select>';
        return implode("\n", $txt);
    }
    
    // Ask user with unknown visibility state directly after login
    // whether they want to be visible or invisible
    //
    // ATTENTION: NOT USED IN STANDARD DISTRIBUTION.
    // see header.php for further info on enabling this feature.
    //
    // DON'T USE UNMODIFIED TEXTS!
    //
    function first_decision($userid) {
        $vis_cmd = Request::option('vis_cmd');
        $vis_state = Request::option('vis_state');
        $user_language = getUserLanguagePath($userid);
    
        if ($vis_cmd == "apply" && ($vis_state == "global" || $vis_state == "yes" || $vis_state == "no")) {
            $query = "UPDATE auth_user_md5 SET visible = ? WHERE user_id = ?";
            $statement = DBManager::get()->prepare($query);
            $statement->execute([$vis_state, $userid]);
            return;
        }
    
        $query = "SELECT visible FROM auth_user_md5 WHERE user_id = ?";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([$userid]);
        $visiblity = $statement->fetchColumn();
    
        if ($visiblity != 'unknown') {
            return;
        }
    
        PageLayout::setTitle(_('Bitte wählen Sie Ihren Sichtbarkeitsstatus aus!'));
        PageLayout::setTabNavigation(NULL);
    
        // avoid recursion when loading the header
        Config::get()->USER_VISIBILITY_CHECK = false;
    
        $template = $GLOBALS['template_factory']->open("../locale/$user_language/LC_HELP/visibility_decision.php");
        $template->set_layout('layouts/base.php');
    
        echo $template->render();
        page_close();
        die;
    }
    
    
    /**
     * Gets a user's visibility settings for special context. Valid contexts are
     * at the moment:
     * <ul>
     * <li><b>online</b>: Visibility in "Who is online" list</li>
     * <li><b>search</b>: Can the user be found via person search?</li>
     * <li><b>email</b>: Is user's email address shown?</li>
     * <li><b>homepage</b>: Visibility of all user homepage elements, stored as
     * JSON-serialized array</li>
     * </ul>
     *
     * @param string $user_id user ID to check
     * @param string $context local visibility in which context?
     * @param boolean $return_user_perm return not only visibility, but also
     * the user's global permission level
     * @return mixed Visibility flag or array with visibility and user permission
     * level.
     */
    function get_local_visibility_by_id($user_id, $context, $return_user_perm=false) {
        global $NOT_HIDEABLE_FIELDS;
    
        $user = User::find($user_id);
    
        if (Visibility::allowExtendedSettings($user)) {
            $query = "SELECT u.`{$context}`
                      FROM auth_user_md5 AS a
                      LEFT JOIN user_visibility AS u USING (user_id)
                      WHERE user_id = ?";
            $statement = DBManager::get()->prepare($query);
            $statement->execute([$user_id]);
            $data = $statement->fetch(PDO::FETCH_ASSOC);
        } else {
            $data = [];
        }
    
        if ($context === 'homepage') {
            $homepage_settings = [];
    
            $settings = User_Visibility_Settings::findByUser_id($user_id);
            foreach ($settings as $setting) {
                if ($setting['category'] == 1) {
                    $homepage_settings[$setting['identifier']] = $setting['state'];
                }
            }
    
            if ($homepage_settings) {
                $data[$context] = json_encode($homepage_settings);
            }
        }
    
        if (!isset($data[$context])) {
            $data[$context] = Config::get()->getValue(mb_strtoupper($context) . '_VISIBILITY_DEFAULT');
        }
    
        if (!isset($data[$context])) {
            // No valid context given.
            $result = false;
        } elseif (!Visibility::isFieldHideableForUser($context, $user)) {
            // Context may not be hidden per global config setting.
            $result = true;
        } elseif ($return_user_perm) {
            // Give also user's permission level.
            $result = [
                'perms' => $user->perms,
                $context => $data[$context]
            ];
        } else {
            // Valid context given.
            $result = $data[$context];
        }
    
        return $result;
    }
    
    
    /**
     * Checks whether an element of a user homepage is visible for another user.
     * We do not give an element name and look up its visibility setting in the
     * database, because that would generate many database requests for a single
     * user homepage. Instead, the homepage itself loads all element visibilities
     * and we only need to check if the given element visibility allows showing it
     * to the visiting user. We need not check for not hideable fields here,
     * because that is already done when loading the element visibilities.
     *
     * @param string $user_id ID of the user who wants to see the element
     * @param string $owner_id ID of the homepage owner
     * @param int $element_visibility visibility level of the element, one of
     * the constants VISIBILITY_ME, VISIBILITY_BUDDIES, VISIBILITY_DOMAIN,
     * VISIBILITY_STUDIP, VISIBILITY_EXTERN
     * @return boolean Is the element visible?
     */
    function is_element_visible_for_user($user_id, $owner_id, $element_visibility) {
        $is_visible = false;
        if ($user_id == $owner_id) {
            $is_visible = true;
        // Deputies with homepage editing rights see the same as the owner
        } else if (Config::get()->DEPUTIES_ENABLE && Config::get()->DEPUTIES_DEFAULTENTRY_ENABLE && Config::get()->DEPUTIES_EDIT_ABOUT_ENABLE && Deputy::isDeputy($user_id, $owner_id, true)) {
            $is_visible = true;
        } else {
            // No element visibility given (user has not configured this element yet)
            // Set default visibility as element visibility
            if (!$element_visibility) {
                $element_visibility = get_default_homepage_visibility($owner_id);
            }
            // Check if the given element is visible according to its visibility.
            switch ($element_visibility) {
                case VISIBILITY_EXTERN:
                    $is_visible = true;
                    break;
                case VISIBILITY_STUDIP:
                    if ($user_id != "nobody") {
                        $is_visible = true;
                    }
                    break;
                case VISIBILITY_DOMAIN:
                    $user_domains = UserDomain::getUserDomainsForUser($user_id);
                    $owner_domains = UserDomain::getUserDomainsForUser($owner_id);
                    if ((count($user_domains) === 0 && count($owner_domains) === 0)
                        || array_intersect($user_domains, $owner_domains)) {
                        $is_visible = true;
                    }
                    break;
                case VISIBILITY_BUDDIES:
                    if (Contact::CountBySQL("user_id=? AND owner_id=?", [$user_id, $owner_id])) {
                        $is_visible = true;
                    }
                    break;
                case VISIBILITY_ME:
                    if ($owner_id == $user_id) {
                        $is_visible = true;
                    }
                    break;
            }
        }
        return $is_visible;
    }
    
    /**
     * Checks whether a homepage element is visible on external pages.
     * We do not give an element name and look up its visibility setting in the
     * database, because that would generate many database requests for a single
     * user homepage. Instead, the homepage itself loads all element visibilities
     * and we only need to check if the given element visibility allows showing it.
     *
     * @param string $owner_id user ID of the homepage owner
     * @param string $owner_perm permission level of the homepage owner, needed
     * because every permission level can have its own not hideable fields.
     * @param string $field_name Name of the homepage field to check, needed for
     * checking if the element is not hideable
     * @param int $element_visibility visibility level of the element, one of
     * the constants VISIBILITY_ME, VISIBILITY_BUDDIES, VISIBILITY_DOMAIN,
     * VISIBILITY_STUDIP, VISIBILITY_EXTERN
     * @return boolean May the element be shown on external pages?
     */
    function is_element_visible_externally($owner_id, $owner_perm, $field_name, $element_visibility) {
        global $NOT_HIDEABLE_FIELDS;
        $is_visible = false;
        if (!isset($element_visibility)) {
            $element_visibility = get_default_homepage_visibility($owner_id);
        }
        if ($element_visibility == VISIBILITY_EXTERN || $NOT_HIDEABLE_FIELDS[$owner_perm][$field_name])
            $is_visible = true;
        return $is_visible;
    }
    
    /**
     * Retrieves the standard visibility level for a homepage element if the user
     * hasn't specified anything explicitly. This default can be set via the global
     * configuration (variable "HOMEPAGE_VISIBILITY_DEFAULT").
     *
     * @return int Default visibility level.
     */
    function get_default_homepage_visibility($user_id)
    {
        $query = "SELECT default_homepage_visibility FROM user_visibility WHERE user_id = ?";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([$user_id]);
        $visibility = $statement->fetchColumn();
    
        if (intval($visibility) != 0) {
            $result = $visibility;
        } else {
            $result = @constant(Config::get()->HOMEPAGE_VISIBILITY_DEFAULT);
            if (!$result) {
                $result = VISIBILITY_STUDIP;
            }
        }
        return $result;
    }
    
    /**
     * Gets a user's email address. If the address should not be shown according
     * to the user's privacy settings, we try to get the email address of the
     * default institute (this can be one of the institutes the user is assigned
     * to). If no default institute is found, the email address of the first found
     * institute is given. If the user isn't assigned to any institute, an empty
     * string is returned.
     *
     * @param string $user_id which user's email address is required?
     * @return string User email address or email address of the user's default
     * institute or empty string.
     */
    function get_visible_email($user_id) {
        $result = '';
        // Email address is visible -> just show user's address.
        if (get_local_visibility_by_id($user_id, 'email')) {
            $query = "SELECT Email FROM auth_user_md5 WHERE user_id = ?";
            $statement = DBManager::get()->prepare($query);
            $statement->execute([$user_id]);
            $result = $statement->fetchColumn();
        // User's email is not visible
        } else if ($GLOBALS['perm']->get_perm($user_id) == 'dozent') {
            // bei Lehrenden eine Institutsadresse verwenden
            $query = "SELECT i.email, u.externdefault
                      FROM user_inst AS u
                      JOIN Institute AS i USING (Institut_id)
                      WHERE u.user_id = ? AND u.inst_perms != 'user'
                      ORDER BY u.priority";
            $statement = DBManager::get()->prepare($query);
            $statement->execute([$user_id]);
    
            while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
                if (!$result || $row['externdefault']) {
                    $result = $row['email'];
                }
            }
        }
        return $result;
    }