PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/src/libraries/models/User.php

https://github.com/hfiguiere/frontend
PHP | 432 lines | 229 code | 45 blank | 158 comment | 42 complexity | 640a592338cea5b5dd05f684727c1e2e MD5 | raw file
  1. <?php
  2. /**
  3. * User model
  4. *
  5. * This is the model for user data.
  6. * User data consists of application settings as well as profile information.
  7. * Application settings include things like default permissions and auto increment ids.
  8. * Profile information includes things like email address.
  9. * @author Jaisen Mathai <jaisen@jmathai.com>
  10. */
  11. class User extends BaseModel
  12. {
  13. const displayNameDefault = 'Trovebox User';
  14. /**
  15. * A user object that caches the value once it's been fetched from the remote datasource.
  16. * @access private
  17. * @var array
  18. */
  19. protected $user, $userArray = array(), $credential, $themeObj;
  20. /*
  21. * Constructor
  22. */
  23. public function __construct()
  24. {
  25. parent::__construct();
  26. }
  27. /**
  28. * Encrypt user password
  29. *
  30. * @return string
  31. */
  32. public function encryptPassword($password)
  33. {
  34. return sha1(sprintf('%s-%s', $password, $this->config->secrets->passwordSalt));
  35. }
  36. /**
  37. * Gets an attribute from the user's entry in the user db
  38. * @param string $name The name of the value to retrieve
  39. *
  40. * @return mixed String on success FALSE on failure
  41. */
  42. public function getAttribute($name)
  43. {
  44. $name = $this->getAttributeName($name);
  45. $user = $this->getUserRecord();
  46. if($user === false)
  47. return false;
  48. if(isset($user[$name]))
  49. return $user[$name];
  50. return false;
  51. }
  52. /**
  53. * Gets an attribute name
  54. * @param string $name The name of the value to retrieve
  55. *
  56. * @return string
  57. */
  58. public function getAttributeName($name)
  59. {
  60. return sprintf('attr%s', $name);
  61. }
  62. /**
  63. * Get an avatar given an email address
  64. * See http://en.gravatar.com/site/implement/images/ and http://en.gravatar.com/site/implement/hash/
  65. *
  66. * @return string
  67. */
  68. public function getAvatarFromEmail($size = 50, $email = null)
  69. {
  70. if($email === null)
  71. $email = $this->session->get('email');
  72. // TODO return standard avatar
  73. if(empty($email))
  74. return;
  75. $user = $this->getUserByEmail($email);
  76. if(isset($user['attrprofilePhoto']) && !empty($user['attrprofilePhoto']))
  77. return $user['attrprofilePhoto'];
  78. $utilityObj = new Utility;
  79. if(empty($this->config->site->cdnPrefix))
  80. $hostAndProtocol = sprintf('%s://%s', $utilityObj->getProtocol(false), $utilityObj->getHost(false));
  81. else
  82. $hostAndProtocol = sprintf('%s%s', $utilityObj->getProtocol(false), $this->config->site->cdnPrefix);
  83. if(!$this->themeObj)
  84. $this->themeObj = getTheme();
  85. $defaultUrl = sprintf('%s%s', $hostAndProtocol, $this->themeObj->asset('image', 'profile-default.png', false));
  86. $hash = md5(strtolower(trim($email)));
  87. return sprintf("http://www.gravatar.com/avatar/%s?s=%s&d=%s", $hash, $size, urlencode($defaultUrl));
  88. }
  89. /**
  90. * Get the email address of the logged in user.
  91. *
  92. * @return string
  93. */
  94. public function getEmailAddress()
  95. {
  96. $credential = $this->getCredentialObject();
  97. if($credential->isOAuthRequest())
  98. return $credential->getEmailFromOAuth();
  99. else
  100. return $this->session->get('email');
  101. }
  102. /**
  103. * Get a name given an email address
  104. *
  105. * @return string
  106. */
  107. public function getNameFromEmail($email = null)
  108. {
  109. if($email === null)
  110. $email = $this->getEmailAddress();
  111. if(!empty($email))
  112. {
  113. $user = $this->getUserByEmail($email);
  114. if(isset($user['attrprofileName']) && !empty($user['attrprofileName']))
  115. return $user['attrprofileName'];
  116. }
  117. return self::displayNameDefault;
  118. }
  119. /**
  120. * Get the next ID to be used for a action, group or photo.
  121. * The ID is a base 32 string that represents an autoincrementing integer.
  122. * @return string
  123. */
  124. public function getNextId($type)
  125. {
  126. $type = ucwords($type);
  127. $key = "last{$type}Id";
  128. $user = $this->getUserRecord(false, true); // no cache, do lock
  129. if($user === false)
  130. return false;
  131. if(!isset($user[$key]))
  132. $user[$key] = '';
  133. $nextIntId = base_convert($user[$key], 31, 10) + 1;
  134. $nextId = base_convert($nextIntId, 10, 31);
  135. $status = $this->update(array($key => $nextId));
  136. if(!$status)
  137. return false;
  138. return $nextId;
  139. }
  140. /**
  141. * Get the total amount of space used
  142. * @return int Size in bytes
  143. */
  144. public function getStorageUsed()
  145. {
  146. return $this->db->getStorageUsed();
  147. }
  148. /**
  149. * Get the user record from the remote database.
  150. * If the record does not exist then attempt to create it before returning.
  151. * Returns false if no user record could be obtained or crated.
  152. * Returns the user array on success.
  153. *
  154. * @return mixed FALSE on error, array on success
  155. */
  156. public function getUserRecord($cache = true, $lock = false)
  157. {
  158. // we cache the user entry per request
  159. if($cache && $this->user)
  160. return $this->user;
  161. $res = $this->db->getUser(null, $lock);
  162. // if null create, onerror return false
  163. if($res === null)
  164. {
  165. // user entry does not exist, create it
  166. $res = $this->create();
  167. if(!$res)
  168. return false;
  169. // fetch the record to return
  170. $res = $this->db->getUser(null, $lock);
  171. if(!$res)
  172. return false;
  173. }
  174. elseif($res === false)
  175. {
  176. return false;
  177. }
  178. $this->user = $res;
  179. return $this->user;
  180. }
  181. /**
  182. * Get the user record by email address.
  183. *
  184. * @return mixed FALSE on error, array on success
  185. */
  186. public function getUserByEmail($email, $cache = true)
  187. {
  188. if($cache && isset($this->userArray[$email]))
  189. return $this->userArray[$email];
  190. $user = $this->db->getUser($email);
  191. if($user)
  192. $this->userArray[$email] = $user;
  193. return $user;
  194. }
  195. /**
  196. * Checks if the user is logged in.
  197. * Works for Cookie and OAuth requests
  198. *
  199. * @return boolean
  200. */
  201. public function isLoggedIn()
  202. {
  203. $credential = $this->getCredentialObject();
  204. if($credential->isOAuthRequest())
  205. return $credential->checkRequest() === true;
  206. else
  207. return $this->session->get('email') != '';
  208. }
  209. /**
  210. * Checks if the logged in user is the owner or an admin
  211. * Works for Cookie and OAuth requests
  212. *
  213. * @return boolean
  214. */
  215. public function isAdmin()
  216. {
  217. return $this->isOwner(true);
  218. }
  219. /**
  220. * Checks if the logged in user is the owner
  221. * Works for Cookie and OAuth requests
  222. *
  223. * @return boolean
  224. */
  225. public function isOwner($includeAdmin = false)
  226. {
  227. if(!isset($this->config->user))
  228. return false;
  229. $user = $this->config->user;
  230. $credential = $this->getCredentialObject();
  231. $loggedInEmail = $this->session->get('email');
  232. if($credential->isOAuthRequest())
  233. {
  234. return $credential->checkRequest() === true && $credential->getEmailFromOAuth() === $user->email;;
  235. }
  236. elseif(!$this->isLoggedIn())
  237. {
  238. return false;
  239. }
  240. else
  241. {
  242. if($user === null)
  243. return false;
  244. $len = max(strlen($loggedInEmail), strlen($user->email));
  245. $isOwner = isset($user->email) && strncmp(strtolower($loggedInEmail), strtolower($user->email), $len) === 0;
  246. if($isOwner)
  247. return true;
  248. if($includeAdmin && isset($user->admins))
  249. {
  250. $admins = (array)explode(',', $user->admins);
  251. if(array_search(strtolower($loggedInEmail), array_map('strtolower', $admins)) !== false)
  252. return true;
  253. }
  254. }
  255. return false;
  256. }
  257. /**
  258. * Validate the identity of the user using BrowserID
  259. * If the assertion is valid then the email address is stored in session with a random key to prevent XSRF.
  260. *
  261. * @param string $assertion Assertion from BrowserID.org
  262. * @param string $audience Audience from BrowserID.org
  263. * @return boolean
  264. */
  265. public function login($provider, $params)
  266. {
  267. $email = getLogin($provider)->verifyEmail($params);
  268. if($email === false)
  269. return false;
  270. $this->setEmail($email);
  271. return true;
  272. }
  273. /**
  274. * Log a user out.
  275. *
  276. * @return void
  277. */
  278. public function logout()
  279. {
  280. $this->session->end();
  281. }
  282. /**
  283. * Returns the number of tutorials for the current page
  284. *
  285. * @return int
  286. */
  287. public function numberOfTutorials()
  288. {
  289. if(!$this->isAdmin())
  290. return 0;
  291. $tutorial = new Tutorial;
  292. $unseen = $tutorial->getUnseen();
  293. if($unseen === false)
  294. return 0;
  295. return count($unseen);
  296. }
  297. /**
  298. * Set an attribute.
  299. *
  300. * @return boolean
  301. */
  302. public function setAttribute($name, $value)
  303. {
  304. $name = $this->getAttributeName($name);
  305. return $this->update(array($name => $value));
  306. }
  307. /**
  308. * Set the session email.
  309. *
  310. * @return void
  311. */
  312. public function setEmail($email)
  313. {
  314. $this->session->set('email', $email);
  315. $this->session->set('crumb', md5($this->config->secrets->secret . time()));
  316. if($this->isAdmin())
  317. $this->session->set('site', $_SERVER['HTTP_HOST']);
  318. }
  319. /**
  320. * Update an existing user record.
  321. * This method updates an existing user record.
  322. * Differs from $this->create on the implementation at the adapter layer.
  323. *
  324. * The user record has a key of 1 and default attributes specified by $this->getDefaultAttributes().
  325. *
  326. * @return boolean
  327. */
  328. public function update($params)
  329. {
  330. $user = $this->getUserRecord();
  331. $params = array_merge($this->getDefaultAttributes(), $user, $params);
  332. // encrypt the password if present, else remove it
  333. if(isset($params['password']))
  334. {
  335. if(!empty($params['password']))
  336. $params['password'] = $this->encryptPassword($params['password']);
  337. else
  338. unset($params['password']);
  339. }
  340. // update cache
  341. $this->getUserRecord(false);
  342. // TODO check $params against a whitelist
  343. return $this->db->postUser($params);
  344. }
  345. /**
  346. * Creates and returns a credential object
  347. *
  348. * @return object
  349. */
  350. protected function getCredentialObject()
  351. {
  352. if(isset($this->credential))
  353. return $this->credential;
  354. $this->credential = new Credential;
  355. return $this->credential;
  356. }
  357. /**
  358. * Create a new user record.
  359. * This method should only be called if no record already exists.
  360. * The user record has a key of 1 and default attributes specified by $this->getDefaultAttributes().
  361. * Differs from $this->update on the implementation at the adapter layer.
  362. *
  363. * @return boolean
  364. */
  365. private function create()
  366. {
  367. return $this->db->putUser($this->getDefaultAttributes());
  368. }
  369. /**
  370. * Default attributes for a new user record.
  371. *
  372. * @return array
  373. */
  374. private function getDefaultAttributes()
  375. {
  376. return array('lastPhotoId' => '', 'lastActionId' => '', 'lastGroupId' => '', 'lastWebhookId' => '', 'password' => '');
  377. }
  378. /**
  379. * Mobile passphrase key.
  380. *
  381. * @return array
  382. */
  383. private function getMobilePassphraseKey()
  384. {
  385. return sprintf('%s-%s', 'mobile.passphrase.key', getenv('HTTP_HOST'));
  386. }
  387. }