Example #1
0
    $PAGE->set_other_editing_capability('moodle/course:activityvisibility');

    // Prevent caching of this page to stop confusion when changing page after making AJAX changes
    $PAGE->set_cacheable(false);

    if ($CFG->forcelogin) {
        require_login();
    } else {
        user_accesstime_log();
    }

    $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));

/// If the site is currently under maintenance, then print a message
    if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
        print_maintenance_message();
    }

    if ($hassiteconfig && moodle_needs_upgrading()) {
        redirect($CFG->wwwroot .'/'. $CFG->admin .'/index.php');
    }

    if (get_home_page() != HOMEPAGE_SITE) {
        // Redirect logged-in users to My Moodle overview if required
        if (optional_param('setdefaulthome', false, PARAM_BOOL)) {
            set_user_preference('user_home_page_preference', HOMEPAGE_SITE);
        } else if (!empty($CFG->defaulthomepage) && ($CFG->defaulthomepage == HOMEPAGE_MY) && optional_param('redirect', 1, PARAM_BOOL) === 1) {
            redirect($CFG->wwwroot .'/my/');
        } else if (!empty($CFG->defaulthomepage) && ($CFG->defaulthomepage == HOMEPAGE_USER)) {
            $PAGE->settingsnav->get('usercurrentsettings')->add(get_string('makethismyhome'), new moodle_url('/', array('setdefaulthome'=>true)), navigation_node::TYPE_SETTING);
        }
Example #2
0
/**
 * This function checks that the current user is logged in and has the
 * required privileges
 *
 * This function checks that the current user is logged in, and optionally
 * whether they are allowed to be in a particular course and view a particular
 * course module.
 * If they are not logged in, then it redirects them to the site login unless
 * $autologinguest is set and {@link $CFG}->autologinguests is set to 1 in which
 * case they are automatically logged in as guests.
 * If $courseid is given and the user is not enrolled in that course then the
 * user is redirected to the course enrolment page.
 * If $cm is given and the course module is hidden and the user is not a teacher
 * in the course then the user is redirected to the course home page.
 *
 * When $cm parameter specified, this function sets page layout to 'module'.
 * You need to change it manually later if some other layout needed.
 *
 * @package    core_access
 * @category   access
 *
 * @param mixed $courseorid id of the course or course object
 * @param bool $autologinguest default true
 * @param object $cm course module object
 * @param bool $setwantsurltome Define if we want to set $SESSION->wantsurl, defaults to
 *             true. Used to avoid (=false) some scripts (file.php...) to set that variable,
 *             in order to keep redirects working properly. MDL-14495
 * @param bool $preventredirect set to true in scripts that can not redirect (CLI, rss feeds, etc.), throws exceptions
 * @return mixed Void, exit, and die depending on path
 * @throws coding_exception
 * @throws require_login_exception
 */
function require_login($courseorid = null, $autologinguest = true, $cm = null, $setwantsurltome = true, $preventredirect = false)
{
    global $CFG, $SESSION, $USER, $PAGE, $SITE, $DB, $OUTPUT;
    // Must not redirect when byteserving already started.
    if (!empty($_SERVER['HTTP_RANGE'])) {
        $preventredirect = true;
    }
    if (AJAX_SCRIPT) {
        // We cannot redirect for AJAX scripts either.
        $preventredirect = true;
    }
    // Setup global $COURSE, themes, language and locale.
    if (!empty($courseorid)) {
        if (is_object($courseorid)) {
            $course = $courseorid;
        } else {
            if ($courseorid == SITEID) {
                $course = clone $SITE;
            } else {
                $course = $DB->get_record('course', array('id' => $courseorid), '*', MUST_EXIST);
            }
        }
        if ($cm) {
            if ($cm->course != $course->id) {
                throw new coding_exception('course and cm parameters in require_login() call do not match!!');
            }
            // Make sure we have a $cm from get_fast_modinfo as this contains activity access details.
            if (!$cm instanceof cm_info) {
                // Note: nearly all pages call get_fast_modinfo anyway and it does not make any
                // db queries so this is not really a performance concern, however it is obviously
                // better if you use get_fast_modinfo to get the cm before calling this.
                $modinfo = get_fast_modinfo($course);
                $cm = $modinfo->get_cm($cm->id);
            }
        }
    } else {
        // Do not touch global $COURSE via $PAGE->set_course(),
        // the reasons is we need to be able to call require_login() at any time!!
        $course = $SITE;
        if ($cm) {
            throw new coding_exception('cm parameter in require_login() requires valid course parameter!');
        }
    }
    // If this is an AJAX request and $setwantsurltome is true then we need to override it and set it to false.
    // Otherwise the AJAX request URL will be set to $SESSION->wantsurl and events such as self enrolment in the future
    // risk leading the user back to the AJAX request URL.
    if ($setwantsurltome && defined('AJAX_SCRIPT') && AJAX_SCRIPT) {
        $setwantsurltome = false;
    }
    // Redirect to the login page if session has expired, only with dbsessions enabled (MDL-35029) to maintain current behaviour.
    if ((!isloggedin() or isguestuser()) && !empty($SESSION->has_timed_out) && !empty($CFG->dbsessions)) {
        if ($preventredirect) {
            throw new require_login_session_timeout_exception();
        } else {
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            redirect(get_login_url());
        }
    }
    // If the user is not even logged in yet then make sure they are.
    if (!isloggedin()) {
        if ($autologinguest and !empty($CFG->guestloginbutton) and !empty($CFG->autologinguests)) {
            if (!($guest = get_complete_user_data('id', $CFG->siteguest))) {
                // Misconfigured site guest, just redirect to login page.
                redirect(get_login_url());
                exit;
                // Never reached.
            }
            $lang = isset($SESSION->lang) ? $SESSION->lang : $CFG->lang;
            complete_user_login($guest);
            $USER->autologinguest = true;
            $SESSION->lang = $lang;
        } else {
            // NOTE: $USER->site check was obsoleted by session test cookie, $USER->confirmed test is in login/index.php.
            if ($preventredirect) {
                throw new require_login_exception('You are not logged in');
            }
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            $referer = get_local_referer(false);
            if (!empty($referer)) {
                $SESSION->fromurl = $referer;
            }
            // Give auth plugins an opportunity to authenticate or redirect to an external login page
            $authsequence = get_enabled_auth_plugins(true);
            // auths, in sequence
            foreach ($authsequence as $authname) {
                $authplugin = get_auth_plugin($authname);
                $authplugin->pre_loginpage_hook();
                if (isloggedin()) {
                    break;
                }
            }
            // If we're still not logged in then go to the login page
            if (!isloggedin()) {
                redirect(get_login_url());
                exit;
                // Never reached.
            }
        }
    }
    // Loginas as redirection if needed.
    if ($course->id != SITEID and \core\session\manager::is_loggedinas()) {
        if ($USER->loginascontext->contextlevel == CONTEXT_COURSE) {
            if ($USER->loginascontext->instanceid != $course->id) {
                print_error('loginasonecourse', '', $CFG->wwwroot . '/course/view.php?id=' . $USER->loginascontext->instanceid);
            }
        }
    }
    // Check whether the user should be changing password (but only if it is REALLY them).
    if (get_user_preferences('auth_forcepasswordchange') && !\core\session\manager::is_loggedinas()) {
        $userauth = get_auth_plugin($USER->auth);
        if ($userauth->can_change_password() and !$preventredirect) {
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            if ($changeurl = $userauth->change_password_url()) {
                // Use plugin custom url.
                redirect($changeurl);
            } else {
                // Use moodle internal method.
                if (empty($CFG->loginhttps)) {
                    redirect($CFG->wwwroot . '/login/change_password.php');
                } else {
                    $wwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
                    redirect($wwwroot . '/login/change_password.php');
                }
            }
        } else {
            if ($userauth->can_change_password()) {
                throw new moodle_exception('forcepasswordchangenotice');
            } else {
                throw new moodle_exception('nopasswordchangeforced', 'auth');
            }
        }
    }
    // Check that the user account is properly set up. If we can't redirect to
    // edit their profile, perform just the lax check. It will allow them to
    // use filepicker on the profile edit page.
    if ($preventredirect) {
        $usernotfullysetup = user_not_fully_set_up($USER, false);
    } else {
        $usernotfullysetup = user_not_fully_set_up($USER, true);
    }
    if ($usernotfullysetup) {
        if ($preventredirect) {
            throw new moodle_exception('usernotfullysetup');
        }
        if ($setwantsurltome) {
            $SESSION->wantsurl = qualified_me();
        }
        redirect($CFG->wwwroot . '/user/edit.php?id=' . $USER->id . '&course=' . SITEID);
    }
    // Make sure the USER has a sesskey set up. Used for CSRF protection.
    sesskey();
    // Do not bother admins with any formalities.
    if (is_siteadmin()) {
        // Set the global $COURSE.
        if ($cm) {
            $PAGE->set_cm($cm, $course);
            $PAGE->set_pagelayout('incourse');
        } else {
            if (!empty($courseorid)) {
                $PAGE->set_course($course);
            }
        }
        // Set accesstime or the user will appear offline which messes up messaging.
        user_accesstime_log($course->id);
        return;
    }
    // Check that the user has agreed to a site policy if there is one - do not test in case of admins.
    if (!$USER->policyagreed and !is_siteadmin()) {
        if (!empty($CFG->sitepolicy) and !isguestuser()) {
            if ($preventredirect) {
                throw new moodle_exception('sitepolicynotagreed', 'error', '', $CFG->sitepolicy);
            }
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            redirect($CFG->wwwroot . '/user/policy.php');
        } else {
            if (!empty($CFG->sitepolicyguest) and isguestuser()) {
                if ($preventredirect) {
                    throw new moodle_exception('sitepolicynotagreed', 'error', '', $CFG->sitepolicyguest);
                }
                if ($setwantsurltome) {
                    $SESSION->wantsurl = qualified_me();
                }
                redirect($CFG->wwwroot . '/user/policy.php');
            }
        }
    }
    // Fetch the system context, the course context, and prefetch its child contexts.
    $sysctx = context_system::instance();
    $coursecontext = context_course::instance($course->id, MUST_EXIST);
    if ($cm) {
        $cmcontext = context_module::instance($cm->id, MUST_EXIST);
    } else {
        $cmcontext = null;
    }
    // If the site is currently under maintenance, then print a message.
    if (!empty($CFG->maintenance_enabled) and !has_capability('moodle/site:maintenanceaccess', $sysctx)) {
        if ($preventredirect) {
            throw new require_login_exception('Maintenance in progress');
        }
        $PAGE->set_context(null);
        print_maintenance_message();
    }
    // Make sure the course itself is not hidden.
    if ($course->id == SITEID) {
        // Frontpage can not be hidden.
    } else {
        if (is_role_switched($course->id)) {
            // When switching roles ignore the hidden flag - user had to be in course to do the switch.
        } else {
            if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
                // Originally there was also test of parent category visibility, BUT is was very slow in complex queries
                // involving "my courses" now it is also possible to simply hide all courses user is not enrolled in :-).
                if ($preventredirect) {
                    throw new require_login_exception('Course is hidden');
                }
                $PAGE->set_context(null);
                // We need to override the navigation URL as the course won't have been added to the navigation and thus
                // the navigation will mess up when trying to find it.
                navigation_node::override_active_url(new moodle_url('/'));
                notice(get_string('coursehidden'), $CFG->wwwroot . '/');
            }
        }
    }
    // Is the user enrolled?
    if ($course->id == SITEID) {
        // Everybody is enrolled on the frontpage.
    } else {
        if (\core\session\manager::is_loggedinas()) {
            // Make sure the REAL person can access this course first.
            $realuser = \core\session\manager::get_realuser();
            if (!is_enrolled($coursecontext, $realuser->id, '', true) and !is_viewing($coursecontext, $realuser->id) and !is_siteadmin($realuser->id)) {
                if ($preventredirect) {
                    throw new require_login_exception('Invalid course login-as access');
                }
                $PAGE->set_context(null);
                echo $OUTPUT->header();
                notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot . '/');
            }
        }
        $access = false;
        if (is_role_switched($course->id)) {
            // Ok, user had to be inside this course before the switch.
            $access = true;
        } else {
            if (is_viewing($coursecontext, $USER)) {
                // Ok, no need to mess with enrol.
                $access = true;
            } else {
                if (isset($USER->enrol['enrolled'][$course->id])) {
                    if ($USER->enrol['enrolled'][$course->id] > time()) {
                        $access = true;
                        if (isset($USER->enrol['tempguest'][$course->id])) {
                            unset($USER->enrol['tempguest'][$course->id]);
                            remove_temp_course_roles($coursecontext);
                        }
                    } else {
                        // Expired.
                        unset($USER->enrol['enrolled'][$course->id]);
                    }
                }
                if (isset($USER->enrol['tempguest'][$course->id])) {
                    if ($USER->enrol['tempguest'][$course->id] == 0) {
                        $access = true;
                    } else {
                        if ($USER->enrol['tempguest'][$course->id] > time()) {
                            $access = true;
                        } else {
                            // Expired.
                            unset($USER->enrol['tempguest'][$course->id]);
                            remove_temp_course_roles($coursecontext);
                        }
                    }
                }
                if (!$access) {
                    // Cache not ok.
                    $until = enrol_get_enrolment_end($coursecontext->instanceid, $USER->id);
                    if ($until !== false) {
                        // Active participants may always access, a timestamp in the future, 0 (always) or false.
                        if ($until == 0) {
                            $until = ENROL_MAX_TIMESTAMP;
                        }
                        $USER->enrol['enrolled'][$course->id] = $until;
                        $access = true;
                    } else {
                        $params = array('courseid' => $course->id, 'status' => ENROL_INSTANCE_ENABLED);
                        $instances = $DB->get_records('enrol', $params, 'sortorder, id ASC');
                        $enrols = enrol_get_plugins(true);
                        // First ask all enabled enrol instances in course if they want to auto enrol user.
                        foreach ($instances as $instance) {
                            if (!isset($enrols[$instance->enrol])) {
                                continue;
                            }
                            // Get a duration for the enrolment, a timestamp in the future, 0 (always) or false.
                            $until = $enrols[$instance->enrol]->try_autoenrol($instance);
                            if ($until !== false) {
                                if ($until == 0) {
                                    $until = ENROL_MAX_TIMESTAMP;
                                }
                                $USER->enrol['enrolled'][$course->id] = $until;
                                $access = true;
                                break;
                            }
                        }
                        // If not enrolled yet try to gain temporary guest access.
                        if (!$access) {
                            foreach ($instances as $instance) {
                                if (!isset($enrols[$instance->enrol])) {
                                    continue;
                                }
                                // Get a duration for the guest access, a timestamp in the future or false.
                                $until = $enrols[$instance->enrol]->try_guestaccess($instance);
                                if ($until !== false and $until > time()) {
                                    $USER->enrol['tempguest'][$course->id] = $until;
                                    $access = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        if (!$access) {
            if ($preventredirect) {
                throw new require_login_exception('Not enrolled');
            }
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            redirect($CFG->wwwroot . '/enrol/index.php?id=' . $course->id);
        }
    }
    // Check visibility of activity to current user; includes visible flag, conditional availability, etc.
    if ($cm && !$cm->uservisible) {
        if ($preventredirect) {
            throw new require_login_exception('Activity is hidden');
        }
        if ($course->id != SITEID) {
            $url = new moodle_url('/course/view.php', array('id' => $course->id));
        } else {
            $url = new moodle_url('/');
        }
        redirect($url, get_string('activityiscurrentlyhidden'));
    }
    // Set the global $COURSE.
    if ($cm) {
        $PAGE->set_cm($cm, $course);
        $PAGE->set_pagelayout('incourse');
    } else {
        if (!empty($courseorid)) {
            $PAGE->set_course($course);
        }
    }
    // Finally access granted, update lastaccess times.
    user_accesstime_log($course->id);
}
Example #3
0
/**
 * This function checks that the current user is logged in and has the
 * required privileges
 *
 * This function checks that the current user is logged in, and optionally
 * whether they are allowed to be in a particular course and view a particular
 * course module.
 * If they are not logged in, then it redirects them to the site login unless
 * $autologinguest is set and {@link $CFG}->autologinguests is set to 1 in which
 * case they are automatically logged in as guests.
 * If $courseid is given and the user is not enrolled in that course then the
 * user is redirected to the course enrolment page.
 * If $cm is given and the course module is hidden and the user is not a teacher
 * in the course then the user is redirected to the course home page.
 *
 * When $cm parameter specified, this function sets page layout to 'module'.
 * You need to change it manually later if some other layout needed.
 *
 * @param mixed $courseorid id of the course or course object
 * @param bool $autologinguest default true
 * @param object $cm course module object
 * @param bool $setwantsurltome Define if we want to set $SESSION->wantsurl, defaults to
 *             true. Used to avoid (=false) some scripts (file.php...) to set that variable,
 *             in order to keep redirects working properly. MDL-14495
 * @param bool $preventredirect set to true in scripts that can not redirect (CLI, rss feeds, etc.), throws exceptions
 * @return mixed Void, exit, and die depending on path
 */
function require_login($courseorid = NULL, $autologinguest = true, $cm = NULL, $setwantsurltome = true, $preventredirect = false)
{
    global $CFG, $SESSION, $USER, $FULLME, $PAGE, $SITE, $DB, $OUTPUT;
    // setup global $COURSE, themes, language and locale
    if (!empty($courseorid)) {
        if (is_object($courseorid)) {
            $course = $courseorid;
        } else {
            if ($courseorid == SITEID) {
                $course = clone $SITE;
            } else {
                $course = $DB->get_record('course', array('id' => $courseorid), '*', MUST_EXIST);
            }
        }
        if ($cm) {
            if ($cm->course != $course->id) {
                throw new coding_exception('course and cm parameters in require_login() call do not match!!');
            }
            // make sure we have a $cm from get_fast_modinfo as this contains activity access details
            if (!$cm instanceof cm_info) {
                // note: nearly all pages call get_fast_modinfo anyway and it does not make any
                // db queries so this is not really a performance concern, however it is obviously
                // better if you use get_fast_modinfo to get the cm before calling this.
                $modinfo = get_fast_modinfo($course);
                $cm = $modinfo->get_cm($cm->id);
            }
            $PAGE->set_cm($cm, $course);
            // set's up global $COURSE
            $PAGE->set_pagelayout('incourse');
        } else {
            $PAGE->set_course($course);
            // set's up global $COURSE
        }
    } else {
        // do not touch global $COURSE via $PAGE->set_course(),
        // the reasons is we need to be able to call require_login() at any time!!
        $course = $SITE;
        if ($cm) {
            throw new coding_exception('cm parameter in require_login() requires valid course parameter!');
        }
    }
    // If the user is not even logged in yet then make sure they are
    if (!isloggedin()) {
        if ($autologinguest and !empty($CFG->guestloginbutton) and !empty($CFG->autologinguests)) {
            if (!($guest = get_complete_user_data('id', $CFG->siteguest))) {
                // misconfigured site guest, just redirect to login page
                redirect(get_login_url());
                exit;
                // never reached
            }
            $lang = isset($SESSION->lang) ? $SESSION->lang : $CFG->lang;
            complete_user_login($guest, false);
            $USER->autologinguest = true;
            $SESSION->lang = $lang;
        } else {
            //NOTE: $USER->site check was obsoleted by session test cookie,
            //      $USER->confirmed test is in login/index.php
            if ($preventredirect) {
                throw new require_login_exception('You are not logged in');
            }
            if ($setwantsurltome) {
                // TODO: switch to PAGE->url
                $SESSION->wantsurl = $FULLME;
            }
            if (!empty($_SERVER['HTTP_REFERER'])) {
                $SESSION->fromurl = $_SERVER['HTTP_REFERER'];
            }
            redirect(get_login_url());
            exit;
            // never reached
        }
    }
    // loginas as redirection if needed
    if ($course->id != SITEID and session_is_loggedinas()) {
        if ($USER->loginascontext->contextlevel == CONTEXT_COURSE) {
            if ($USER->loginascontext->instanceid != $course->id) {
                print_error('loginasonecourse', '', $CFG->wwwroot . '/course/view.php?id=' . $USER->loginascontext->instanceid);
            }
        }
    }
    // check whether the user should be changing password (but only if it is REALLY them)
    if (get_user_preferences('auth_forcepasswordchange') && !session_is_loggedinas()) {
        $userauth = get_auth_plugin($USER->auth);
        if ($userauth->can_change_password() and !$preventredirect) {
            $SESSION->wantsurl = $FULLME;
            if ($changeurl = $userauth->change_password_url()) {
                //use plugin custom url
                redirect($changeurl);
            } else {
                //use moodle internal method
                if (empty($CFG->loginhttps)) {
                    redirect($CFG->wwwroot . '/login/change_password.php');
                } else {
                    $wwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
                    redirect($wwwroot . '/login/change_password.php');
                }
            }
        } else {
            print_error('nopasswordchangeforced', 'auth');
        }
    }
    // Check that the user account is properly set up
    if (user_not_fully_set_up($USER)) {
        if ($preventredirect) {
            throw new require_login_exception('User not fully set-up');
        }
        $SESSION->wantsurl = $FULLME;
        redirect($CFG->wwwroot . '/user/edit.php?id=' . $USER->id . '&course=' . SITEID);
    }
    // Make sure the USER has a sesskey set up. Used for CSRF protection.
    sesskey();
    // Do not bother admins with any formalities
    if (is_siteadmin()) {
        //set accesstime or the user will appear offline which messes up messaging
        user_accesstime_log($course->id);
        return;
    }
    // Check that the user has agreed to a site policy if there is one - do not test in case of admins
    if (!$USER->policyagreed and !is_siteadmin()) {
        if (!empty($CFG->sitepolicy) and !isguestuser()) {
            if ($preventredirect) {
                throw new require_login_exception('Policy not agreed');
            }
            $SESSION->wantsurl = $FULLME;
            redirect($CFG->wwwroot . '/user/policy.php');
        } else {
            if (!empty($CFG->sitepolicyguest) and isguestuser()) {
                if ($preventredirect) {
                    throw new require_login_exception('Policy not agreed');
                }
                $SESSION->wantsurl = $FULLME;
                redirect($CFG->wwwroot . '/user/policy.php');
            }
        }
    }
    // Fetch the system context, the course context, and prefetch its child contexts
    $sysctx = get_context_instance(CONTEXT_SYSTEM);
    $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
    if ($cm) {
        $cmcontext = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST);
    } else {
        $cmcontext = null;
    }
    // If the site is currently under maintenance, then print a message
    if (!empty($CFG->maintenance_enabled) and !has_capability('moodle/site:config', $sysctx)) {
        if ($preventredirect) {
            throw new require_login_exception('Maintenance in progress');
        }
        print_maintenance_message();
    }
    // make sure the course itself is not hidden
    if ($course->id == SITEID) {
        // frontpage can not be hidden
    } else {
        if (is_role_switched($course->id)) {
            // when switching roles ignore the hidden flag - user had to be in course to do the switch
        } else {
            if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
                // originally there was also test of parent category visibility,
                // BUT is was very slow in complex queries involving "my courses"
                // now it is also possible to simply hide all courses user is not enrolled in :-)
                if ($preventredirect) {
                    throw new require_login_exception('Course is hidden');
                }
                notice(get_string('coursehidden'), $CFG->wwwroot . '/');
            }
        }
    }
    // is the user enrolled?
    if ($course->id == SITEID) {
        // everybody is enrolled on the frontpage
    } else {
        if (session_is_loggedinas()) {
            // Make sure the REAL person can access this course first
            $realuser = session_get_realuser();
            if (!is_enrolled($coursecontext, $realuser->id, '', true) and !is_viewing($coursecontext, $realuser->id) and !is_siteadmin($realuser->id)) {
                if ($preventredirect) {
                    throw new require_login_exception('Invalid course login-as access');
                }
                echo $OUTPUT->header();
                notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot . '/');
            }
        }
        // very simple enrolment caching - changes in course setting are not reflected immediately
        if (!isset($USER->enrol)) {
            $USER->enrol = array();
            $USER->enrol['enrolled'] = array();
            $USER->enrol['tempguest'] = array();
        }
        $access = false;
        if (is_viewing($coursecontext, $USER)) {
            // ok, no need to mess with enrol
            $access = true;
        } else {
            if (isset($USER->enrol['enrolled'][$course->id])) {
                if ($USER->enrol['enrolled'][$course->id] == 0) {
                    $access = true;
                } else {
                    if ($USER->enrol['enrolled'][$course->id] > time()) {
                        $access = true;
                    } else {
                        //expired
                        unset($USER->enrol['enrolled'][$course->id]);
                    }
                }
            }
            if (isset($USER->enrol['tempguest'][$course->id])) {
                if ($USER->enrol['tempguest'][$course->id] == 0) {
                    $access = true;
                } else {
                    if ($USER->enrol['tempguest'][$course->id] > time()) {
                        $access = true;
                    } else {
                        //expired
                        unset($USER->enrol['tempguest'][$course->id]);
                        $USER->access = remove_temp_roles($coursecontext, $USER->access);
                    }
                }
            }
            if ($access) {
                // cache ok
            } else {
                if (is_enrolled($coursecontext, $USER, '', true)) {
                    // active participants may always access
                    // TODO: refactor this into some new function
                    $now = time();
                    $sql = "SELECT MAX(ue.timeend)\n                          FROM {user_enrolments} ue\n                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n                          JOIN {user} u ON u.id = ue.userid\n                         WHERE ue.userid = :userid AND ue.status = :active AND e.status = :enabled AND u.deleted = 0\n                               AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)";
                    $params = array('enabled' => ENROL_INSTANCE_ENABLED, 'active' => ENROL_USER_ACTIVE, 'userid' => $USER->id, 'courseid' => $coursecontext->instanceid, 'now1' => $now, 'now2' => $now);
                    $until = $DB->get_field_sql($sql, $params);
                    if (!$until or $until > time() + ENROL_REQUIRE_LOGIN_CACHE_PERIOD) {
                        $until = time() + ENROL_REQUIRE_LOGIN_CACHE_PERIOD;
                    }
                    $USER->enrol['enrolled'][$course->id] = $until;
                    $access = true;
                    // remove traces of previous temp guest access
                    $USER->access = remove_temp_roles($coursecontext, $USER->access);
                } else {
                    $instances = $DB->get_records('enrol', array('courseid' => $course->id, 'status' => ENROL_INSTANCE_ENABLED), 'sortorder, id ASC');
                    $enrols = enrol_get_plugins(true);
                    // first ask all enabled enrol instances in course if they want to auto enrol user
                    foreach ($instances as $instance) {
                        if (!isset($enrols[$instance->enrol])) {
                            continue;
                        }
                        // Get a duration for the guestaccess, a timestamp in the future or false.
                        $until = $enrols[$instance->enrol]->try_autoenrol($instance);
                        if ($until !== false) {
                            $USER->enrol['enrolled'][$course->id] = $until;
                            $USER->access = remove_temp_roles($coursecontext, $USER->access);
                            $access = true;
                            break;
                        }
                    }
                    // if not enrolled yet try to gain temporary guest access
                    if (!$access) {
                        foreach ($instances as $instance) {
                            if (!isset($enrols[$instance->enrol])) {
                                continue;
                            }
                            // Get a duration for the guestaccess, a timestamp in the future or false.
                            $until = $enrols[$instance->enrol]->try_guestaccess($instance);
                            if ($until !== false) {
                                $USER->enrol['tempguest'][$course->id] = $until;
                                $access = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (!$access) {
            if ($preventredirect) {
                throw new require_login_exception('Not enrolled');
            }
            $SESSION->wantsurl = $FULLME;
            redirect($CFG->wwwroot . '/enrol/index.php?id=' . $course->id);
        }
    }
    // Check visibility of activity to current user; includes visible flag, groupmembersonly,
    // conditional availability, etc
    if ($cm && !$cm->uservisible) {
        if ($preventredirect) {
            throw new require_login_exception('Activity is hidden');
        }
        redirect($CFG->wwwroot, get_string('activityiscurrentlyhidden'));
    }
    // Finally access granted, update lastaccess times
    user_accesstime_log($course->id);
}
Example #4
0
/**
 * This function checks that the current user is logged in and has the
 * required privileges
 *
 * This function checks that the current user is logged in, and optionally
 * whether they are allowed to be in a particular course and view a particular
 * course module.
 * If they are not logged in, then it redirects them to the site login unless
 * $autologinguest is set and {@link $CFG}->autologinguests is set to 1 in which
 * case they are automatically logged in as guests.
 * If $courseid is given and the user is not enrolled in that course then the
 * user is redirected to the course enrolment page.
 * If $cm is given and the coursemodule is hidden and the user is not a teacher
 * in the course then the user is redirected to the course home page.
 *
 * @uses $CFG
 * @uses $SESSION
 * @uses $USER
 * @uses $FULLME
 * @uses SITEID
 * @uses $COURSE
 * @param mixed $courseorid id of the course or course object
 * @param bool $autologinguest
 * @param object $cm course module object
 * @param bool $setwantsurltome Define if we want to set $SESSION->wantsurl, defaults to
 *             true. Used to avoid (=false) some scripts (file.php...) to set that variable,
 *             in order to keep redirects working properly. MDL-14495
 */
function require_login($courseorid = 0, $autologinguest = true, $cm = null, $setwantsurltome = true)
{
    global $CFG, $SESSION, $USER, $COURSE, $FULLME;
    /// setup global $COURSE, themes, language and locale
    course_setup($courseorid);
    /// If the user is not even logged in yet then make sure they are
    if (!isloggedin()) {
        //NOTE: $USER->site check was obsoleted by session test cookie,
        //      $USER->confirmed test is in login/index.php
        if ($setwantsurltome) {
            $SESSION->wantsurl = $FULLME;
        }
        if (!empty($_SERVER['HTTP_REFERER'])) {
            $SESSION->fromurl = $_SERVER['HTTP_REFERER'];
        }
        if ($autologinguest and !empty($CFG->guestloginbutton) and !empty($CFG->autologinguests) and ($COURSE->id == SITEID or $COURSE->guest)) {
            $loginguest = '?loginguest=true';
        } else {
            $loginguest = '';
        }
        if (empty($CFG->loginhttps) or $loginguest) {
            //do not require https for guest logins
            redirect($CFG->wwwroot . '/login/index.php' . $loginguest);
        } else {
            $wwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
            redirect($wwwroot . '/login/index.php');
        }
        exit;
    }
    /// loginas as redirection if needed
    if ($COURSE->id != SITEID and !empty($USER->realuser)) {
        if ($USER->loginascontext->contextlevel == CONTEXT_COURSE) {
            if ($USER->loginascontext->instanceid != $COURSE->id) {
                print_error('loginasonecourse', '', $CFG->wwwroot . '/course/view.php?id=' . $USER->loginascontext->instanceid);
            }
        }
    }
    /// check whether the user should be changing password (but only if it is REALLY them)
    if (get_user_preferences('auth_forcepasswordchange') && empty($USER->realuser)) {
        $userauth = get_auth_plugin($USER->auth);
        if ($userauth->can_change_password()) {
            $SESSION->wantsurl = $FULLME;
            if ($changeurl = $userauth->change_password_url()) {
                //use plugin custom url
                redirect($changeurl);
            } else {
                //use moodle internal method
                if (empty($CFG->loginhttps)) {
                    redirect($CFG->wwwroot . '/login/change_password.php');
                } else {
                    $wwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
                    redirect($wwwroot . '/login/change_password.php');
                }
            }
        } else {
            print_error('nopasswordchangeforced', 'auth');
        }
    }
    /// Check that the user account is properly set up
    if (user_not_fully_set_up($USER)) {
        $SESSION->wantsurl = $FULLME;
        redirect($CFG->wwwroot . '/user/edit.php?id=' . $USER->id . '&amp;course=' . SITEID);
    }
    /// Make sure current IP matches the one for this session (if required)
    if (!empty($CFG->tracksessionip)) {
        if ($USER->sessionIP != md5(getremoteaddr())) {
            print_error('sessionipnomatch', 'error');
        }
    }
    /// Make sure the USER has a sesskey set up.  Used for checking script parameters.
    sesskey();
    // Check that the user has agreed to a site policy if there is one
    if (!empty($CFG->sitepolicy)) {
        if (!$USER->policyagreed) {
            $SESSION->wantsurl = $FULLME;
            redirect($CFG->wwwroot . '/user/policy.php');
        }
    }
    // Fetch the system context, we are going to use it a lot.
    $sysctx = get_context_instance(CONTEXT_SYSTEM);
    /// If the site is currently under maintenance, then print a message
    if (!has_capability('moodle/site:config', $sysctx)) {
        if (file_exists($CFG->dataroot . '/' . SITEID . '/maintenance.html')) {
            print_maintenance_message();
            exit;
        }
    }
    /// groupmembersonly access control
    if (!empty($CFG->enablegroupings) and $cm and $cm->groupmembersonly and !has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) {
        if (isguestuser() or !groups_has_membership($cm)) {
            print_error('groupmembersonlyerror', 'group', $CFG->wwwroot . '/course/view.php?id=' . $cm->course);
        }
    }
    // Fetch the course context, and prefetch its child contexts
    if (!isset($COURSE->context)) {
        if (!($COURSE->context = get_context_instance(CONTEXT_COURSE, $COURSE->id))) {
            print_error('nocontext');
        }
    }
    if (!empty($cm) && !isset($cm->context)) {
        if (!($cm->context = get_context_instance(CONTEXT_MODULE, $cm->id))) {
            print_error('nocontext');
        }
    }
    if ($COURSE->id == SITEID) {
        /// Eliminate hidden site activities straight away
        if (!empty($cm) && !$cm->visible && !has_capability('moodle/course:viewhiddenactivities', $cm->context)) {
            redirect($CFG->wwwroot, get_string('activityiscurrentlyhidden'));
        }
        user_accesstime_log($COURSE->id);
        /// Access granted, update lastaccess times
        return;
    } else {
        /// Check if the user can be in a particular course
        if (empty($USER->access['rsw'][$COURSE->context->path])) {
            //
            // MDL-13900 - If the course or the parent category are hidden
            // and the user hasn't the 'course:viewhiddencourses' capability, prevent access
            //
            if (!($COURSE->visible && course_parent_visible($COURSE)) && !has_capability('moodle/course:viewhiddencourses', $COURSE->context)) {
                print_header_simple();
                notice(get_string('coursehidden'), $CFG->wwwroot . '/');
            }
        }
        /// Non-guests who don't currently have access, check if they can be allowed in as a guest
        if ($USER->username != 'guest' and !has_capability('moodle/course:view', $COURSE->context)) {
            if ($COURSE->guest == 1) {
                // Temporarily assign them guest role for this context, if it fails later user is asked to enrol
                $USER->access = load_temp_role($COURSE->context, $CFG->guestroleid, $USER->access);
            }
        }
        /// If the user is a guest then treat them according to the course policy about guests
        if (has_capability('moodle/legacy:guest', $COURSE->context, NULL, false)) {
            if (has_capability('moodle/site:doanything', $sysctx)) {
                // administrators must be able to access any course - even if somebody gives them guest access
                user_accesstime_log($COURSE->id);
                /// Access granted, update lastaccess times
                return;
            }
            switch ($COURSE->guest) {
                /// Check course policy about guest access
                case 1:
                    /// Guests always allowed
                    if (!has_capability('moodle/course:view', $COURSE->context)) {
                        // Prohibited by capability
                        print_header_simple();
                        notice(get_string('guestsnotallowed', '', format_string($COURSE->fullname)), "{$CFG->wwwroot}/login/index.php");
                    }
                    if (!empty($cm) and !$cm->visible) {
                        // Not allowed to see module, send to course page
                        redirect($CFG->wwwroot . '/course/view.php?id=' . $cm->course, get_string('activityiscurrentlyhidden'));
                    }
                    user_accesstime_log($COURSE->id);
                    /// Access granted, update lastaccess times
                    return;
                    // User is allowed to see this course
                    break;
                case 2:
                    /// Guests allowed with key
                    if (!empty($USER->enrolkey[$COURSE->id])) {
                        // Set by enrol/manual/enrol.php
                        user_accesstime_log($COURSE->id);
                        /// Access granted, update lastaccess times
                        return true;
                    }
                    //  otherwise drop through to logic below (--> enrol.php)
                    break;
                default:
                    /// Guests not allowed
                    $strloggedinasguest = get_string('loggedinasguest');
                    print_header_simple('', '', build_navigation(array(array('name' => $strloggedinasguest, 'link' => null, 'type' => 'misc'))));
                    if (empty($USER->access['rsw'][$COURSE->context->path])) {
                        // Normal guest
                        notice(get_string('guestsnotallowed', '', format_string($COURSE->fullname)), "{$CFG->wwwroot}/login/index.php");
                    } else {
                        notify(get_string('guestsnotallowed', '', format_string($COURSE->fullname)));
                        echo '<div class="notifyproblem">' . switchroles_form($COURSE->id) . '</div>';
                        print_footer($COURSE);
                        exit;
                    }
                    break;
            }
            /// For non-guests, check if they have course view access
        } else {
            if (has_capability('moodle/course:view', $COURSE->context)) {
                if (!empty($USER->realuser)) {
                    // Make sure the REAL person can also access this course
                    if (!has_capability('moodle/course:view', $COURSE->context, $USER->realuser)) {
                        print_header_simple();
                        notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot . '/');
                    }
                }
                /// Make sure they can read this activity too, if specified
                if (!empty($cm) && !$cm->visible && !has_capability('moodle/course:viewhiddenactivities', $cm->context)) {
                    redirect($CFG->wwwroot . '/course/view.php?id=' . $cm->course, get_string('activityiscurrentlyhidden'));
                }
                user_accesstime_log($COURSE->id);
                /// Access granted, update lastaccess times
                return;
                // User is allowed to see this course
            }
        }
        /// Currently not enrolled in the course, so see if they want to enrol
        $SESSION->wantsurl = $FULLME;
        redirect($CFG->wwwroot . '/course/enrol.php?id=' . $COURSE->id);
        die;
    }
}
function require_obu_login($courseorid = null, $autologinguest = true, $cm = null, $setwantsurltome = true, $preventredirect = false)
{
    global $CFG, $SESSION, $USER, $PAGE, $SITE, $DB, $OUTPUT;
    $login_url = '/local/obu_application/login.php';
    // Must not redirect when byteserving already started.
    if (!empty($_SERVER['HTTP_RANGE'])) {
        $preventredirect = true;
    }
    // Do not touch global $COURSE via $PAGE->set_course(),
    // the reasons is we need to be able to call require_obu_login() at any time!!
    $course = $SITE;
    // If this is an AJAX request and $setwantsurltome is true then we need to override it and set it to false.
    // Otherwise the AJAX request URL will be set to $SESSION->wantsurl and events such as self enrolment in the future
    // risk leading the user back to the AJAX request URL.
    if ($setwantsurltome && defined('AJAX_SCRIPT') && AJAX_SCRIPT) {
        $setwantsurltome = false;
    }
    // Redirect to the login page if session has expired, only with dbsessions enabled (MDL-35029) to maintain current behaviour.
    if ((!isloggedin() or isguestuser()) && !empty($SESSION->has_timed_out) && !$preventredirect && !empty($CFG->dbsessions)) {
        if ($setwantsurltome) {
            $SESSION->wantsurl = qualified_me();
        }
        redirect($login_url);
    }
    // If the user is not even logged in yet then make sure they are.
    if (!isloggedin()) {
        if ($autologinguest and !empty($CFG->guestloginbutton) and !empty($CFG->autologinguests)) {
            if (!($guest = get_complete_user_data('id', $CFG->siteguest))) {
                // Misconfigured site guest, just redirect to login page.
                redirect($login_url);
                exit;
                // Never reached.
            }
            $lang = isset($SESSION->lang) ? $SESSION->lang : $CFG->lang;
            complete_user_login($guest);
            $USER->autologinguest = true;
            $SESSION->lang = $lang;
        } else {
            // NOTE: $USER->site check was obsoleted by session test cookie, $USER->confirmed test is in login/index.php.
            if ($preventredirect) {
                throw new require_login_exception('You are not logged in');
            }
            if ($setwantsurltome) {
                $SESSION->wantsurl = qualified_me();
            }
            if (!empty($_SERVER['HTTP_REFERER'])) {
                $SESSION->fromurl = $_SERVER['HTTP_REFERER'];
            }
            redirect($login_url);
            exit;
            // Never reached.
        }
    }
    // Make sure the USER has a sesskey set up. Used for CSRF protection.
    sesskey();
    // Do not bother admins with any formalities.
    if (is_siteadmin()) {
        // Set accesstime or the user will appear offline which messes up messaging.
        user_accesstime_log($course->id);
        return;
    }
    // Fetch the system context, the course context, and prefetch its child contexts.
    $sysctx = context_system::instance();
    $coursecontext = context_course::instance($course->id, MUST_EXIST);
    $cmcontext = null;
    // If the site is currently under maintenance, then print a message.
    if (!empty($CFG->maintenance_enabled) and !has_capability('moodle/site:config', $sysctx)) {
        if ($preventredirect) {
            throw new require_login_exception('Maintenance in progress');
        }
        print_maintenance_message();
    }
    // Finally access granted, update lastaccess times.
    user_accesstime_log($course->id);
}