Source for file sloodle_session.php

Documentation is available at sloodle_session.php

  1. <?php
  2.     // This file is part of the Sloodle project (www.sloodle.org)
  3.     
  4.     /**
  5.     * This file defines the primary API class, SloodleSession.
  6.     *
  7.     * @package sloodle
  8.     * @copyright Copyright (c) 2008 Sloodle (various contributors)
  9.     * @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
  10.     *
  11.     * @contributor Peter R. Bloomfield
  12.     */
  13.     
  14.     /** General functionality. */
  15.     require_once(SLOODLE_LIBROOT.'/general.php');
  16.     /** Request and response functionality. */
  17.     require_once(SLOODLE_LIBROOT.'/io.php');
  18.     /** User functionality. */
  19.     require_once(SLOODLE_LIBROOT.'/user.php');
  20.     /** Course functionality. */
  21.     require_once(SLOODLE_LIBROOT.'/course.php');
  22.     /** Sloodle Controller functionality. */
  23.     require_once(SLOODLE_LIBROOT.'/controller.php');
  24.     /** Module functionality. */
  25.     require_once(SLOODLE_LIBROOT.'/modules.php');
  26.     
  27.     
  28.     /**
  29.     * The primary API class, which manages all other parts.
  30.     * @package sloodle
  31.     */
  32.     class SloodleSession
  33.     {
  34.     // DATA //
  35.         
  36.         /**
  37.         * Incoming HTTP request.
  38.         * @var SloodleRequest 
  39.         * @access public
  40.         */
  41.         var $request = null;
  42.     
  43.         /**
  44.         * Outgoing response - can be rendered to HTTP or as a string.
  45.         * @var SloodleResponse 
  46.         * @access public
  47.         */
  48.         var $response = null;
  49.         
  50.         /**
  51.         * Current user information.
  52.         * @var SloodleUser 
  53.         * @access public
  54.         */
  55.         var $user = null;
  56.         
  57.         /**
  58.         * The Sloodle course structure for the course this session is accessing
  59.         * @var SloodleCourse 
  60.         * @access public
  61.         */
  62.         var $course = null;
  63.         
  64.         /**
  65.         * The Sloodle module this session relates to, if any.
  66.         * Note: this may be the base Sloodle module class, or a derivative.
  67.         * @var SloodleModule 
  68.         * @access public
  69.         */
  70.         var $module = null;
  71.         
  72.         
  73.     // FUNCTIONS //
  74.     
  75.         /**
  76.         * Constructor - initialises members
  77.         * @param bool $process If true (default) then basic request data will be processed immediately. Otherwise, it can be done manually by calling $request->process_request_data()
  78.         */
  79.         function SloodleSession($process true)
  80.         {
  81.             // Construct the different parts of the session, as far as possible
  82.             $this->user = new SloodleUser($this);
  83.             $this->response = new SloodleResponse();
  84.             $this->request = new SloodleRequest($this);
  85.             $this->course = new SloodleCourse();
  86.             
  87.             // Process the basic request data
  88.             if ($process$this->request->process_request_data();
  89.         }
  90.         
  91.         
  92.         /**
  93.         * Constructs and loads the appropriate module part of the session.
  94.         * Note that this function will fail if the current VLE user (in the $user member) does not have permission to access it.
  95.         * @param string $type The expected type of module - function fails if type is not correctly matched
  96.         * @param bool $db If true then the system will also try to load appropriate data from the database, as specified in the module ID request parameter
  97.         * @param bool $require If true, then if something goes wrong, the script will be terminated with an error message
  98.         * @param bool $override_access If true, then the user access permissions will be overriden to force access (not implemented yet)
  99.         * @return bool True if successful, or false otherwise. (Note, if parameter $require was true, then the script will terminate before this function returns if something goes wrong)
  100.         */
  101.         function load_module($type$db$require true$override_access false)
  102.         {
  103.             // If the database loading is requested, then make sure we have a parameter to load with
  104.             $db_id null;
  105.             if ($db{
  106.                 $db_id $this->request->get_module_id($require);
  107.                 if ($db_id == nullreturn false;
  108.             }
  109.             
  110.             // Construct the module
  111.             $this->module = sloodle_load_module($type$this$db_id);
  112.             if (!$this->module{
  113.                 if ($require{
  114.                     $this->response->quick_output(-601'MODULE''Failed to construct module object'false);
  115.                     exit();
  116.                 }
  117.                 return false;
  118.             }
  119.             
  120.             return true;
  121.         }
  122.         
  123.         
  124.         /**
  125.         * Verifies security for the incoming request (but does not check user access).
  126.         * Initially ensures that the request is coming in on a valid and enabled course/controller (rejects it if not).
  127.         * The password is then checked, and it can handle prim-passwords and object-specific passwords.
  128.         *
  129.         * @param bool $require If true, the function will NOT return on authentication failure. Rather, it will terminate the script with an error message.
  130.         * @return bool true if successful in authenticating the request, or false if not.
  131.         */
  132.         function authenticate_request$require true )
  133.         {
  134.             // Make sure that the request data has been processed
  135.             if (!$this->request->is_request_data_processed()) {
  136.                 $this->request->process_request_data();
  137.             }
  138.             
  139.             // Make sure the controller ID parameter was specified
  140.             if ($this->request->get_controller_id($require=== nullreturn false;
  141.             
  142.             // Make sure we've got a valid course and controller object
  143.             if (!$this->course->controller->is_loaded()) {
  144.                 if ($require{
  145.                     $this->response->quick_output(-514'COURSE''Course controller could not be accessed.'false);
  146.                     exit();
  147.                 }
  148.                 return false;
  149.             }
  150.             if (!$this->course->is_loaded()) {
  151.                 if ($require{
  152.                     $this->response->quick_output(-512'COURSE''Course could not be accessed.'false);
  153.                     exit();
  154.                 }
  155.                 return false;
  156.             }
  157.             
  158.             // Make sure the course is available
  159.             if (!$this->course->is_available()) {
  160.                 if ($require{
  161.                     $this->response->quick_output(-513'COURSE''Course not available.'false);
  162.                     exit();
  163.                 }
  164.                 return false;
  165.             }
  166.             // Make sure the contrller is available
  167.             if (!$this->course->controller->is_available()) {
  168.                 if ($require{
  169.                     $this->response->quick_output(-514'COURSE''Course controller not available.'false);
  170.                     exit();
  171.                 }
  172.                 return false;
  173.             }
  174.             
  175.             // Make sure the controller is enabled
  176.             if (!$this->course->controller->is_enabled()) {
  177.                 if ($require{
  178.                     $this->response->quick_output(-514'COURSE''Course controller disabled.'false);
  179.                     exit();
  180.                 }
  181.                 return false;
  182.             }
  183.         
  184.             // Get the password parameter
  185.             $password $this->request->get_password($require);
  186.             if ($password == null{
  187.                 if ($require{
  188.                     $this->response->quick_output(-212'OBJECT_AUTH''Prim Password cannot be empty.'false);
  189.                     exit();
  190.                 }
  191.                 return false;
  192.             }
  193.             
  194.             // Does the password contain an object UUID?
  195.             $parts explode('|'$password);
  196.             if (count($parts>= 2{
  197.                 $objuuid $parts[0];
  198.                 $objpwd $parts[1];
  199.                 // Make sure the password was provided
  200.                 if (empty($objpwd)) {
  201.                     if ($require{
  202.                         $this->response->quick_output(-212'OBJECT_AUTH''Object-specific password not specified.'false);
  203.                         exit();
  204.                     }
  205.                     return false;
  206.                 }
  207.                 
  208.                 // Verify the object's authorisation
  209.                 if ($this->course->controller->check_authorisation($objuuid$objpwd)) {
  210.                     // Passed authorisation - make sure the object is registered as being still active
  211.                     $this->course->controller->ping_object($objuuid);
  212.                     return true;
  213.                 }
  214.                 if ($require{
  215.                     $this->response->quick_output(-213'OBJECT_AUTH''Object-specific password was invalid.'false);
  216.                     exit();
  217.                 }
  218.                 return false;
  219.             }
  220.             
  221.             // Get the controller password
  222.             $controllerpwd $this->course->controller->get_password();
  223.             // Prim Password access is disabled if no password has been specified
  224.             if (strlen($controllerpwd== 0{
  225.                 if ($require{
  226.                     $this->response->quick_output(-213'OBJECT_AUTH''Access to this Controller by prim password has been disabled.'false);
  227.                     exit();
  228.                 }
  229.                 return false;
  230.             }
  231.             // Check that the passwords match
  232.             if ($password != $this->course->controller->get_password()) {
  233.                 if ($require{
  234.                     $this->response->quick_output(-213'OBJECT_AUTH''Prim password was invalid.'false);
  235.                     exit();
  236.                 }
  237.                 return false;
  238.             }
  239.  
  240.             return true;
  241.         }
  242.         
  243.         
  244.         /**
  245.         * Validates the user account and enrolment (ensures there is an avatar linked to a VLE account, and that the VLE account is enrolled in the current course).
  246.         * Attempts auto-registration/enrolment if that is allowed and required, and logs-in the user.
  247.         * Server access level is checked if it is specified in the request parameters.
  248.         * Note: if the request indicates that it relates to an object, then the validation fails.
  249.         * @param bool $require If true, the script will be terminated with an error message if validation fails
  250.         * @param bool $suppress_autoreg If true, auto-registration will be completely suppressed for this function call
  251.         * @param bool $suppress_autoenrol If true, auto-enrolment will be completely suppressed for this function call
  252.         * @return bool Returns true if validation and/or autoregistration were successful. Returns false on failure (unless $require was true).
  253.         */
  254.         function validate_user($require true$suppress_autoreg false$suppress_autoenrol false)
  255.         {
  256.             // Is it an object request?
  257.             if ($this->request->is_object_request()) {
  258.                 if ($require{
  259.                     $this->response->quick_output(-301'USER_AUTH''Cannot validate object as user.'false);
  260.                     exit();
  261.                 }
  262.                 return false;
  263.             }
  264.             
  265.             // Was a server access level specified in the request?
  266.             $sal $this->request->get_server_access_level(false);
  267.             if ($sal != null{
  268.                 // Check what level was specified
  269.                 $sal = (int)$sal;
  270.                 $allowed false;
  271.                 $reason 'Unknown.';
  272.                 switch ($sal{
  273.                 case SLOODLE_SERVER_ACCESS_LEVEL_PUBLIC:
  274.                     // Always allowed
  275.                     $allowed true;
  276.                     break;
  277.                 
  278.                 case SLOODLE_SERVER_ACCESS_LEVEL_COURSE:
  279.                     // Is a course already loaded?
  280.                     if (!$this->course->is_loaded()) {
  281.                         $reason 'No course loaded.';
  282.                         break;
  283.                     }
  284.                 
  285.                     // Was a user account already fully loaded?
  286.                     if ($this->user->is_avatar_linked()) {
  287.                         // Is the user enrolled on the current course?
  288.                         if ($this->user->is_enrolled($this->course->get_course_id())) $allowed true;
  289.                         else $reason 'User not enrolled in course.';
  290.                     else {
  291.                         $reason 'User not registered on site.';
  292.                     }
  293.                     break;
  294.                     
  295.                 case SLOODLE_SERVER_ACCESS_LEVEL_SITE:
  296.                     // Was a user account already fully loaded?
  297.                     if ($this->user->is_avatar_linked()) $allowed true;
  298.                     else $reason 'User not registered on site.';
  299.                     break;
  300.                     
  301.                 case SLOODLE_SERVER_ACCESS_LEVEL_STAFF:
  302.                     // Is a course already loaded?
  303.                     if (!$this->course->is_loaded()) {
  304.                         $reason 'No course loaded.';
  305.                         break;
  306.                     }
  307.                 
  308.                     // Was a user account already fully loaded?
  309.                     if ($this->user->is_avatar_linked()) {
  310.                         // Is the user staff on the current course?
  311.                         if ($this->user->is_staff($this->course->get_course_id())) $allowed true;
  312.                         else $reason 'User not staff in course.';
  313.                     else {
  314.                         $reason 'User not registered on site.';
  315.                     }
  316.                     break;
  317.                     
  318.                 default:
  319.                     // Unknown access level
  320.                     $reason 'Access level not recognised';
  321.                     break;
  322.                 }
  323.                 
  324.                 // Was the user blocked by access level?
  325.                 if (!$allowed{
  326.                     if ($require{
  327.                         $this->response->quick_output(-331'USER_AUTH'$reasonfalse);
  328.                         exit();
  329.                     }
  330.                     return false;
  331.                 }
  332.             }
  333.         
  334.         // REGISTRATION //
  335.         
  336.             // Make sure a the course is loaded
  337.             if (!$this->course->is_loaded()) {
  338.                 if ($require{
  339.                     $this->response->quick_output(-511'COURSE''Cannot validate user - no course data loaded.'false);
  340.                     exit();
  341.                 }
  342.                 return false;
  343.             }
  344.         
  345.             // Is the user already loaded?
  346.             if (!$this->user->is_avatar_linked())
  347.             {
  348.                 // If an avatar is loaded, but the user isn't, then we probably have a deleted Moodle user
  349.                 if ($this->user->is_avatar_loaded(== true && $this->user->is_user_loaded(== false{
  350.                     $this->response->quick_output(-301'USER_AUTH''Avatar linked to deleted user account'false);
  351.                     exit();
  352.                 }
  353.             
  354.                 // Make sure avatar details were provided
  355.                 $uuid $this->request->get_avatar_uuid(false);
  356.                 $avname $this->request->get_avatar_name(false);
  357.                 // Is validation required?
  358.                 if ($require{
  359.                     // Check the UUID
  360.                     if (empty($uuid)) {
  361.                         $this->response->quick_output(-311'USER_AUTH''User UUID required'false);
  362.                         exit();
  363.                     }
  364.                     // Check the name
  365.                     if (empty($avname)) {
  366.                         $this->response->quick_output(-311'USER_AUTH''Avatar name required'false);
  367.                         exit();
  368.                     }
  369.                 else if (empty($uuid|| empty($avname)) {
  370.                     // If there was a problem, just stop
  371.                     return false;
  372.                 }
  373.             
  374.                 // Ensure autoreg is not suppressed, and that it is permitted on that course and on the site
  375.                 if ($suppress_autoreg == true || $this->course->check_autoreg(== false{
  376.                     if ($require{
  377.                         $this->response->quick_output(-321'USER_AUTH''User not registered, and auto-registration of users was not permitted'false);
  378.                         exit();
  379.                     }
  380.                     return false;
  381.                 }
  382.                 
  383.                 // It is important that we also check auto-enrolment here.
  384.                 // If that is not enabled, but the call here requires it, then there is no point registering the user.
  385.                 if ($suppress_autoenrol == true || $this->course->check_autoenrol(== false{
  386.                     if ($require{
  387.                         $this->response->quick_output(-421'USER_ENROL''User not enrolled, and auto-enrolment of users was not permitted'false);
  388.                         exit();
  389.                     }
  390.                     return false;
  391.                 }
  392.             
  393.                 // Is there an avatar loaded?
  394.                 if (!$this->user->is_avatar_loaded()) {
  395.                     // Add the avatar details, linked to imaginary user 0
  396.                     if (!$this->user->add_linked_avatar(0$uuid$avname)) {
  397.                         if ($require{
  398.                             $this->response->quick_output(-322'USER_AUTH''Failed to add new avatar'false);
  399.                             exit();
  400.                         }
  401.                         return false;
  402.                     }
  403.                 }
  404.                 
  405.                 // If we reached here then we definitely have an avatar
  406.                 // Create a matching Moodle user
  407.                 $password $this->user->autoregister_avatar_user();
  408.                 if ($password === FALSE{
  409.                     if ($require{
  410.                         $this->response->quick_output(-322'USER_AUTH''Failed to register new user account'false);
  411.                         exit();
  412.                     }
  413.                     return false;
  414.                 }
  415.                 
  416.                 // Add a side effect code to our response data
  417.                 $this->response->add_side_effect(322);
  418.                 // The user needs to be notified of their new username/password
  419.                 if (isset($_SERVER['HTTP_X_SECONDLIFE_OBJECT_KEY'])) {
  420.                     sloodle_login_notification($_SERVER['HTTP_X_SECONDLIFE_OBJECT_KEY']$uuid$this->user->get_username()$password);
  421.                 }
  422.             }
  423.             
  424.         // ENROLMENT //
  425.             
  426.             // Is the user already enrolled on the course?
  427.             if (!$this->user->is_enrolled($this->course->get_course_id())) {
  428.                 // Ensure auto-enrolment is not suppressed, and that it is permitted on that course and on the site
  429.                 if ($suppress_autoenrol == true || $this->course->check_autoenrol(== false{
  430.                     if ($require{
  431.                         $this->response->quick_output(-421'USER_ENROL''Auto-enrolment of users was not permitted'false);
  432.                         exit();
  433.                     }
  434.                     return false;
  435.                 }
  436.                 
  437.                 // Attempt to enrol the user
  438.                 if (!$this->user->enrol()) {
  439.                     if ($require{
  440.                         $this->response->quick_output(-422'USER_ENROL''Auto-enrolment failed'false);
  441.                         exit();
  442.                     }
  443.                     return false;
  444.                 }
  445.                 
  446.                 // Add a side effect code to our response data
  447.                 $this->response->add_side_effect(422);
  448.             }
  449.             
  450.             // Make sure the user is logged-in
  451.             return ($this->user->login());
  452.         }
  453.         
  454.         //... Add functions for verifying user access to resources?
  455.         
  456.     }
  457.  
  458. ?>

Documentation generated on Mon, 16 Jun 2008 15:57:00 +0100 by phpDocumentor 1.4.0