1
0

OC_User.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. use OC\Authentication\Token\IProvider;
  8. use OC\User\LoginException;
  9. use OCP\Authentication\Token\IToken;
  10. use OCP\EventDispatcher\IEventDispatcher;
  11. use OCP\IGroupManager;
  12. use OCP\ISession;
  13. use OCP\IUser;
  14. use OCP\IUserManager;
  15. use OCP\Server;
  16. use OCP\User\Events\BeforeUserLoggedInEvent;
  17. use OCP\User\Events\UserLoggedInEvent;
  18. use Psr\Log\LoggerInterface;
  19. /**
  20. * This class provides wrapper methods for user management. Multiple backends are
  21. * supported. User management operations are delegated to the configured backend for
  22. * execution.
  23. *
  24. * Note that &run is deprecated and won't work anymore.
  25. *
  26. * Hooks provided:
  27. * pre_createUser(&run, uid, password)
  28. * post_createUser(uid, password)
  29. * pre_deleteUser(&run, uid)
  30. * post_deleteUser(uid)
  31. * pre_setPassword(&run, uid, password, recoveryPassword)
  32. * post_setPassword(uid, password, recoveryPassword)
  33. * pre_login(&run, uid, password)
  34. * post_login(uid)
  35. * logout()
  36. */
  37. class OC_User {
  38. private static $_usedBackends = [];
  39. private static $_setupedBackends = [];
  40. // bool, stores if a user want to access a resource anonymously, e.g if they open a public link
  41. private static $incognitoMode = false;
  42. /**
  43. * Adds the backend to the list of used backends
  44. *
  45. * @param string|\OCP\UserInterface $backend default: database The backend to use for user management
  46. * @return bool
  47. *
  48. * Set the User Authentication Module
  49. * @suppress PhanDeprecatedFunction
  50. */
  51. public static function useBackend($backend = 'database') {
  52. if ($backend instanceof \OCP\UserInterface) {
  53. self::$_usedBackends[get_class($backend)] = $backend;
  54. \OC::$server->getUserManager()->registerBackend($backend);
  55. } else {
  56. // You'll never know what happens
  57. if ($backend === null or !is_string($backend)) {
  58. $backend = 'database';
  59. }
  60. // Load backend
  61. switch ($backend) {
  62. case 'database':
  63. case 'mysql':
  64. case 'sqlite':
  65. Server::get(LoggerInterface::class)->debug('Adding user backend ' . $backend . '.', ['app' => 'core']);
  66. self::$_usedBackends[$backend] = new \OC\User\Database();
  67. \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
  68. break;
  69. case 'dummy':
  70. self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
  71. \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
  72. break;
  73. default:
  74. Server::get(LoggerInterface::class)->debug('Adding default user backend ' . $backend . '.', ['app' => 'core']);
  75. $className = 'OC_USER_' . strtoupper($backend);
  76. self::$_usedBackends[$backend] = new $className();
  77. \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
  78. break;
  79. }
  80. }
  81. return true;
  82. }
  83. /**
  84. * remove all used backends
  85. */
  86. public static function clearBackends() {
  87. self::$_usedBackends = [];
  88. \OC::$server->getUserManager()->clearBackends();
  89. }
  90. /**
  91. * setup the configured backends in config.php
  92. * @suppress PhanDeprecatedFunction
  93. */
  94. public static function setupBackends() {
  95. OC_App::loadApps(['prelogin']);
  96. $backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
  97. if (isset($backends['default']) && !$backends['default']) {
  98. // clear default backends
  99. self::clearBackends();
  100. }
  101. foreach ($backends as $i => $config) {
  102. if (!is_array($config)) {
  103. continue;
  104. }
  105. $class = $config['class'];
  106. $arguments = $config['arguments'];
  107. if (class_exists($class)) {
  108. if (!in_array($i, self::$_setupedBackends)) {
  109. // make a reflection object
  110. $reflectionObj = new ReflectionClass($class);
  111. // use Reflection to create a new instance, using the $args
  112. $backend = $reflectionObj->newInstanceArgs($arguments);
  113. self::useBackend($backend);
  114. self::$_setupedBackends[] = $i;
  115. } else {
  116. Server::get(LoggerInterface::class)->debug('User backend ' . $class . ' already initialized.', ['app' => 'core']);
  117. }
  118. } else {
  119. Server::get(LoggerInterface::class)->error('User backend ' . $class . ' not found.', ['app' => 'core']);
  120. }
  121. }
  122. }
  123. /**
  124. * Try to login a user, assuming authentication
  125. * has already happened (e.g. via Single Sign On).
  126. *
  127. * Log in a user and regenerate a new session.
  128. *
  129. * @param \OCP\Authentication\IApacheBackend $backend
  130. * @return bool
  131. */
  132. public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
  133. $uid = $backend->getCurrentUserId();
  134. $run = true;
  135. OC_Hook::emit("OC_User", "pre_login", ["run" => &$run, "uid" => $uid, 'backend' => $backend]);
  136. if ($uid) {
  137. if (self::getUser() !== $uid) {
  138. self::setUserId($uid);
  139. $userSession = \OC::$server->getUserSession();
  140. /** @var IEventDispatcher $dispatcher */
  141. $dispatcher = \OC::$server->get(IEventDispatcher::class);
  142. if ($userSession->getUser() && !$userSession->getUser()->isEnabled()) {
  143. $message = \OC::$server->getL10N('lib')->t('Account disabled');
  144. throw new LoginException($message);
  145. }
  146. $userSession->setLoginName($uid);
  147. $request = OC::$server->getRequest();
  148. $password = null;
  149. if ($backend instanceof \OCP\Authentication\IProvideUserSecretBackend) {
  150. $password = $backend->getCurrentUserSecret();
  151. }
  152. /** @var IEventDispatcher $dispatcher */
  153. $dispatcher->dispatchTyped(new BeforeUserLoggedInEvent($uid, $password, $backend));
  154. $userSession->createSessionToken($request, $uid, $uid, $password);
  155. $userSession->createRememberMeToken($userSession->getUser());
  156. if (empty($password)) {
  157. $tokenProvider = \OC::$server->get(IProvider::class);
  158. $token = $tokenProvider->getToken($userSession->getSession()->getId());
  159. $token->setScope([
  160. IToken::SCOPE_SKIP_PASSWORD_VALIDATION => true,
  161. IToken::SCOPE_FILESYSTEM => true,
  162. ]);
  163. $tokenProvider->updateToken($token);
  164. }
  165. // setup the filesystem
  166. OC_Util::setupFS($uid);
  167. // first call the post_login hooks, the login-process needs to be
  168. // completed before we can safely create the users folder.
  169. // For example encryption needs to initialize the users keys first
  170. // before we can create the user folder with the skeleton files
  171. OC_Hook::emit(
  172. 'OC_User',
  173. 'post_login',
  174. [
  175. 'uid' => $uid,
  176. 'password' => $password,
  177. 'isTokenLogin' => false,
  178. ]
  179. );
  180. $dispatcher->dispatchTyped(new UserLoggedInEvent(
  181. \OC::$server->get(IUserManager::class)->get($uid),
  182. $uid,
  183. null,
  184. false)
  185. );
  186. //trigger creation of user home and /files folder
  187. \OC::$server->getUserFolder($uid);
  188. }
  189. return true;
  190. }
  191. return false;
  192. }
  193. /**
  194. * Verify with Apache whether user is authenticated.
  195. *
  196. * @return boolean|null
  197. * true: authenticated
  198. * false: not authenticated
  199. * null: not handled / no backend available
  200. */
  201. public static function handleApacheAuth() {
  202. $backend = self::findFirstActiveUsedBackend();
  203. if ($backend) {
  204. OC_App::loadApps();
  205. //setup extra user backends
  206. self::setupBackends();
  207. \OC::$server->getUserSession()->unsetMagicInCookie();
  208. return self::loginWithApache($backend);
  209. }
  210. return null;
  211. }
  212. /**
  213. * Sets user id for session and triggers emit
  214. *
  215. * @param string $uid
  216. */
  217. public static function setUserId($uid) {
  218. $userSession = \OC::$server->getUserSession();
  219. $userManager = \OC::$server->getUserManager();
  220. if ($user = $userManager->get($uid)) {
  221. $userSession->setUser($user);
  222. } else {
  223. \OC::$server->getSession()->set('user_id', $uid);
  224. }
  225. }
  226. /**
  227. * Check if the user is logged in, considers also the HTTP basic credentials
  228. *
  229. * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
  230. * @return bool
  231. */
  232. public static function isLoggedIn() {
  233. return \OC::$server->getUserSession()->isLoggedIn();
  234. }
  235. /**
  236. * set incognito mode, e.g. if a user wants to open a public link
  237. *
  238. * @param bool $status
  239. */
  240. public static function setIncognitoMode($status) {
  241. self::$incognitoMode = $status;
  242. }
  243. /**
  244. * get incognito mode status
  245. *
  246. * @return bool
  247. */
  248. public static function isIncognitoMode() {
  249. return self::$incognitoMode;
  250. }
  251. /**
  252. * Returns the current logout URL valid for the currently logged-in user
  253. *
  254. * @param \OCP\IURLGenerator $urlGenerator
  255. * @return string
  256. */
  257. public static function getLogoutUrl(\OCP\IURLGenerator $urlGenerator) {
  258. $backend = self::findFirstActiveUsedBackend();
  259. if ($backend) {
  260. return $backend->getLogoutUrl();
  261. }
  262. $user = \OC::$server->getUserSession()->getUser();
  263. if ($user instanceof IUser) {
  264. $backend = $user->getBackend();
  265. if ($backend instanceof \OCP\User\Backend\ICustomLogout) {
  266. return $backend->getLogoutUrl();
  267. }
  268. }
  269. $logoutUrl = $urlGenerator->linkToRoute('core.login.logout');
  270. $logoutUrl .= '?requesttoken=' . urlencode(\OCP\Util::callRegister());
  271. return $logoutUrl;
  272. }
  273. /**
  274. * Check if the user is an admin user
  275. *
  276. * @param string $uid uid of the admin
  277. * @return bool
  278. */
  279. public static function isAdminUser($uid) {
  280. $user = Server::get(IUserManager::class)->get($uid);
  281. $isAdmin = $user && Server::get(IGroupManager::class)->isAdmin($user->getUID());
  282. return $isAdmin && self::$incognitoMode === false;
  283. }
  284. /**
  285. * get the user id of the user currently logged in.
  286. *
  287. * @return string|false uid or false
  288. */
  289. public static function getUser() {
  290. $uid = Server::get(ISession::class)?->get('user_id');
  291. if (!is_null($uid) && self::$incognitoMode === false) {
  292. return $uid;
  293. } else {
  294. return false;
  295. }
  296. }
  297. /**
  298. * Set password
  299. *
  300. * @param string $uid The username
  301. * @param string $password The new password
  302. * @param string $recoveryPassword for the encryption app to reset encryption keys
  303. * @return bool
  304. *
  305. * Change the password of a user
  306. */
  307. public static function setPassword($uid, $password, $recoveryPassword = null) {
  308. $user = \OC::$server->getUserManager()->get($uid);
  309. if ($user) {
  310. return $user->setPassword($password, $recoveryPassword);
  311. } else {
  312. return false;
  313. }
  314. }
  315. /**
  316. * @param string $uid The username
  317. * @return string
  318. *
  319. * returns the path to the users home directory
  320. * @deprecated Use \OC::$server->getUserManager->getHome()
  321. */
  322. public static function getHome($uid) {
  323. $user = \OC::$server->getUserManager()->get($uid);
  324. if ($user) {
  325. return $user->getHome();
  326. } else {
  327. return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
  328. }
  329. }
  330. /**
  331. * Get a list of all users display name
  332. *
  333. * @param string $search
  334. * @param int $limit
  335. * @param int $offset
  336. * @return array associative array with all display names (value) and corresponding uids (key)
  337. *
  338. * Get a list of all display names and user ids.
  339. * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
  340. */
  341. public static function getDisplayNames($search = '', $limit = null, $offset = null) {
  342. $displayNames = [];
  343. $users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
  344. foreach ($users as $user) {
  345. $displayNames[$user->getUID()] = $user->getDisplayName();
  346. }
  347. return $displayNames;
  348. }
  349. /**
  350. * Returns the first active backend from self::$_usedBackends.
  351. *
  352. * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
  353. */
  354. private static function findFirstActiveUsedBackend() {
  355. foreach (self::$_usedBackends as $backend) {
  356. if ($backend instanceof OCP\Authentication\IApacheBackend) {
  357. if ($backend->isSessionActive()) {
  358. return $backend;
  359. }
  360. }
  361. }
  362. return null;
  363. }
  364. }