phpPoA2
[ class tree: phpPoA2 ] [ index: phpPoA2 ] [ all elements ]

Source for file InviteAuthzEngine.php

Documentation is available at InviteAuthzEngine.php

  1. <?php
  2. /**
  3.  * @copyright Copyright 2005-2010 RedIRIS, http://www.rediris.es/
  4.  *
  5.  *  This file is part of phpPoA2.
  6.  *
  7.  *  phpPoA2 is free software: you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation, either version 3 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  phpPoA2 is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with phpPoA2. If not, see <http://www.gnu.org/licenses/>.
  19.  *
  20.  * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
  21.  * @version 2.0
  22.  * @author Jaime Perez <jaime.perez@rediris.es>
  23.  * @filesource
  24.  */
  25.  
  26. /**
  27.  * Supported database types.
  28.  */
  29. define('INVITES_DBA''InviteDBADB');
  30. define('INVITES_MYSQL''InviteMySQLDB');
  31. define('INVITES_SESSION''InviteSessionDB');
  32. define('AUTHORIZED_DBA''AuthorizedDBADB');
  33. define('AUTHORIZED_MYSQL''AuthorizedMySQLDB');
  34. define('AUTHORIZED_SESSION''AuthorizedSessionDB');
  35.  
  36. /**
  37.  * This hook is executed right before it is checked whether the user was invited or not to
  38.  * continue with authorization.
  39.  * It can be used to trick the engine to believe the user was previously invited (and therefore
  40.  * forcing authorization).
  41.  * The hook receives a boolean parameter representing whether the referenced invitation was found
  42.  * or not.
  43.  *
  44.  * function invitesBeforeAuthorization(&$invite_exists);
  45.  *
  46.  * Please bear in mind that hooks must return TRUE or they'll keep other hooks from executing.
  47.  */
  48. define("INVITES_BEFORE_AUTHORIZATION""INVITES_BEFORE_AUTHORIZATION");
  49.  
  50. /**
  51.  * Invitation based authorization engine.
  52.  * @package phpPoA2
  53.  * @subpackage InviteAuthorizationEngine
  54.  */
  55.  
  56.     protected $authz_db;
  57.     protected $invites_db;
  58.     protected $valid_hooks = array(INVITES_BEFORE_AUTHORIZATION);
  59.  
  60.     /**
  61.      * Configure the authorization engine.
  62.      * @param file The configuration file.
  63.      * @param section The section of the configuration file to use.
  64.      */
  65.     public function configure($file$section{
  66.         parent::configure($file$section);
  67.  
  68.         // configure authorized DB
  69.         $db_t $this->cfg->getAuthorizedDBType();
  70.         if (class_exists($db_ttrue)) {
  71.             $this->authz_db = new $db_t($this->cfg);
  72.         }
  73.  
  74.         // configure invites DB
  75.         $db_t $this->cfg->getInvitesDBType();
  76.         if (class_exists($db_ttrue)) {
  77.             $this->invites_db = new $db_t($this->cfg);
  78.         }
  79.     }
  80.  
  81.     /**
  82.      * Check if the specified user is authorized with the given attributes.
  83.      * @param user The name of the user to check authorization for.
  84.      * @param attrs The attributes of the user to match his identity.
  85.      * @return boolean true if the user is authorized, false otherwise.
  86.      */
  87.     public function isAuthorized($user$attrs{
  88.         if (!$this->authz_db->open()) {
  89.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  90.             return false;
  91.         }
  92.  
  93.         // retrieve data
  94.         $stored $this->authz_db->fetch($user);
  95.         $this->authz_db->close();
  96.         if (!$stored// not found
  97.             trigger_error(msg('cannot-fetch-key'array($user))E_USER_WARNING);
  98.             return false;
  99.         }
  100.  
  101.         // check expiration
  102.         $now time();
  103.         if ($stored['expires'&& $now $stored['expires']{
  104.             trigger_error(msg('authz-expired'array($user))E_USER_WARNING);
  105.             return false;
  106.         }
  107.  
  108.         // check attributes
  109.         $rslt false;
  110.         foreach ($this->cfg->getUniqueAttributes(as $attr{
  111.             if (is_array($attr)) {
  112.                 $partial true;
  113.                 foreach ($attr as $compound{
  114.                     $partial &= $stored['attributes'][$compound== $attrs[$compound];
  115.                 }
  116.                 $rslt |= $partial;
  117.             else {
  118.                 $rslt |= $stored['attributes'][$attr== $attrs[$attr];
  119.             }
  120.             if ($rsltbreak;
  121.         }
  122.         return $rslt;
  123.     }
  124.  
  125.     /**
  126.      * Get a list of all authorized users.
  127.      * @return array The list of all users currently authorized. An empty
  128.      *  array if none found.
  129.      */
  130.     public function getAuthorizedList({
  131.         if (!$this->authz_db->open()) {
  132.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  133.             return false;
  134.         }
  135.  
  136.         $all $this->authz_db->fetch_all();
  137.         return $this->finish($all);
  138.     }
  139.  
  140.     /**
  141.      * Get a list of all pending invitations.
  142.      * @return array The list of all pending invitations. An empty array if
  143.      *  none found.
  144.      */
  145.     public function getPendingInvites({
  146.         if (!$this->invites_db->open()) {
  147.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  148.             return false;
  149.         }
  150.  
  151.         $all $this->invites_db->fetch_all();
  152.         return $this->finish($all);
  153.     }
  154.  
  155.     /**
  156.      * Authorize the specified user.
  157.      * @param user 
  158.      * @param attrs 
  159.      * @param ref 
  160.      * @param expires 
  161.      * @return boolean true if the user was successfully authorized, false otherwise.
  162.      */
  163.     public function authorize($user$attrs$ref$expires 0{
  164.         if (!$this->authz_db->open()) {
  165.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  166.             return false;
  167.         }
  168.  
  169.         if (!$this->invites_db->open()) {
  170.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  171.             return false;
  172.         }
  173.  
  174.         $invited $this->invites_db->check($ref);
  175.         $exists $this->authz_db->check($user);
  176.  
  177.         // run hook before actually performing authorization
  178.         $args array($invited);
  179.         $this->runHooks(INVITES_BEFORE_AUTHORIZATION$args);
  180.         $invited $args[0];
  181.  
  182.         // the user wasn't previously invited
  183.         if (!$invited{
  184.             if ($exists// the user was previously authorized
  185.                 $stored $this->authz_db->fetch($user);
  186.                 $matches true;
  187.                 foreach ($stored['attributes'as $name => $value{
  188.                     $matches &= ($attrs[$name== $value);
  189.                 }
  190.                 if ($matches// is the same user, skip
  191.                     trigger_error(msg('user-already-authz'array($user))E_USER_WARNING);
  192.                     return $this->finish(false);
  193.                 }
  194.             }
  195.             trigger_error(msg('invite-non-existant'array($ref))E_USER_WARNING);
  196.             return $this->finish(false);
  197.         }
  198.  
  199.         // either the invite exists or we are asked to force authorization
  200.         $invite $this->invites_db->fetch($ref);
  201.  
  202.         // check if the user has some of the mandatory attributes
  203.         $unique $this->cfg->getUniqueAttributes();
  204.         foreach ($unique as $item{
  205.             $save array()// restore on each iteration
  206.             if (is_array($item)) // a combination of attributes
  207.                 $complete true;
  208.                 foreach ($item as $name{
  209.                     $complete &= !empty($attrs[$name]);
  210.                     $save[$name$attrs[$name];
  211.                 }
  212.                 if ($complete{
  213.                     break// all attributes found, ok!
  214.                 }
  215.             else // a single attribute
  216.                 if (!empty($attrs[$item])) // attribute found, ok!
  217.                     $save[$item$attrs[$item];
  218.                     break;
  219.                 }
  220.             }
  221.         }
  222.         if (empty($save)) // no available attributes!
  223.             trigger_error(msg('missing-attrs')E_USER_WARNING);
  224.             return $this->finish(false);
  225.         }
  226.  
  227.         // e-mail verification
  228.         if (!$this->emailVerify($invite['email']$attrs)) {
  229.              return $this->finish(false);
  230.         }
  231.  
  232.         // now save the user in the authorized database
  233.         if (@!$this->authz_db->replace_authorization($user$save$invite['email']$expires)) {
  234.             trigger_error(msg('cannot-authorize'array($user))E_USER_WARNING);
  235.             return $this->finish(false);
  236.         }
  237.  
  238.         // remove invite
  239.         if (@!$this->invites_db->delete($ref)) {
  240.             trigger_error(msg('cannot-del-invite'array($user$reference))E_USER_WARNING);
  241.             return $this->finish(false);
  242.         }
  243.  
  244.         // success
  245.         trigger_error(msg('user-authorized'array($user))E_USER_NOTICE);
  246.         return $this->finish(true);
  247.     }
  248.  
  249.     /**
  250.      * Revoke authorization for the specified user.
  251.      * @param 
  252.      * @return boolean true if authorization was successfully revoked, false otherwise.
  253.      */
  254.     public function revoke($mail{
  255.         if (!$this->authz_db->open()) {
  256.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  257.             return false;
  258.         }
  259.  
  260.         // sanitize email
  261.         $mail strtolower($mail);
  262.  
  263.         // get a list with all users authorized 
  264.         $all $this->authz_db->fetch_all();
  265.  
  266.         // iterate to find the user
  267.         foreach ($all as $key => $values{
  268.             if ($values['email'== $mail{
  269.                 // found, remove!
  270.                 return $this->finish($this->authz_db->delete($key));
  271.             }
  272.         }
  273.  
  274.         // not found!
  275.         return $this->finish(false);
  276.     }
  277.  
  278.     /**
  279.      * Send an invitation to an e-mail address (that is, send an e-mail to that
  280.      * address with instructions on how to get authorized and an URL to follow).
  281.      * @param mail The e-mail of the user.
  282.      * @param expires The time (POSIX) when authorization will expire. Use 0 if authorization
  283.      *  should never expire. Defaults to 0.
  284.      * @return boolean true if the invitation was correctly sent, false in any other case.
  285.      */
  286.     public function invite($mail$expires 0{
  287.         if (!$this->invites_db->open()) {
  288.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  289.             return false;
  290.         }
  291.  
  292.         // sanitize e-mail
  293.         $mail strtolower($mail);
  294.  
  295.         // generate random reference
  296.         $ref mt_rand();
  297.  
  298.         if (@!$this->invites_db->replace_invite($ref$mail$expires)) {
  299.             trigger_error(msg('cannot-save-invite'array($mail))E_USER_WARNING);
  300.             return $this->finish(false);
  301.         }
  302.  
  303.         // setup email
  304.         $sep (!strstr($this->cfg->getInviteURL()"?")) "?" "&";
  305.         $url $this->cfg->getInviteURL().$sep."ref=".$ref;
  306.         $text preg_replace("/##URL##/"$url$this->cfg->getInviteText());
  307.         $headers "From: ".$this->cfg->getAdminEmail();
  308.         $command_params "-f ".$this->cfg->getAdminEmail();
  309.  
  310.         // send it
  311.         mail($mail$this->cfg->getInviteSubject()$text$headers$command_params);
  312.  
  313.         trigger_error(msg('invite-sent-to'array($mail)));
  314.         return $this->finish(true);
  315.     }
  316.  
  317.     /**
  318.      * Remove an invitation from the database.
  319.      * @param ref The reference to the invite to remove.
  320.      * @return boolean true if the invite was removed, false otherwise.
  321.      */
  322.     public function removeInvite($ref{
  323.         if (!$this->invites_db->open()) {
  324.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  325.             return false;
  326.         }
  327.  
  328.         // remove the invite
  329.         $rslt $this->invites_db->delete($ref);
  330.         return $this->finish($rslt);
  331.     }
  332.  
  333.     /**
  334.      * Perform e-mail verification for the current user according to the configuration
  335.      * for this site.
  336.      * @param mail The e-mail of the user.
  337.      * @param attrs The array of attributes of the user.
  338.      * @return boolean true if verification succeeds or was not performed, false otherwise.
  339.      */
  340.     protected function emailVerify($mail$attrs{
  341.         $mail_attr $this->cfg->getEmailVerifyAttribute();
  342.         if ($this->cfg->doEmailVerify()) {
  343.             // empty attribute, configuration error!
  344.             if (empty($mail_attr)) {
  345.                 trigger_error(msg('mail-attr-err')E_USER_WARNING);
  346.                 return false;
  347.             }
  348.             // attribute not set, cannot verify
  349.             if (!isset($attrs[$mail_attr])) {
  350.                 trigger_error(msg('missing-mail-attr'array($mail_attr))E_USER_WARNING);
  351.                 return false;
  352.             }
  353.  
  354.             $alg_re $this->cfg->getEmailVerifyAlgRegEx();
  355.             $val_re $this->cfg->getEmailVerifyRegEx();
  356.  
  357.             // extract function
  358.             $alg "sprintf(\"%s\",";
  359.             if (!empty($alg_re)) {
  360.                 if (!preg_match("/".$alg_re."/"$attrs[$mail_attr]$vals)) {
  361.                     trigger_error(msg('mail-attr-alg-err'array($mail_attr$attrs[$mail_attr]))E_USER_WARNING);
  362.                     return false;
  363.                 }
  364.                 $alg $vals[1]."(";
  365.             }
  366.  
  367.             // extract value
  368.             if (!preg_match("/".$val_re."/"$attrs[$mail_attr]$vals)) {
  369.                 trigger_error(msg('mail-attr-val-err'array($mail_attr$attrs[$mail_attr]))E_USER_WARNING);
  370.                 return false;
  371.             }
  372.             $received $vals[1];
  373.  
  374.             $computed_value = eval("return ".$alg."\"".$mail."\");");
  375.             if ($computed_value != $received{
  376.                 trigger_error(msg('mail-verify-err'array($mail$computed_value$received))E_USER_WARNING);
  377.                 return false;
  378.             }
  379.         }
  380.         return true;
  381.     }
  382.  
  383.     /**
  384.      * Close databases and return the same value received as a parameter.
  385.      * @param value The value that must be returned.
  386.      * @return mixed The first param.
  387.      */
  388.     protected function finish($value{
  389.         $this->invites_db->close();
  390.         $this->authz_db->close();
  391.         return $value;
  392.     }
  393.  
  394. }
  395.  
  396. ?>

Documentation generated on Thu, 26 Aug 2010 13:38:50 +0200 by phpDocumentor 1.4.3