4 * Class Users_model models user information from DB
10 class Users_model extends CI_Model {
13 public function __construct()
15 parent::__construct();
17 if ($this->db === NULL)
19 $this->load->library('singleton_db');
20 $this->db = $this->singleton_db->connect();
25 * Check authentication credentials. $username can be username or e-mail.
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:
36 * <li>'internal' or 'ldap': a DB row</li>
37 * <li>'ldap_first_time': LDAP user information</li>
40 public function login($username, $password)
42 $this->load->helper('email');
44 // User logs with e-mail address.
45 if (! valid_email($username))
46 $cond_user = "username = '$username'";
48 $cond_user = "email = '$username'";
50 $enc_password = sha1($password);
52 // TODO select only required fields.
53 $query = $this->db->query("SELECT u.*, a.activation_code
54 FROM `users` u LEFT JOIN `users_unactivated` a ON (u.id = a.user_id)
56 AND (auth_src = 'ldap' OR password = '$enc_password')");
58 // It is possible that the user has a LDAP account but he's
59 // authenticating here for the first time so it does not have an entry
61 if ($query->num_rows() === 0)
63 $ldap_userdata = $this->ldap_login($username, $password);
64 if ($ldap_userdata === FALSE)
66 $userdata = $this->convert_ldap_userdata($ldap_userdata);
67 $this->register($userdata);
69 $user = $this->login($username, $password);
70 $user['import'] = TRUE;
74 $user = $query->row_array();
76 // Authenticate with LDAP.
77 if ($user['auth_src'] == 'ldap'
78 && ! $this->ldap_login($username, $password))
81 if (empty($user['email']) || empty($user['first_name'])
82 || empty($user['last_name']))
83 $user['import'] = TRUE;
85 // Update last login time.
86 $this->db->query("UPDATE `users`
87 SET last_login = UTC_TIMESTAMP()
88 WHERE username = '$username'");
90 // If we are here internal authentication has successful.
95 * Converts an array returned by LDAP login to an array which contains
96 * user data ready to be used in `users` DB.
98 * @param array $ldap_userdata
101 public function convert_ldap_userdata($ldap_userdata)
103 $userdata['username'] = $ldap_userdata['uid'][0];
104 $userdata['email'] = $ldap_userdata['mail'][0];
105 $userdata['first_name'] = $ldap_userdata['givenname'][0];
106 $userdata['last_name'] = $ldap_userdata['sn'][0];
108 $userdata['auth_src'] = 'ldap';
116 * @param string $username
117 * @param string $password
119 * @author Alex Herișanu, Răzvan Deaconescu, Călin-Andrei Burloiu
121 public function ldap_login($username, $password)
123 $this->config->load('ldap');
125 // First connection: binding.
127 $ds = ldap_connect($this->config->item('ldap_server')) or die("Can't connect to ldap server.\n");
128 if (!@ldap_bind($ds, $this->config->item('ldap_bind_user'),
129 $this->config->item('ldap_bind_password')))
132 die("Can't connect to ".$this->config->item('ldap_server')."\n");
135 $sr = ldap_search($ds, "dc=cs,dc=curs,dc=pub,dc=ro", "(uid=" . $username . ")");
136 if (ldap_count_entries($ds, $sr) > 1)
137 die("Multiple entries with the same uid in LDAP database??");
138 if (ldap_count_entries($ds, $sr) < 1) {
143 $info = ldap_get_entries($ds, $sr);
144 $dn = $info[0]["dn"];
147 // Second connection: connect with user's credentials.
148 $ds = ldap_connect($this->config->item('ldap_server')) or die("Can't connect to ldap server\n");
149 if (!@ldap_bind($ds, $dn, $password) or $password == '') {
154 // Verifify if DN belongs to the requested OU.
155 $info[0]['ou_ok'] = $this->ldap_dn_belongs_ou( $dn, $this->config->item('ldap_req_ou') );
157 // Set authentication source.
158 $info[0]['auth_src'] = 'ldap_first_time';
164 * Verify if a user belongs to a group.
166 * @param string $dn = "ou=Student,ou=People..."
167 * @param array $ou = array ("Student", etc
168 * @return TRUE or FALSE
169 * @author Răzvan Herișanu, Răzvan Deaconescu, Călin-Andrei Burloiu
171 public function ldap_dn_belongs_ou($dn, $ou)
177 $words = explode(',', $dn);
178 foreach ($words as $c) {
179 $parts = explode("=", $c);
183 if (strtolower($key) == "ou" && in_array($value, $ou) )
191 * Adds a new user to DB.
192 * Do not add join_date and last_login column, they will be automatically
195 * @param array $data corresponds to DB columns
197 public function register($data)
199 $this->load->helper('array');
201 // TODO verify mandatory data existance
204 if (isset($data['password']))
205 $data['password'] = sha1($data['password']);
206 // TODO picture data: save, convert, make it thumbnail
208 if (empty($data['birth_date']))
209 $data['birth_date'] = NULL;
213 foreach ($data as $col=> $val)
225 else if (is_string($val))
228 $cols = substr($cols, 0, -2);
229 $vals = substr($vals, 0, -2);
231 $query = $this->db->query("INSERT INTO `users`
232 ($cols, registration_date, last_login)
233 VALUES ($vals, utc_timestamp(), utc_timestamp())");
234 if ($query === FALSE)
237 // If registered with internal authentication it needs to activate
239 if ($data['auth_src'] == 'internal')
241 $activation_code = Users_model::gen_activation_code($data['username']);
242 $user_id = $this->get_user_id($data['username']);
243 $query = $this->db->query("INSERT INTO `users_unactivated`
244 (user_id, activation_code)
245 VALUES ($user_id, '$activation_code')");
246 $this->send_activation_email($user_id, $data['email'],
247 $activation_code, $data['username']);
250 // TODO exception on failure
254 public function get_user_id($username)
256 $query = $this->db->query("SELECT id FROM `users`
257 WHERE username = '$username'");
259 if ($query->num_rows() === 0)
262 return $query->row()->id;
265 // TODO cleanup account activation
266 public function cleanup_account_activation()
272 * Activated an account for an user having $user_id with $activation_code.
274 * @param int $user_id
275 * @param string $activation_code hexa 16 characters string
276 * @return returns TRUE if activation was successful and FALSE otherwise
278 public function activate_account($user_id, $activation_code)
280 $query = $this->db->query("SELECT * FROM `users_unactivated`
281 WHERE user_id = $user_id
282 AND activation_code = '$activation_code'");
284 if ($query->num_rows() === 0)
287 $this->db->query("DELETE FROM `users_unactivated`
288 WHERE user_id = $user_id");
293 public function send_activation_email($user_id, $email = NULL,
294 $activation_code = NULL, $username = NULL)
296 if (!$activation_code || !$email || !$username)
303 $userdata = $this->get_userdata($user_id,
304 $cols. "a.activation_code, username");
305 $activation_code =& $userdata['activation_code'];
308 $email =& $userdata['email'];
309 $username =& $userdata['username'];
312 if ($activation_code === NULL)
315 $subject = '['. $this->config->item('site_name')
316 . '] Account Activation';
318 site_url("user/activate/$user_id/code/$activation_code");
319 $msg = sprintf($this->lang->line('user_activation_email_content'),
320 $username, $this->config->item('site_name'), site_url(),
321 $activation_url, $activation_code);
322 $headers = "From: ". $this->config->item('noreply_email');
324 return mail($email, $subject, $msg, $headers);
327 public function recover_password($username, $email)
329 $userdata = $this->get_userdata($username, 'email, username, id');
331 if (strcmp($userdata['email'], $email) !== 0)
334 $recovered_password = Users_model::gen_password();
336 $this->set_userdata(intval($userdata['id']), array('password'=>
337 $recovered_password));
339 $subject = '['. $this->config->item('site_name')
340 . '] Password Recovery';
341 $msg = sprintf($this->lang->line('user_password_recovery_email_content'),
342 $username, $this->config->item('site_name'), site_url(),
343 $recovered_password);
344 $headers = "From: ". $this->config->item('noreply_email');
346 mail($email, $subject, $msg, $headers);
352 * Returns data from `users` table. If $user is int it is used as an
353 * id, if it is string it is used as an username.
356 * @param string $table_cols (optional) string with comma separated
357 * `users` table column names. Use a.activation_code to check user's
358 * account activation_code. If this value is NULL than the account is
360 * @return array associative array with userdata from DB
362 public function get_userdata($user, $table_cols = '*')
365 $cond = "id = $user";
367 $cond = "username = '$user'";
369 $query = $this->db->query("SELECT $table_cols
370 FROM `users` u LEFT JOIN `users_unactivated` a
371 ON (u.id = a.user_id)
374 if ($query->num_rows() === 0)
377 $userdata = $query->row_array();
379 // Post process userdata.
380 if (isset($userdata['picture']))
382 $userdata['picture_thumb'] = site_url(
383 "data/user_pictures/{$userdata['picture']}-thumb.jpg");
384 $userdata['picture'] = site_url(
385 "data/user_pictures/{$userdata['picture']}");
392 * Modifies data from `users` table for user with $user_id.
394 * @param int $user_id
395 * @param array $data key-value pairs with columns and new values to be
397 * @return boolean returns TRUE on success and FALSE otherwise
399 public function set_userdata($user_id, $data)
401 // TODO verify mandatory data existance
404 if (isset($data['password']))
405 $data['password'] = sha1($data['password']);
406 // TODO picture data: save, convert, make it thumbnail
408 if (empty($data['birth_date']))
409 $data['birth_date'] = NULL;
412 foreach ($data as $col => $val)
416 $set .= "$col = NULL, ";
421 $set .= "$col = $val, ";
422 else if (is_string($val))
423 $set .= "$col = '$val', ";
425 $set = substr($set, 0, -2);
427 $query_str = "UPDATE `users`
428 SET $set WHERE id = $user_id";
429 //echo "<p>$query_str</p>";
430 $query = $this->db->query($query_str);
436 public static function gen_activation_code($str = '')
438 $ci =& get_instance();
440 $activation_code = substr(
441 sha1(''. $str. $ci->config->item('encryption_key')
446 return $activation_code;
449 public static function gen_password()
451 $ci =& get_instance();
453 $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.?!_-';
454 $len_chars = strlen($chars);
455 $enc_key = $ci->config->item('encryption_key');
456 $len_enc_key = strlen($enc_key);
459 for ($p = 0; $p < $length; $p++)
461 $i = (mt_rand(1, 100) * ord($enc_key[ mt_rand(0, $len_enc_key-1) ]))
463 $password .= $chars[$i];
469 public static function roles_to_string($roles)
471 $ci =& get_instance();
472 $ci->lang->load('user');
474 if ($roles == USER_ROLE_STANDARD)
475 return $ci->lang->line('user_role_standard');
480 if ($roles & USER_ROLE_ADMIN)
481 $str_roles .= $ci->lang->line('user_role_admin') . '; ';
488 /* End of file users_model.php */
489 /* Location: ./application/models/users_model.php */