<?php
/**
 * Observium authorisation plugin to read headers from an authentifying proxy
 *
 * Configuration variables:
 *
 * $config['auth_mechanism'] = "idp";
 *   - Enables this authentication method
 *
 * $config['auth_idp_variable'] = 'REMOTE_USER';
 *   - What server variable contains the username (default: 'REMOTE_USER').
 *
 * $config['auth_idp_groups_variable'] = 'REMOTE_GROUPS';
 *   - What server variable contains the list of groups the user is a member of (default: 'REMOTE_GORUPS').
 *
 * $config['auth_idp_groups_separator'] = ',';
 *   - Character used as a group separator (default: ',').
 *
 * $config['auth_idp_name_variable'] = 'REOMTE_NAME';
 *   - Server variable containing the user's full name (no default).
 *
 * $config['auth_idp_email_variable'] = 'REMOTE_EMAIL';
 *   - Server variable containing the user's email address (no default).
 *
 * $config['auth_idp_logout_url'] = 'http://blah';
 *   - URL to redirect users when they click the logout button. If this is not specified, no logout button
 *     will be available.
 *
 * @copyright  (C) Benjamin Collet
 *
 */

$username_var = isset($config['auth_idp_variable']) ? $config['auth_idp_variable'] : 'REMOTE_USER';

if (isset($_SERVER[$username_var]) && !empty($_SERVER[$username_var])) {
    $idp_username = $_SERVER[$username_var];

    if ($_SESSION['authenticated']) {
        if ($idp_username != $_SESSION['username']) {
            session_logout(FALSE, "idp username changed");
        }
    }

    if (!$_SESSION['authenticated'] && !is_cli()) {
        session_set_var('username', $idp_username);
        session_set_var('authenticated', TRUE);
        dbInsert(['user'       => $_SESSION['username'],
                  'address'    => session_remote_address(),
                  'user_agent' => $_SERVER['HTTP_USER_AGENT'],
                  'result'     => 'Logged In (idp username)'], 'authlog');
    }
}
else {
    header('HTTP/1.1 401 Unauthorized');

    print_error_permission();
    die();
}

/**
 * Check if the backend allows users to log out.
 *
 * @return bool TRUE if logout is possible, FALSE if it is not
 */
function idp_auth_can_logout()
{
    global $config;
    return isset($config['auth_idp_logout_url']);
}

/**
 * Returns the URL to lgoout.
 *
 * @return string logout url
 */
function idp_auth_logout_url()
{
    global $config;
    return isset($config['auth_idp_logout_url']) ? $config['auth_idp_logout_url'] : NULL;
}

/**
 * Check if the backend allows a specific user to change their password.
 * This is not possible using the idp backend.
 *
 * @param string $username Username to check
 *
 * @return bool TRUE if password change is possible, FALSE if it is not
 */
function idp_auth_can_change_password($username = "")
{
    return FALSE;
}

/**
 * Changes a user's password.
 * This is not possible using the idp backend.
 *
 * @param string $username Username to modify the password for
 * @param string $password New password
 *
 * @return bool TRUE if password change is successful, FALSE if it is not
 */
function idp_auth_change_password($username, $newpassword)
{
    # Not supported
    return FALSE;
}

/**
 * Check if the backend allows user management at all (create/delete/modify users).
 * This is not possible using the idp backend.
 *
 * @return bool TRUE if user management is possible, FALSE if it is not
 */
function idp_auth_usermanagement()
{
    return FALSE;
}

/**
 * Check if a user, specified by username, exists in the user backend.
 *
 * @param string $username Username to check
 *
 * @return bool TRUE if the user exists, FALSE if they do not
 */
function idp_auth_user_exists($username)
{
    return dbExist('users', '`username` = ? AND `type` = ?', [$username, 'idp']);
}

/**
 * Find the user's username by specifying their user ID.
 *
 * @param int $user_id The user's ID to look up the username for
 *
 * @return string The user's user name, or FALSE if the user ID is not found
 */
