source: contrib/davical/inc/auth-functions.php @ 3733

Revision 3733, 7.4 KB checked in by gabriel.malheiros, 13 years ago (diff)

Ticket #1541 - <Davical customizado para o Expresso.Utiliza Caldav e CardDav?>

Line 
1<?php
2/**
3* The authentication handling plugins can be used by the Session class to
4* provide authentication.
5*
6* Each authenticate hook needs to:
7*   - Accept a username / password
8*   - Confirm the username / password are correct
9*   - Create (or update) a 'usr' record in our database
10*   - Return the 'usr' record as an object
11*   - Return === false when authentication fails
12*
13* It can expect that:
14*   - Configuration data will be in $c->authenticate_hook['config'], which might be an array, or whatever is needed.
15*
16* In order to be called:
17*   - This file should be included
18*   - $c->authenticate_hook['call'] should be set to the name of the plugin
19*   - $c->authenticate_hook['config'] should be set up with any configuration data for the plugin
20*
21* @package   davical
22* @subpackage   authentication
23* @author    Andrew McMillan <andrew@mcmillan.net.nz>
24* @copyright Catalyst IT Ltd, Morphoss Ltd
25* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
26*/
27
28require_once("DataUpdate.php");
29
30
31/**
32* Create a default home calendar for the user.
33* @param string $username The username of the user we are creating relationships for.
34*/
35function CreateHomeCalendar( $username ) {
36  global $session, $c;
37  if ( ! isset($c->home_calendar_name) || strlen($c->home_calendar_name) == 0 ) return true;
38
39  $usr = getUserByName( $username );
40  $parent_path = "/".$username."/";
41
42  /************** Modificado ****************   
43  */
44  $calendar_path = $parent_path . $c->home_calendar_name."/";
45  //$calendar_path = $parent_path;
46 
47  $dav_etag = md5($usr->user_no . $calendar_path);
48  $sql = 'INSERT INTO collection (user_no, parent_container, dav_name, dav_etag, dav_displayname, is_calendar, created, modified, resourcetypes) ';
49  $sql .= 'VALUES( :user_no, :parent_container, :calendar_path, :dav_etag, :displayname, true, current_timestamp, current_timestamp, :resourcetypes );';
50  $params = array(
51      ':user_no' => $usr->user_no,
52      ':parent_container' => $parent_path,
53      ':calendar_path' => $calendar_path,
54      ':dav_etag' => $dav_etag,
55      ':displayname' => $usr->fullname,
56      ':resourcetypes' => '<DAV::collection/><urn:ietf:params:xml:ns:caldav:calendar/>'
57  );
58  $qry = new AwlQuery( $sql, $params );
59  if ( $qry->Exec() ) {
60    $c->messages[] = i18n("Home calendar added.");
61    dbg_error_log("User",":Write: Created user's home calendar at '%s'", $calendar_path );
62  }
63  else {
64    $c->messages[] = i18n("There was an error writing to the database.");
65    return false;
66  }
67  return true;
68}
69
70
71/**
72* Defunct function for creating default relationships.
73* @param string $username The username of the user we are creating relationships for.
74*/
75function CreateDefaultRelationships( $username ) {
76  return true;
77}
78
79
80/**
81* Update the local cache of the remote user details
82* @param object $usr The user details we read from the remote.
83*/
84function UpdateUserFromExternal( &$usr ) {
85  global $c;
86  /**
87  * When we're doing the create we will usually need to generate a user number
88  */
89  if ( !isset($usr->user_no) || intval($usr->user_no) == 0 ) {
90    $qry = new AwlQuery( "SELECT nextval('usr_user_no_seq');" );
91    $qry->Exec('Login',__LINE__,__FILE__);
92    $sequence_value = $qry->Fetch(true);  // Fetch as an array
93    $usr->user_no = $sequence_value[0];
94  }
95
96  $qry = new AwlQuery('SELECT * FROM usr WHERE user_no = :user_no', array(':user_no' => $usr->user_no) );
97  if ( $qry->Exec('Login',__LINE__,__FILE__) && $qry->rows() == 1 ) {
98    $type = "UPDATE";
99    if ( $old = $qry->Fetch() ) {
100      $changes = false;
101      foreach( $usr AS $k => $v ) {
102        if ( $old->{$k} != $v ) {
103          $changes = true;
104          dbg_error_log("Login","User '%s' field '%s' changed from '%s' to '%s'", $usr->username, $k, $old->{$k}, $v );
105          break;
106        }
107      }
108      if ( !$changes ) {
109        dbg_error_log("Login","No changes to user record for '%s' - leaving as-is.", $usr->username );
110        if ( isset($usr->active) && $usr->active == 'f' ) return false;
111        return; // Normal case, if there are no changes
112      }
113      else {
114        dbg_error_log("Login","Changes to user record for '%s' - updating.", $usr->username );
115      }
116    }
117  }
118  else
119    $type = "INSERT";
120
121  $params = array();
122  if ( $type != 'INSERT' ) $params[':user_no'] = $usr->user_no;
123  $qry = new AwlQuery( sql_from_object( $usr, $type, 'usr', 'WHERE user_no= :user_no' ), $params );
124  $qry->Exec('Login',__LINE__,__FILE__);
125
126  /**
127  * We disallow login by inactive users _after_ we have updated the local copy
128  */
129  if ( isset($usr->active) && ($usr->active === 'f' || $usr->active === false) ) return false;
130
131  if ( $type == 'INSERT' ) {
132    $qry = new AwlQuery( 'INSERT INTO principal( type_id, user_no, displayname, default_privileges) SELECT 1, user_no, fullname, :privs::INT::BIT(24) FROM usr WHERE username=:username',
133                          array( ':privs' => privilege_to_bits($c->default_privileges), ':username' => $usr->username) );
134    $qry->Exec('Login',__LINE__,__FILE__);
135    CreateHomeCalendar($usr->username);
136  }
137}
138
139
140/**
141* Authenticate against a different PostgreSQL database which contains a usr table in
142* the AWL format.
143*
144* Use this as in the following example config snippet:
145*
146* require_once('auth-functions.php');
147*  $c->authenticate_hook = array(
148*      'call'   => 'AuthExternalAwl',
149*      'config' => array(
150*           // A PgSQL database connection string for the database containing user records
151*          'connection[]' => 'dbname=wrms host=otherhost port=5433 user=general',
152*           // Which columns should be fetched from the database
153*          'columns'    => "user_no, active, email_ok, joined, last_update AS updated, last_used, username, password, fullname, email",
154*           // a WHERE clause to limit the records returned.
155*          'where'    => "active AND org_code=7"
156*      )
157*  );
158*
159*/
160function AuthExternalAWL( $username, $password ) {
161  global $c;
162
163  $persistent = isset($c->authenticate_hook['config']['use_persistent']) && $c->authenticate_hook['config']['use_persistent'];
164
165  if ( isset($c->authenticate_hook['config']['columns']) )
166    $cols = $c->authenticate_hook['config']['columns'];
167  else
168    $cols = '*';
169
170  if ( isset($c->authenticate_hook['config']['where']) )
171    $andwhere = ' AND '.$c->authenticate_hook['config']['where'];
172  else
173    $andwhere = '';
174
175  $qry = new AwlQuery('SELECT '.$cols.' FROM usr WHERE lower(username) = :username '. $andwhere, array( ':username' => strtolower($username) ));
176  $authconn = $qry->SetConnection($c->authenticate_hook['config']['connection'], ($persistent ? array(PDO::ATTR_PERSISTENT => true) : null));
177  if ( ! $authconn ) {
178    echo <<<EOERRMSG
179  <html><head><title>Database Connection Failure</title></head><body>
180  <h1>Database Error</h1>
181  <h3>Could not connect to PostgreSQL database</h3>
182  </body>
183  </html>
184EOERRMSG;
185    exit(1);
186  }
187
188  if ( $qry->Exec('Login',__LINE__,__FILE__) && $qry->rows() == 1 ) {
189    $usr = $qry->Fetch();
190    if ( session_validate_password( $password, $usr->password ) ) {
191      UpdateUserFromExternal($usr);
192
193      /**
194      * We disallow login by inactive users _after_ we have updated the local copy
195      */
196      if ( isset($usr->active) && $usr->active == 'f' ) return false;
197
198      $qry = new AwlQuery('SELECT * FROM dav_principal WHERE username = :username', array(':username' => $usr->username) );
199      if ( $qry->Exec() && $qry->rows() == 1 ) {
200        $principal = $qry->Fetch();
201        return $principal;
202      }
203      return $usr; // Somewhat optimistically
204    }
205  }
206
207  return false;
208
209}
Note: See TracBrowser for help on using the repository browser.