ef7dd37ed9cdcd9af13a09a1aec1203866ae98e2
[living-lab-site.git] / application / models / users_model.php
1 <?php
2
3 /**
4  * Class Users_model models user information from DB
5  * 
6  * @category    Model
7  * @author              calinburloiu
8  *
9  */
10 class Users_model extends CI_Model {
11         public $db = NULL;
12
13         public function __construct()
14         {
15                 parent::__construct();
16
17                 if ($this->db === NULL)
18                 {
19                         $this->load->library('singleton_db');
20                         $this->db = $this->singleton_db->connect();
21                 }
22         }
23
24         /**
25          * Check authentication credentials. $username can be username or e-mail.
26          * 
27          * @param string $username
28          * @param string $password
29          * @return mixed can return FALSE if authentication failed, a DB row as an
30          * associative array if authentication was succesful or an associative
31          * array with LDAP user information if authentication with LDAP was
32          * successful but the user logged in for the first time and it does not
33          * have an entry in `users` table yet. The key 'auth_src' distinguishes
34          * which associative array was returned:
35          * <ul>
36          *   <li>'internal' or 'ldap': a DB row</li>
37          *   <li>'ldap_first_time': LDAP user information</li>
38          * </ul>
39          */
40         public function login($username, $password)
41         {
42                 $this->load->helper('email');
43                 
44                 // User logs with e-mail address.
45                 if (! valid_email($username))
46                         $cond_user = "username = '$username'";
47                 else
48                         $cond_user = "email = '$username'";
49                 
50                 $enc_password = sha1($password);
51                 
52                 // TODO select only required fields.
53                 $query = $this->db->query("SELECT * FROM `users` 
54                         WHERE $cond_user
55                                 AND (auth_src = 'ldap' OR password = '$enc_password')");
56                 
57                 // It is possible that the user has a LDAP account but he's
58                 // authenticating here for the first time so it does not have an entry
59                 // in `users` table.
60                 if ($query->num_rows() !== 1)
61                 {
62                         $ldap_userdata = $this->ldap_login($username, $password);
63                         $userdata = $this->convert_ldap_userdata($ldap_userdata);
64                         $this->register($userdata);
65                         
66                         $user = $this->login($username, $password);
67                         $user['import'] = TRUE;
68                         return $user;
69                         
70                         /* foreach ($ldap_userdata as $k => $v)
71                         {
72                                 echo "<h1>$k</h1>";
73                                 print_r($v);
74                         }
75                         die(); */
76                 }
77                 
78                 $user = $query->row_array();
79                 
80                 // Authenticate with LDAP.
81                 if ($user['auth_src'] == 'ldap')
82                         return ($this->ldap_login($username, $password) !== FALSE 
83                                 ? $user : FALSE);
84                 
85                 // If we are here internal authentication has successful.
86                 return $user;
87         }
88         
89         /**
90          * Converts an array returned by LDAP login to an array which contains
91          * user data ready to be used in `users` DB.
92          * 
93          * @param array $ldap_userdata
94          * @return array
95          */
96         public function convert_ldap_userdata($ldap_userdata)
97         {
98                 $userdata['username'] = $ldap_userdata['uid'][0];
99                 $userdata['email'] = $ldap_userdata['mail'][0];
100                 $userdata['first_name'] = $ldap_userdata['givenname'][0];
101                 $userdata['last_name'] = $ldap_userdata['sn'][0];
102                 
103                 $userdata['auth_src'] = 'ldap';
104                 
105                 return $userdata;
106         }
107         
108         /**
109         * Login with LDAP.
110         *
111         * @param string $username
112         * @param string $password
113         * @return boolean
114         * @author  Alex Herișanu, Răzvan Deaconescu, Călin-Andrei Burloiu
115         */
116         public function ldap_login($username, $password)
117         {
118                 $this->config->load('ldap');
119                 
120                 // First connection: binding.
121                 // TODO exception
122                 $ds = ldap_connect($this->config->item('ldap_server')) or die("Can't connect to ldap server.\n");
123                 if (!@ldap_bind($ds, $this->config->item('ldap_bind_user'),
124                         $this->config->item('ldap_bind_password'))) 
125                 {
126                         ldap_close($ds);
127                         die("Can't connect to ".$this->config->item('ldap_server')."\n");
128                         return FALSE;
129                 }
130                 $sr = ldap_search($ds, "dc=cs,dc=curs,dc=pub,dc=ro", "(uid=" . $username . ")");
131                 if (ldap_count_entries($ds, $sr) > 1)
132                 die("Multiple entries with the same uid in LDAP database??");
133                 if (ldap_count_entries($ds, $sr) < 1) {
134                         ldap_close($ds);
135                         return FALSE;
136                 }
137                 
138                 $info = ldap_get_entries($ds, $sr);
139                 $dn = $info[0]["dn"];
140                 ldap_close($ds);
141                 
142                 // Second connection: connect with user's credentials.
143                 $ds = ldap_connect($this->config->item('ldap_server')) or die("Can't connect to ldap server\n");
144                 if (!@ldap_bind($ds, $dn, $password) or $password == '') {
145                         ldap_close($ds);
146                         return FALSE;
147                 }
148                 
149                 // Verifify if DN belongs to the requested OU.
150                 $info[0]['ou_ok'] = $this->ldap_dn_belongs_ou( $dn, $this->config->item('ldap_req_ou') );
151                 
152                 // Set authentication source.
153                 $info[0]['auth_src'] = 'ldap_first_time';
154                 
155                 return $info[0];
156         }
157         
158         /**
159         * Verify if a user belongs to a group.
160         * 
161         * @param string $dn = "ou=Student,ou=People..."
162         * @param array $ou = array ("Student", etc
163         * @return TRUE or FALSE
164         * @author  Răzvan Herișanu, Răzvan Deaconescu, Călin-Andrei Burloiu
165         */
166         public function ldap_dn_belongs_ou($dn, $ou)
167         {
168                 if (!is_array($ou))
169                         $ou = array ($ou);
170                 
171                 $founded = FALSE;
172                 $words = explode(',', $dn);
173                 foreach ($words as $c) {
174                         $parts = explode("=", $c);
175                         $key = $parts[0];
176                         $value = $parts[1];
177                 
178                         if (strtolower($key) == "ou" && in_array($value, $ou) )
179                                 $founded = TRUE;
180                 }
181                 
182                 return $founded;
183         }
184         
185         /**
186          * Adds a new user to DB.
187          * 
188          * @param array $data   corresponds to DB columns
189          */
190         public function register($data)
191         {
192                 $this->load->helper('array');
193                 
194                 // TODO verify mandatory data existance
195                 
196                 // Process data.
197                 if (isset($data['password']))
198                         $data['password'] = sha1($data['password']);
199                 // TODO picture data: save, convert, make it thumbnail
200                 
201                 $cols = '';
202                 $vals = '';
203                 foreach ($data as $col=> $val)
204                 {
205                         $cols .= "$col, ";
206                         if (is_int($val))
207                                 $vals .= "$val, ";
208                         else
209                                 $vals .= "'$val', ";
210                 }
211                 $cols = substr($cols, 0, -2);
212                 $vals = substr($vals, 0, -2);
213                 
214                 $query = $this->db->query("INSERT INTO `users`
215                         ($cols)
216                         VALUES ($vals)");
217                 
218                 // TODO exception on failure
219                 return $query;
220         }
221         
222         /**
223          * Returns data from `users` table for user with $user_id.
224          * 
225          * @param int $user_id
226          */
227         public function get_userdata($user_id)
228         {
229                 $query = $this->db->query("SELECT * from `users`
230                         WHERE id = $user_id");
231                 
232                 if ($query->num_rows() === 0)
233                         return FALSE;
234                 
235                 return $query->row_array();
236         }
237         
238         /**
239          * Modifies data from `users` table for user with $user_id.
240          * 
241          * @param int $user_id
242          * @param array $data   key-value pairs with columns and new values to be
243          * modified
244          */
245         public function set_userdata($user_id, $data)
246         {
247                 // TODO verify mandatory data existance
248                 
249                 // Process data.
250                 if (isset($data['password']))
251                         $data['password'] = sha1($data['password']);
252                 // TODO picture data: save, convert, make it thumbnail
253                 
254                 $set = '';
255                 foreach ($data as $col => $val)
256                 {
257                         if (is_int($val))
258                                 $set .= "$col = $val, ";
259                         else
260                                 $set .= "$col = '$val', ";
261                 }
262                 $set = substr($set, 0, -2);
263                 
264                 $query_str = "UPDATE `users`
265                         SET $set WHERE id = $user_id";
266                 //echo "<p>$query_str</p>";
267                 $query = $this->db->query($query_str);
268                 
269                 // TODO exception
270                 return $query;
271         }
272 }
273
274 /* End of file users_model.php */
275 /* Location: ./application/models/users_model.php */