Ushahidi_Web /application/models/user.php

Language PHP Lines 382
MD5 Hash 9921a182f124813ee66949633fc94491 Estimated Cost $5,117 (why?)
Repository git://github.com/ushahidi/Ushahidi_Web.git View Raw File View Project SPDX
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
<?php
/**
 * Model for users for the Auth Module
 *
 * $Id: user.php 3352 2008-08-18 09:43:56BST atomless $
 *
 * PHP version 5
 * LICENSE: This source file is subject to LGPL license
 * that is available through the world-wide-web at the following URI:
 * http://www.gnu.org/copyleft/lesser.html
 * @author     Ushahidi Team <team@ushahidi.com>
 * @package    Ushahidi - http://source.ushahididev.com
 * @subpackage Models
 * @copyright  Ushahidi - http://www.ushahidi.com
 * @license    http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License (LGPL)
 */

class User_Model extends Auth_User_Model {

	protected $has_many = array('alert', 'comment', 'openid', 'private_message', 'rating');
	
	/**
	 * Creates a basic user and assigns to login and member roles
	 * 
	 * @param   string  email
	 * @param   string  password
	 * @param   string  riverid user id
	 * @return  object  ORM object from saving the user
	 */
	public static function create_user($email, $password, $riverid=FALSE, $name=FALSE)
	{
		$user = ORM::factory('user');

		$user->email = $email;
		$user->username = User_Model::random_username();
		$user->password = $password;

		if (! empty($name))
		{
			$user->name = $name;
		}
		else
		{
			$user->needinfo = 1;
		}

		$user->riverid = ( $riverid == false ) ? '' : $riverid;

		// Add New Roles if:
		//    1. We don't require admin to approve users (will be added when admin approves)
		//    2. We don't require users to first confirm their email address (will be added
		//       when user confirms if the admin doesn't have to first approve the user)
		if (Kohana::config('settings.manually_approve_users') == 0
			AND Kohana::config('settings.require_email_confirmation') == 0)
		{
			$user->add(ORM::factory('role', 'login'));
			$user->add(ORM::factory('role', 'member'));
		}

		return $user->save();
	}

	/**
	 * Gets the email address of a user
	 * @return string
	 */
	public static function get_email($user_id)
	{
		$user = ORM::factory('user')->find($user_id);
		return $user->email;
	}

	/**
	 * Returns data for a user based on username
	 * @return object
	 */
	public static function get_user_by_username($username)
	{
		$user = ORM::factory('user')->where(array('username'=>$username))->find();
		return $user;
	}

	/**
	 * Returns data for a user based on email
	 * @return object
	 */
	public static function get_user_by_email($email)
	{
		$user = ORM::factory('user')->where(array('email'=>$email))->find();
		return $user;
	}

	/**
	 * Returns data for a user based on user id
	 * @return object
	 */
	public static function get_user_by_id($user_id)
	{
		$user = ORM::factory('user')->where(array('id'=>$user_id))->find();
		return $user;
	}

	/**
	 * Returns data for a user based on river id
	 * @return object
	 */
	public static function get_user_by_river_id($river_id)
	{
		$user = ORM::factory('user')->where(array('riverid'=>$river_id))->find();
		return $user;
	}

	/**
	 * Returns all users with public profiles
	 * @return object
	 */
	public static function get_public_users()
	{
		$users = ORM::factory('user')
			->where(array('public_profile'=>1)) // Only show public profiles
			->notlike(array('username'=>'@')) // We only want to show profiles that don't have email addresses as usernames
			->find_all();
		return $users;
	}

	/**
	 * Custom validation for this model - complements the default validate()
	 *
	 * @param   array  array to validate
	 * @param   Auth   instance of Auth class; used for testing purposes
	 * @return bool TRUE if validation succeeds, FALSE otherwise
	 */
	public static function custom_validate(array & $post, Auth $auth = NULL)
	{
		// Initalize validation
		$post = Validation::factory($post)
				->pre_filter('trim', TRUE);
		
		if ($auth === NULL)
		{
			$auth = new Auth;
		}

		$post->add_rules('username','required','length[3,100]', 'alpha_numeric');
		$post->add_rules('name','required','length[3,100]');
        $post->add_rules('email','required','email','length[4,64]');

		// If user id is not specified, check if the username already exists
		if (empty($post->user_id))
		{
			$post->add_callbacks('username', array('User_Model', 'unique_value_exists'));
			$post->add_callbacks('email', array('User_Model', 'unique_value_exists'));
		}
		
		// Make sure we have a value for password length to avoid PHP error for missing length[] function
		$password_length = Kohana::config('auth.password_length');
		$password_length = ( ! empty($password_length)) ? $password_length : '1,127';

		// Only check for the password if the user id has been specified and we are passing a pw
		if (isset($post->user_id) AND isset($post->password))
		{
			$post->add_rules('password','required', 'length['.$password_length.']');
		}

		// If Password field is not blank and is being passed
		if ( isset($post->password) AND
			(! empty($post->password) OR (empty($post->password) AND ! empty($post->password_again))))
		{
			$post->add_rules('password','required','length['.$password_length.']', 'matches[password_again]');
		}

		$post->add_rules('role','required','length[3,30]', 'alpha_numeric');
		$post->add_rules('notify','between[0,1]');

		if ( ! $auth->logged_in('superadmin'))
		{
			$post->add_callbacks('role', array('User_Model', 'prevent_superadmin_modification'));
		}

		// Additional validation checks
		Event::run('ushahidi_action.user_submit_admin', $post);

		// Return
		return $post->validate();
	}

