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.         $this->registerHandler();
  132.         if (!$this->authz_db->open()) {
  133.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  134.             return false;
  135.         }
  136.  
  137.         $all $this->authz_db->fetch_all();
  138.         $this->clean();
  139.         return $this->finish($all);
  140.     }
  141.  
  142.     /**
  143.      * Get a list of all pending invitations.
  144.      * @return array The list of all pending invitations. An empty array if
  145.      *  none found.
  146.      */
  147.     public function getPendingInvites({
  148.         $this->registerHandler();
  149.         if (!$this->invites_db->open()) {
  150.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  151.             return false;
  152.         }
  153.  
  154.         $all $this->invites_db->fetch_all();
  155.         $this->clean();
  156.         return $this->finish($all);
  157.     }
  158.  
  159.     /**
  160.      * Authorize the specified user.
  161.      * @param user 
  162.      * @param attrs 
  163.      * @param ref 
  164.      * @param expires 
  165.      * @return boolean true if the user was successfully authorized, false otherwise.
  166.      */
  167.     public function authorize($user$attrs$ref$expires 0{
  168.         if (!$this->authz_db->open()) {
  169.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  170.             return false;
  171.         }
  172.  
  173.         if (!$this->invites_db->open()) {
  174.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  175.             return false;
  176.         }
  177.  
  178.         $invited $this->invites_db->check($ref);
  179.         $exists $this->authz_db->check($user);
  180.  
  181.         // run hook before actually performing authorization
  182.         $args array($invited);
  183.         $this->runHooks(INVITES_BEFORE_AUTHORIZATION$args);
  184.         $invited $args[0];
  185.  
  186.         // the user wasn't previously invited
  187.         if (!$invited{
  188.             if ($exists// the user was previously authorized
  189.                 $stored $this->authz_db->fetch($user);
  190.                 $matches true;
  191.                 foreach ($stored['attributes'as $name => $value{
  192.                     $matches &= ($attrs[$name== $value);
  193.                 }
  194.                 if ($matches// is the same user, skip
  195.                     trigger_error(msg('user-already-authz'array($user))E_USER_WARNING);
  196.                     return $this->finish(false);
  197.                 }
  198.             }
  199.             trigger_error(msg('invite-non-existant'array($ref))E_USER_WARNING);
  200.             return $this->finish(false);
  201.         }
  202.  
  203.         // either the invite exists or we are asked to force authorization
  204.         $invite $this->invites_db->fetch($ref);
  205.  
  206.         // check if the user has some of the mandatory attributes
  207.         $unique $this->cfg->getUniqueAttributes();
  208.         foreach ($unique as $item{
  209.             $save array()// restore on each iteration
  210.             if (is_array($item)) // a combination of attributes
  211.                 $complete true;
  212.                 foreach ($item as $name{
  213.                     $complete &= !empty($attrs[$name]);
  214.                     $save[$name$attrs[$name];
  215.                 }
  216.                 if ($complete{
  217.                     break// all attributes found, ok!
  218.                 }
  219.             else // a single attribute
  220.                 if (!empty($attrs[$item])) // attribute found, ok!
  221.                     $save[$item$attrs[$item];
  222.                     break;
  223.                 }
  224.             }
  225.         }
  226.         if (empty($save)) // no available attributes!
  227.             trigger_error(msg('missing-attrs')E_USER_WARNING);
  228.             return $this->finish(false);
  229.         }
  230.  
  231.         // e-mail verification
  232.         if (!$this->emailVerify($invite['email']$attrs)) {
  233.              return $this->finish(false);
  234.         }
  235.  
  236.         // now save the user in the authorized database
  237.         if (@!$this->authz_db->replace_authorization($user$save$invite['email']$expires)) {
  238.             trigger_error(msg('cannot-authorize'array($user))E_USER_WARNING);
  239.             return $this->finish(false);
  240.         }
  241.  
  242.         // remove invite
  243.         if (@!$this->invites_db->delete($ref)) {
  244.             trigger_error(msg('cannot-del-invite'array($user$reference))E_USER_WARNING);
  245.             return $this->finish(false);
  246.         }
  247.  
  248.         // success
  249.         trigger_error(msg('user-authorized'array($user))E_USER_NOTICE);
  250.         return $this->finish(true);
  251.     }
  252.  
  253.     /**
  254.      * Revoke authorization for the specified user.
  255.      * @param 
  256.      * @return boolean true if authorization was successfully revoked, false otherwise.
  257.      */
  258.     public function revoke($mail{
  259.         if (!$this->authz_db->open()) {
  260.             trigger_error(msg('cannot-open-authz-db')E_USER_WARNING);
  261.             return false;
  262.         }
  263.  
  264.         // sanitize email
  265.         $mail strtolower($mail);
  266.  
  267.         // get a list with all users authorized 
  268.         $all $this->authz_db->fetch_all();
  269.  
  270.         // iterate to find the user
  271.         foreach ($all as $key => $values{
  272.             if ($values['email'== $mail{
  273.                 // found, remove!
  274.                 return $this->finish($this->authz_db->delete($key));
  275.             }
  276.         }
  277.  
  278.         // not found!
  279.         return $this->finish(false);
  280.     }
  281.  
  282.     /**
  283.      * Send an invitation to an e-mail address (that is, send an e-mail to that
  284.      * address with instructions on how to get authorized and an URL to follow).
  285.      * @param mail The e-mail of the user.
  286.      * @param expires The time (POSIX) when authorization will expire. Use 0 if authorization
  287.      *  should never expire. Defaults to 0.
  288.      * @return boolean true if the invitation was correctly sent, false in any other case.
  289.      */
  290.     public function invite($mail$expires 0{
  291.         $this->registerHandler();
  292.         if (!$this->invites_db->open()) {
  293.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  294.             return false;
  295.         }
  296.  
  297.         // sanitize e-mail
  298.         $mail strtolower($mail);
  299.  
  300.         // generate random reference
  301.         $ref mt_rand();
  302.  
  303.         if (@!$this->invites_db->replace_invite($ref$mail$expires)) {
  304.             trigger_error(msg('cannot-save-invite'array($mail))E_USER_WARNING);
  305.             return $this->finish(false);
  306.         }
  307.  
  308.         // setup email
  309.         $sep (!strstr($this->cfg->getInviteURL()"?")) "?" "&";
  310.         $url $this->cfg->getInviteURL().$sep."ref=".$ref;
  311.         $text preg_replace("/##URL##/"$url$this->cfg->getInviteText());
  312.         $headers "From: ".$this->cfg->getAdminEmail();
  313.         $command_params "-f ".$this->cfg->getAdminEmail();
  314.  
  315.         // send it
  316.         mail($mail$this->cfg->getInviteSubject()$text$headers$command_params);
  317.  
  318.         trigger_error(msg('invite-sent-to'array($mail))E_USER_WARNING);
  319.         $this->clean();
  320.         return $this->finish(true);
  321.     }
  322.  
  323.     /**
  324.      * Remove an invitation from the database.
  325.      * @param ref The reference to the invite to remove.
  326.      * @return boolean true if the invite was removed, false otherwise.
  327.      */
  328.     public function removeInvite($ref{
  329.         $this->registerHandler();
  330.         if (!$this->invites_db->open()) {
  331.             trigger_error(msg('cannot-open-inv-db')E_USER_WARNING);
  332.             return false;
  333.         }
  334.  
  335.         // remove the invite
  336.         $rslt $this->invites_db->delete($ref);
  337.         trigger_error(msg('invite-removed'array($ref))E_USER_WARNING);
  338.         $this->clean();
  339.         return $this->finish($rslt);
  340.     }
  341.  
  342.     /**
  343.      * Perform e-mail verification for the current user according to the configuration
  344.      * for this site.
  345.      * @param mail The e-mail of the user.
  346.      * @param attrs The array of attributes of the user.
  347.      * @return boolean true if verification succeeds or was not performed, false otherwise.
  348.      */
  349.     protected function emailVerify($mail$attrs{
  350.         $mail_attr $this->cfg->getEmailVerifyAttribute();
  351.         if ($this->cfg->doEmailVerify()) {
  352.             // empty attribute, configuration error!
  353.             if (empty($mail_attr)) {
  354.                 trigger_error(msg('mail-attr-err')E_USER_WARNING);
  355.                 return false;
  356.             }
  357.             // attribute not set, cannot verify
  358.             if (!isset($attrs[$mail_attr])) {
  359.                 trigger_error(msg('missing-mail-attr'array($mail_attr))E_USER_WARNING);
  360.                 return false;
  361.             }
  362.  
  363.             $alg_re $this->cfg->getEmailVerifyAlgRegEx();
  364.             $val_re $this->cfg->getEmailVerifyRegEx();
  365.  
  366.             // support for attributes with multiple values
  367.             $mail_attrs $attrs[$mail_attr];
  368.             if (!is_array($attrs[$mail_attr])) {
  369.                 $mail_attrs array($attrs[$mail_attr]);
  370.             }
  371.  
  372.             $match false;
  373.             foreach ($mail_attrs as $attr_val{
  374.                 // extract function for each value
  375.                 $alg "sprintf(\"%s\",";
  376.                 if (!empty($alg_re)) {
  377.                     if (!preg_match("/".$alg_re."/"$attr_val$vals_alg)) {
  378.                         trigger_error(msg('mail-attr-alg-err'array($mail_attr$attr_val))E_USER_WARNING);
  379.                         continue;
  380.                     }
  381.                     $alg $vals_alg[1]."(";
  382.                 }
  383.  
  384.                 // extract value
  385.                 if (!preg_match("/".$val_re."/"$attr_val$vals_value)) {
  386.                     trigger_error(msg('mail-attr-val-err'array($mail_attr$attr_val))E_USER_WARNING);
  387.                     continue;
  388.                 }
  389.                 $received[$alg$vals_value[1];
  390.                 $match true;
  391.             }
  392.             // none of the mail attributes matched the regular expressions
  393.             if (!$match{
  394.                 return false;
  395.             }
  396.  
  397.             // check all possibilities
  398.             foreach ($received as $alg => $value{
  399.                 $computed_value = eval("return ".$alg."\"".$mail."\");");
  400.                 if ($computed_value != $value{
  401.                     // no match, continue searching
  402.                     //trigger_error(msg('mail-verify-err', array($mail, $computed_value, $value)), E_USER_WARNING);
  403.                     continue;
  404.                 }
  405.                 // match found, end here
  406.                 trigger_error(msg('mail-verify-ok'array($mailpreg_replace("/\(.*$/"""$alg)$value))E_USER_WARNING);
  407.                 return true;
  408.             }
  409.             // verification is enabled but we were unable to find any matching e-mail
  410.             trigger_error(msg('mail-verify-err'array($mail))E_USER_WARNING);
  411.             return false;
  412.         }
  413.         // verification disabled
  414.         return true;
  415.     }
  416.  
  417.     /**
  418.      * Close databases and return the same value received as a parameter.
  419.      * @param value The value that must be returned.
  420.      * @return mixed The first param.
  421.      */
  422.     protected function finish($value{
  423.         $this->invites_db->close();
  424.         $this->authz_db->close();
  425.         return $value;
  426.     }
  427.  
  428. }
  429.  
  430. ?>

Documentation generated on Wed, 13 Oct 2010 15:06:18 +0200 by phpDocumentor 1.4.3