user.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. <?php
  2. /**
  3. * @author Aldo "xoen" Giambelluca <xoen@xoen.org>
  4. * @author Andreas Fischer <bantu@owncloud.com>
  5. * @author Arthur Schiwon <blizzz@owncloud.com>
  6. * @author Bartek Przybylski <bart.p.pl@gmail.com>
  7. * @author Bart Visscher <bartv@thisnet.nl>
  8. * @author Björn Schießle <schiessle@owncloud.com>
  9. * @author Dominik Schmidt <dev@dominik-schmidt.de>
  10. * @author Florian Preinstorfer <nblock@archlinux.us>
  11. * @author Georg Ehrke <georg@owncloud.com>
  12. * @author Jakob Sack <mail@jakobsack.de>
  13. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  14. * @author Lukas Reschke <lukas@owncloud.com>
  15. * @author Morris Jobke <hey@morrisjobke.de>
  16. * @author Robin Appelman <icewind@owncloud.com>
  17. * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
  18. * @author Scrutinizer Auto-Fixer <auto-fixer@scrutinizer-ci.com>
  19. * @author shkdee <louis.traynard@m4x.org>
  20. * @author Thomas Müller <thomas.mueller@tmit.eu>
  21. * @author Tom Needham <tom@owncloud.com>
  22. * @author Victor Dubiniuk <dubiniuk@owncloud.com>
  23. *
  24. * @copyright Copyright (c) 2015, ownCloud, Inc.
  25. * @license AGPL-3.0
  26. *
  27. * This code is free software: you can redistribute it and/or modify
  28. * it under the terms of the GNU Affero General Public License, version 3,
  29. * as published by the Free Software Foundation.
  30. *
  31. * This program is distributed in the hope that it will be useful,
  32. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  34. * GNU Affero General Public License for more details.
  35. *
  36. * You should have received a copy of the GNU Affero General Public License, version 3,
  37. * along with this program. If not, see <http://www.gnu.org/licenses/>
  38. *
  39. */
  40. /**
  41. * This class provides wrapper methods for user management. Multiple backends are
  42. * supported. User management operations are delegated to the configured backend for
  43. * execution.
  44. *
  45. * Hooks provided:
  46. * pre_createUser(&run, uid, password)
  47. * post_createUser(uid, password)
  48. * pre_deleteUser(&run, uid)
  49. * post_deleteUser(uid)
  50. * pre_setPassword(&run, uid, password, recoveryPassword)
  51. * post_setPassword(uid, password, recoveryPassword)
  52. * pre_login(&run, uid, password)
  53. * post_login(uid)
  54. * logout()
  55. */
  56. class OC_User {
  57. /**
  58. * @return \OC\User\Session
  59. */
  60. public static function getUserSession() {
  61. return OC::$server->getUserSession();
  62. }
  63. /**
  64. * @return \OC\User\Manager
  65. * @deprecated Use \OC::$server->getUserManager()
  66. */
  67. public static function getManager() {
  68. return OC::$server->getUserManager();
  69. }
  70. private static $_backends = array();
  71. private static $_usedBackends = array();
  72. private static $_setupedBackends = array();
  73. // bool, stores if a user want to access a resource anonymously, e.g if he opens a public link
  74. private static $incognitoMode = false;
  75. /**
  76. * registers backend
  77. *
  78. * @param string $backend name of the backend
  79. * @deprecated Add classes by calling OC_User::useBackend() with a class instance instead
  80. * @return bool
  81. *
  82. * Makes a list of backends that can be used by other modules
  83. */
  84. public static function registerBackend($backend) {
  85. self::$_backends[] = $backend;
  86. return true;
  87. }
  88. /**
  89. * gets available backends
  90. *
  91. * @deprecated
  92. * @return array an array of backends
  93. *
  94. * Returns the names of all backends.
  95. */
  96. public static function getBackends() {
  97. return self::$_backends;
  98. }
  99. /**
  100. * gets used backends
  101. *
  102. * @deprecated
  103. * @return array an array of backends
  104. *
  105. * Returns the names of all used backends.
  106. */
  107. public static function getUsedBackends() {
  108. return array_keys(self::$_usedBackends);
  109. }
  110. /**
  111. * Adds the backend to the list of used backends
  112. *
  113. * @param string|OC_User_Interface $backend default: database The backend to use for user management
  114. * @return bool
  115. *
  116. * Set the User Authentication Module
  117. */
  118. public static function useBackend($backend = 'database') {
  119. if ($backend instanceof OC_User_Interface) {
  120. self::$_usedBackends[get_class($backend)] = $backend;
  121. self::getManager()->registerBackend($backend);
  122. } else {
  123. // You'll never know what happens
  124. if (null === $backend OR !is_string($backend)) {
  125. $backend = 'database';
  126. }
  127. // Load backend
  128. switch ($backend) {
  129. case 'database':
  130. case 'mysql':
  131. case 'sqlite':
  132. OC_Log::write('core', 'Adding user backend ' . $backend . '.', OC_Log::DEBUG);
  133. self::$_usedBackends[$backend] = new OC_User_Database();
  134. self::getManager()->registerBackend(self::$_usedBackends[$backend]);
  135. break;
  136. default:
  137. OC_Log::write('core', 'Adding default user backend ' . $backend . '.', OC_Log::DEBUG);
  138. $className = 'OC_USER_' . strToUpper($backend);
  139. self::$_usedBackends[$backend] = new $className();
  140. self::getManager()->registerBackend(self::$_usedBackends[$backend]);
  141. break;
  142. }
  143. }
  144. return true;
  145. }
  146. /**
  147. * remove all used backends
  148. */
  149. public static function clearBackends() {
  150. self::$_usedBackends = array();
  151. self::getManager()->clearBackends();
  152. }
  153. /**
  154. * setup the configured backends in config.php
  155. */
  156. public static function setupBackends() {
  157. OC_App::loadApps(array('prelogin'));
  158. $backends = OC_Config::getValue('user_backends', array());
  159. foreach ($backends as $i => $config) {
  160. $class = $config['class'];
  161. $arguments = $config['arguments'];
  162. if (class_exists($class)) {
  163. if (array_search($i, self::$_setupedBackends) === false) {
  164. // make a reflection object
  165. $reflectionObj = new ReflectionClass($class);
  166. // use Reflection to create a new instance, using the $args
  167. $backend = $reflectionObj->newInstanceArgs($arguments);
  168. self::useBackend($backend);
  169. self::$_setupedBackends[] = $i;
  170. } else {
  171. OC_Log::write('core', 'User backend ' . $class . ' already initialized.', OC_Log::DEBUG);
  172. }
  173. } else {
  174. OC_Log::write('core', 'User backend ' . $class . ' not found.', OC_Log::ERROR);
  175. }
  176. }
  177. }
  178. /**
  179. * Create a new user
  180. *
  181. * @param string $uid The username of the user to create
  182. * @param string $password The password of the new user
  183. * @throws Exception
  184. * @return bool true/false
  185. *
  186. * Creates a new user. Basic checking of username is done in OC_User
  187. * itself, not in its subclasses.
  188. *
  189. * Allowed characters in the username are: "a-z", "A-Z", "0-9" and "_.@-"
  190. * @deprecated Use \OC::$server->getUserManager()->createUser($uid, $password)
  191. */
  192. public static function createUser($uid, $password) {
  193. return self::getManager()->createUser($uid, $password);
  194. }
  195. /**
  196. * delete a user
  197. *
  198. * @param string $uid The username of the user to delete
  199. * @return bool
  200. *
  201. * Deletes a user
  202. * @deprecated Use \OC::$server->getUserManager->delete()
  203. */
  204. public static function deleteUser($uid) {
  205. $user = self::getManager()->get($uid);
  206. if ($user) {
  207. return $user->delete();
  208. } else {
  209. return false;
  210. }
  211. }
  212. /**
  213. * Try to login a user
  214. *
  215. * @param string $loginname The login name of the user to log in
  216. * @param string $password The password of the user
  217. * @return boolean|null
  218. *
  219. * Log in a user and regenerate a new session - if the password is ok
  220. */
  221. public static function login($loginname, $password) {
  222. session_regenerate_id(true);
  223. $result = self::getUserSession()->login($loginname, $password);
  224. if ($result) {
  225. //we need to pass the user name, which may differ from login name
  226. OC_Util::setupFS(self::getUserSession()->getUser()->getUID());
  227. }
  228. return $result;
  229. }
  230. /**
  231. * Try to login a user using the magic cookie (remember login)
  232. *
  233. * @param string $uid The username of the user to log in
  234. * @param string $token
  235. * @return bool
  236. */
  237. public static function loginWithCookie($uid, $token) {
  238. return self::getUserSession()->loginWithCookie($uid, $token);
  239. }
  240. /**
  241. * Try to login a user, assuming authentication
  242. * has already happened (e.g. via Single Sign On).
  243. *
  244. * Log in a user and regenerate a new session.
  245. *
  246. * @param \OCP\Authentication\IApacheBackend $backend
  247. * @return bool
  248. */
  249. public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
  250. $uid = $backend->getCurrentUserId();
  251. $run = true;
  252. OC_Hook::emit("OC_User", "pre_login", array("run" => &$run, "uid" => $uid));
  253. if ($uid) {
  254. self::setUserId($uid);
  255. self::setDisplayName($uid);
  256. self::getUserSession()->setLoginName($uid);
  257. OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => ''));
  258. return true;
  259. }
  260. return false;
  261. }
  262. /**
  263. * Verify with Apache whether user is authenticated.
  264. *
  265. * @return boolean|null
  266. * true: authenticated
  267. * false: not authenticated
  268. * null: not handled / no backend available
  269. */
  270. public static function handleApacheAuth() {
  271. $backend = self::findFirstActiveUsedBackend();
  272. if ($backend) {
  273. OC_App::loadApps();
  274. //setup extra user backends
  275. self::setupBackends();
  276. self::unsetMagicInCookie();
  277. return self::loginWithApache($backend);
  278. }
  279. return null;
  280. }
  281. /**
  282. * Sets user id for session and triggers emit
  283. */
  284. public static function setUserId($uid) {
  285. $userSession = \OC::$server->getUserSession();
  286. $userManager = \OC::$server->getUserManager();
  287. if ($user = $userManager->get($uid)) {
  288. $userSession->setUser($user);
  289. } else {
  290. \OC::$server->getSession()->set('user_id', $uid);
  291. }
  292. }
  293. /**
  294. * Sets user display name for session
  295. *
  296. * @param string $uid
  297. * @param null $displayName
  298. * @return bool Whether the display name could get set
  299. */
  300. public static function setDisplayName($uid, $displayName = null) {
  301. if (is_null($displayName)) {
  302. $displayName = $uid;
  303. }
  304. $user = self::getManager()->get($uid);
  305. if ($user) {
  306. return $user->setDisplayName($displayName);
  307. } else {
  308. return false;
  309. }
  310. }
  311. /**
  312. * Logs the current user out and kills all the session data
  313. *
  314. * Logout, destroys session
  315. */
  316. public static function logout() {
  317. self::getUserSession()->logout();
  318. }
  319. /**
  320. * Tries to login the user with HTTP Basic Authentication
  321. */
  322. public static function tryBasicAuthLogin() {
  323. if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
  324. \OC_User::login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
  325. }
  326. }
  327. /**
  328. * Check if the user is logged in, considers also the HTTP basic credentials
  329. *
  330. * @return bool
  331. */
  332. public static function isLoggedIn() {
  333. if (\OC::$server->getSession()->get('user_id') !== null && self::$incognitoMode === false) {
  334. return self::userExists(\OC::$server->getSession()->get('user_id'));
  335. }
  336. return false;
  337. }
  338. /**
  339. * set incognito mode, e.g. if a user wants to open a public link
  340. *
  341. * @param bool $status
  342. */
  343. public static function setIncognitoMode($status) {
  344. self::$incognitoMode = $status;
  345. }
  346. /**
  347. * get incognito mode status
  348. *
  349. * @return bool
  350. */
  351. public static function isIncognitoMode() {
  352. return self::$incognitoMode;
  353. }
  354. /**
  355. * Supplies an attribute to the logout hyperlink. The default behaviour
  356. * is to return an href with '?logout=true' appended. However, it can
  357. * supply any attribute(s) which are valid for <a>.
  358. *
  359. * @return string with one or more HTML attributes.
  360. */
  361. public static function getLogoutAttribute() {
  362. $backend = self::findFirstActiveUsedBackend();
  363. if ($backend) {
  364. return $backend->getLogoutAttribute();
  365. }
  366. return 'href="' . link_to('', 'index.php') . '?logout=true&requesttoken=' . urlencode(OC_Util::callRegister()) . '"';
  367. }
  368. /**
  369. * Check if the user is an admin user
  370. *
  371. * @param string $uid uid of the admin
  372. * @return bool
  373. */
  374. public static function isAdminUser($uid) {
  375. if (OC_Group::inGroup($uid, 'admin') && self::$incognitoMode === false) {
  376. return true;
  377. }
  378. return false;
  379. }
  380. /**
  381. * get the user id of the user currently logged in.
  382. *
  383. * @return string uid or false
  384. */
  385. public static function getUser() {
  386. $uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
  387. if (!is_null($uid) && self::$incognitoMode === false) {
  388. return $uid;
  389. } else {
  390. return false;
  391. }
  392. }
  393. /**
  394. * get the display name of the user currently logged in.
  395. *
  396. * @param string $uid
  397. * @return string uid or false
  398. */
  399. public static function getDisplayName($uid = null) {
  400. if ($uid) {
  401. $user = self::getManager()->get($uid);
  402. if ($user) {
  403. return $user->getDisplayName();
  404. } else {
  405. return $uid;
  406. }
  407. } else {
  408. $user = self::getUserSession()->getUser();
  409. if ($user) {
  410. return $user->getDisplayName();
  411. } else {
  412. return false;
  413. }
  414. }
  415. }
  416. /**
  417. * Autogenerate a password
  418. *
  419. * @return string
  420. *
  421. * generates a password
  422. */
  423. public static function generatePassword() {
  424. return \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(30);
  425. }
  426. /**
  427. * Set password
  428. *
  429. * @param string $uid The username
  430. * @param string $password The new password
  431. * @param string $recoveryPassword for the encryption app to reset encryption keys
  432. * @return bool
  433. *
  434. * Change the password of a user
  435. */
  436. public static function setPassword($uid, $password, $recoveryPassword = null) {
  437. $user = self::getManager()->get($uid);
  438. if ($user) {
  439. return $user->setPassword($password, $recoveryPassword);
  440. } else {
  441. return false;
  442. }
  443. }
  444. /**
  445. * Check whether user can change his avatar
  446. *
  447. * @param string $uid The username
  448. * @return bool
  449. *
  450. * Check whether a specified user can change his avatar
  451. */
  452. public static function canUserChangeAvatar($uid) {
  453. $user = self::getManager()->get($uid);
  454. if ($user) {
  455. return $user->canChangeAvatar();
  456. } else {
  457. return false;
  458. }
  459. }
  460. /**
  461. * Check whether user can change his password
  462. *
  463. * @param string $uid The username
  464. * @return bool
  465. *
  466. * Check whether a specified user can change his password
  467. */
  468. public static function canUserChangePassword($uid) {
  469. $user = self::getManager()->get($uid);
  470. if ($user) {
  471. return $user->canChangePassword();
  472. } else {
  473. return false;
  474. }
  475. }
  476. /**
  477. * Check whether user can change his display name
  478. *
  479. * @param string $uid The username
  480. * @return bool
  481. *
  482. * Check whether a specified user can change his display name
  483. */
  484. public static function canUserChangeDisplayName($uid) {
  485. $user = self::getManager()->get($uid);
  486. if ($user) {
  487. return $user->canChangeDisplayName();
  488. } else {
  489. return false;
  490. }
  491. }
  492. /**
  493. * Check if the password is correct
  494. *
  495. * @param string $uid The username
  496. * @param string $password The password
  497. * @return string|false user id a string on success, false otherwise
  498. *
  499. * Check if the password is correct without logging in the user
  500. * returns the user id or false
  501. */
  502. public static function checkPassword($uid, $password) {
  503. $manager = self::getManager();
  504. $username = $manager->checkPassword($uid, $password);
  505. if ($username !== false) {
  506. return $username->getUID();
  507. }
  508. return false;
  509. }
  510. /**
  511. * @param string $uid The username
  512. * @return string
  513. *
  514. * returns the path to the users home directory
  515. * @deprecated Use \OC::$server->getUserManager->getHome()
  516. */
  517. public static function getHome($uid) {
  518. $user = self::getManager()->get($uid);
  519. if ($user) {
  520. return $user->getHome();
  521. } else {
  522. return OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
  523. }
  524. }
  525. /**
  526. * Get a list of all users
  527. *
  528. * @return array an array of all uids
  529. *
  530. * Get a list of all users.
  531. * @param string $search
  532. * @param integer $limit
  533. * @param integer $offset
  534. */
  535. public static function getUsers($search = '', $limit = null, $offset = null) {
  536. $users = self::getManager()->search($search, $limit, $offset);
  537. $uids = array();
  538. foreach ($users as $user) {
  539. $uids[] = $user->getUID();
  540. }
  541. return $uids;
  542. }
  543. /**
  544. * Get a list of all users display name
  545. *
  546. * @param string $search
  547. * @param int $limit
  548. * @param int $offset
  549. * @return array associative array with all display names (value) and corresponding uids (key)
  550. *
  551. * Get a list of all display names and user ids.
  552. * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
  553. */
  554. public static function getDisplayNames($search = '', $limit = null, $offset = null) {
  555. $displayNames = array();
  556. $users = self::getManager()->searchDisplayName($search, $limit, $offset);
  557. foreach ($users as $user) {
  558. $displayNames[$user->getUID()] = $user->getDisplayName();
  559. }
  560. return $displayNames;
  561. }
  562. /**
  563. * check if a user exists
  564. *
  565. * @param string $uid the username
  566. * @return boolean
  567. */
  568. public static function userExists($uid) {
  569. return self::getManager()->userExists($uid);
  570. }
  571. /**
  572. * disables a user
  573. *
  574. * @param string $uid the user to disable
  575. */
  576. public static function disableUser($uid) {
  577. $user = self::getManager()->get($uid);
  578. if ($user) {
  579. $user->setEnabled(false);
  580. }
  581. }
  582. /**
  583. * enable a user
  584. *
  585. * @param string $uid
  586. */
  587. public static function enableUser($uid) {
  588. $user = self::getManager()->get($uid);
  589. if ($user) {
  590. $user->setEnabled(true);
  591. }
  592. }
  593. /**
  594. * checks if a user is enabled
  595. *
  596. * @param string $uid
  597. * @return bool
  598. */
  599. public static function isEnabled($uid) {
  600. $user = self::getManager()->get($uid);
  601. if ($user) {
  602. return $user->isEnabled();
  603. } else {
  604. return false;
  605. }
  606. }
  607. /**
  608. * Set cookie value to use in next page load
  609. *
  610. * @param string $username username to be set
  611. * @param string $token
  612. */
  613. public static function setMagicInCookie($username, $token) {
  614. self::getUserSession()->setMagicInCookie($username, $token);
  615. }
  616. /**
  617. * Remove cookie for "remember username"
  618. */
  619. public static function unsetMagicInCookie() {
  620. self::getUserSession()->unsetMagicInCookie();
  621. }
  622. /**
  623. * Returns the first active backend from self::$_usedBackends.
  624. *
  625. * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
  626. */
  627. private static function findFirstActiveUsedBackend() {
  628. foreach (self::$_usedBackends as $backend) {
  629. if ($backend instanceof OCP\Authentication\IApacheBackend) {
  630. if ($backend->isSessionActive()) {
  631. return $backend;
  632. }
  633. }
  634. }
  635. return null;
  636. }
  637. }