function idp_auth_username_by_id($user_id)
{
    return dbFetchCell("SELECT `username` FROM `users` WHERE `user_id` = ? AND `type` = ?", [$user_id, 'idp']); // FIXME should return FALSE if not found
}

/**
 * Retrieve user auth level for specified user.
 *
 * @param string $username Username to retrieve the auth level for
 *
 * @return int User's auth level
 */
function idp_auth_user_level($username)
{
    global $config, $cache;

    $idp_userlevel = 1;

    if (isset($config['auth_idp_groups'])) {
        if (!isset($cache['idp']['level'][$username])) {
            $groups_var = isset($config['auth_idp_groups_variable']) ? $config['auth_idp_groups_variable'] : 'REMOTE_GROUPS';

            if (isset($_SERVER[$groups_var]) && !empty($_SERVER[$groups_var])) {
                $separator = isset($config['auth_idp_groups_separator']) ? $config['auth_idp_groups_separator'] : ',';
                $idp_groups = explode($separator, $_SERVER[$groups_var]);

                foreach ($idp_groups as $idp_group) {
                    if (isset($config['auth_idp_groups'][$idp_group]) && $config['auth_idp_groups'][$idp_group]['level'] > $idp_userlevel) {
                        $idp_userlevel = intval($config['auth_idp_groups'][$idp_group]['level']);
                    }
                }
            }
            $cache['idp']['level'][$username] = $idp_userlevel;
        } else {
            $idp_userlevel = $cache['idp']['level'][$username];
        }
    }

    if (!idp_auth_user_exists($username)) {
        $user_id = idp_auth_user_id($username);
        create_mysql_user($username, $user_id, $idp_userlevel, 'idp');
    }

    $user_info = idp_auth_user_info($username);

    if (isset($config['auth_idp_name_variable'])) {
        $name_var = $config['auth_idp_name_variable'];
        if (isset($_SERVER[$name_var]) && !empty($_SERVER[$name_var])) {
            $idp_name = $_SERVER[$name_var];
            if ($user_info['realname'] != $idp_name) {
                dbUpdate(['realname' => $idp_name], 'users', '`username` = ? AND `type` = ?', [$username, 'idp']);
            }
        }
    }

    if (isset($config['auth_idp_email_variable'])) {
        $email_var = $config['auth_idp_email_variable'];
        if (isset($_SERVER[$email_var]) && !empty($_SERVER[$email_var])) {
            $idp_email = $_SERVER[$email_var];
            if ($user_info['email'] != $idp_email) {
                dbUpdate(['email' => $idp_email], 'users', '`username` = ? AND `type` = ?', [$username, 'idp']);
            }
        }
    }

    if ($user_info['level'] != $idp_userlevel) {
        dbUpdate(['level' => $idp_userlevel], 'users', '`username` = ? AND `type` = ?', [$username, 'idp']);
    }

    return $idp_userlevel;
}

/**
 * Retrieve user id for specified user.
 * Returns a hash of the username.
 *
 * @param string $username Username to retrieve the ID for
 *
 * @return int User's ID
 */
function idp_auth_user_id($username)
{
    return string_to_id('idp|' . $username);
}

/**
 * Deletes a user from the user database.
 * This is not possible using the idp backend.
 *
 * @param string $username Username to delete
 *
 * @return bool TRUE if user deletion is successful, FALSE if it is not
 */
function idp_deluser($username)
{
    // Not supported
    return FALSE;
}

/**
 * Retrieve list of users with all details.
 * This is not possible using the idp backend.
 *
 * @return array Rows of user data
 */
function idp_auth_user_list()
{
    return dbFetchRows("SELECT * FROM `users` WHERE `type` = ?", ['idp']);
}

/**
 * Get the user information by username
 *
 * @param string $username Username
 *
 * @return string The user's user name, or FALSE if the user ID is not found
 */
function idp_auth_user_info($username)
{
    return dbFetchRow("SELECT * FROM `users` WHERE `username` = ? AND `type` = ?", [$username, 'idp']);
}

// EOF