	/**
	 * Checks if a password is correct
	 *
	 * @param   int  user id
	 * @param   string   password to check
	 * @return bool TRUE if the password matches, FALSE otherwise
	 */
	public static function check_password($user_id,$password,$force_standard_method=FALSE)
	{
		$user = ORM::factory('user',$user_id);

		// RiverID or Standard method?
		if (kohana::config('riverid.enable') == TRUE
        	AND ! empty($user->riverid)
        	AND ! $force_standard_method)
		{
			// RiverID
			$riverid = new RiverID;
			$riverid->email = $user->email;
			$riverid->password = $password;
			if ($riverid->checkpassword() != FALSE)
			{
				return TRUE;
			}
			else
			{
				// TODO: Maybe return the error message?
				return FALSE;
			}
		}
		else
		{
			// Standard Local
			$auth = Auth::instance();
			return $auth->check_password($user_id,$password);
		}
	}

	/**
	 * Checks if the value in the specified field exists in database
	 */
	public static function unique_value_exists(Validation $post, $field)
	{
		$exists = (bool) ORM::factory('user')->where($field, $post[$field])->count_all();
		if ($exists)
		{
			$post->add_error($field, 'exists');
		}
	}

	/**
	 * Ensures that only a superadmin can modify superadmin users, or upgrade a user to superadmin
	 * @note this assumes the currently logged-in user isn't a superadmin
	 */
	public static function prevent_superadmin_modification(Validation $post, $field)
	{
		if ($post[$field] == 'superadmin')
		{
			$post->add_error($field, 'superadmin_modify');
		}
	}

	/*
	* Creates a random int value for a username that isn't already represented in the database
	*/
	public function random_username()
	{
		while ($random = mt_rand(1000,mt_getrandmax()))
		{
			$find_username = ORM::factory('user')->where('username',$random)->count_all();
			if ($find_username == 0)
			{
				return $random;
			}
		}

		return FALSE;
	}


	/**
	 * Overrides the default delete method for the ORM.
	 * Deletes roles associated with the user before user is removed from DB.
	 */
	public function delete()
	{
		$table_prefix = Kohana::config('database.default.table_prefix');
		
		// Remove assigned roles
		// Have to use db->query() since we don't have an ORM model for roles_users
		$this->db->query('DELETE FROM `'.$table_prefix.'roles_users` WHERE user_id = ?',$this->id);
		
		// Remove assigned badges
		$this->db->query('DELETE FROM `'.$table_prefix.'badge_users` WHERE user_id = ?',$this->id);

		// Delete alerts
		ORM::factory('alert')
		    ->where('user_id', $this->id)
		    ->delete_all();
		
		// Delete user_token
		ORM::factory('user_token')
		    ->where('user_id', $this->id)
		    ->delete_all();
		
		// Delete openid
		ORM::factory('openid')
		    ->where('user_id', $this->id)
		    ->delete_all();

		parent::delete();
	}
	
	/**
	 * Check if user has specified permission
	 * @param $permission String permission name
	 **/
	public function has_permission($permission)
	{
		// Cache superadmin role to avoid repeating query
		static $superadmin;
		if (!isset($superadmin)) $superadmin = ORM::factory('role','superadmin');
		
		// Special case - superadmin ALWAYS has all permissions
		if ($this->has($superadmin))
		{
			return TRUE;
		}
		
		foreach ($this->roles as $user_role)
		{
			if ($user_role->has(ORM::factory('permission',$permission)))
			{
				return TRUE;
			}
		}
		
		return FALSE;
	}
	
	/**
	 * Get user's dashboard
	 */
	public function dashboard()
	{
		if ($this->has_permission('admin_ui'))
			return 'admin';
		
		if ($this->has_permission('member_ui'))
			return 'members';
		
		// Just in case someone has a login only role
		if ($this->has(ORM::factory('role','login')))
			return '';
		
		// Send anyone else to login
		return 'login';
	}
	
	/**
	 * Get a new forgotten password challenge token for this user
	 * @param string $salt Optional salt for token generation (use this)
	 * @return string
	 */
	public function forgot_password_token()
	{
		return $this->_forgot_password_token();
	}

	/**
	 * Check to see if forgotten password token is valid
	 * @param string $token token to check
	 * @return boolean is token valid
	 **/
	public function check_forgot_password_token($token)
	{
		$salt = substr($token, 0, 32);
		return $this->_forgot_password_token($salt) == $token;
	}

	/**
	 * Generate a forgotten password challenge token for this user
	 * @param string $salt Optional salt for token generation (only use this for checking a token in URL)
	 * @return string token
	 */
	private function _forgot_password_token($salt = FALSE)
	{
		// Hashed datq consists of email and the last_login field
		// So as soon as the user logs in again, the reset link expires automatically.
		$salt = $salt ? $salt : text::random('alnum', 32); // Limited charset to keep it URL friendly
		$key = Kohana::config('settings.forgot_password_secret');
		return $salt . hash_hmac('sha1', $this->last_login . $this->email, $salt . $key);
	}

} // End User_Model
Back to Top