You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

378 lines
10 KiB

  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2016, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace Tests\Core\Controller;
  22. use OC\Authentication\TwoFactorAuth\Manager;
  23. use OC\Core\Controller\LoginController;
  24. use OCP\AppFramework\Http\RedirectResponse;
  25. use OCP\AppFramework\Http\TemplateResponse;
  26. use OCP\IConfig;
  27. use OCP\IRequest;
  28. use OCP\ISession;
  29. use OCP\IURLGenerator;
  30. use OCP\IUserManager;
  31. use OCP\IUserSession;
  32. use Test\TestCase;
  33. class LoginControllerTest extends TestCase {
  34. /** @var LoginController */
  35. private $loginController;
  36. /** @var IRequest */
  37. private $request;
  38. /** @var IUserManager */
  39. private $userManager;
  40. /** @var IConfig */
  41. private $config;
  42. /** @var ISession */
  43. private $session;
  44. /** @var IUserSession */
  45. private $userSession;
  46. /** @var IURLGenerator */
  47. private $urlGenerator;
  48. /** @var Manager */
  49. private $twoFactorManager;
  50. public function setUp() {
  51. parent::setUp();
  52. $this->request = $this->getMock('\\OCP\\IRequest');
  53. $this->userManager = $this->getMock('\\OCP\\IUserManager');
  54. $this->config = $this->getMock('\\OCP\\IConfig');
  55. $this->session = $this->getMock('\\OCP\\ISession');
  56. $this->userSession = $this->getMockBuilder('\\OC\\User\\Session')
  57. ->disableOriginalConstructor()
  58. ->getMock();
  59. $this->urlGenerator = $this->getMock('\\OCP\\IURLGenerator');
  60. $this->twoFactorManager = $this->getMockBuilder('\OC\Authentication\TwoFactorAuth\Manager')
  61. ->disableOriginalConstructor()
  62. ->getMock();
  63. $this->loginController = new LoginController(
  64. 'core',
  65. $this->request,
  66. $this->userManager,
  67. $this->config,
  68. $this->session,
  69. $this->userSession,
  70. $this->urlGenerator,
  71. $this->twoFactorManager
  72. );
  73. }
  74. public function testLogoutWithoutToken() {
  75. $this->request
  76. ->expects($this->once())
  77. ->method('getCookie')
  78. ->with('oc_token')
  79. ->willReturn(null);
  80. $this->config
  81. ->expects($this->never())
  82. ->method('deleteUserValue');
  83. $this->urlGenerator
  84. ->expects($this->once())
  85. ->method('linkToRouteAbsolute')
  86. ->with('core.login.showLoginForm')
  87. ->willReturn('/login');
  88. $expected = new RedirectResponse('/login');
  89. $this->assertEquals($expected, $this->loginController->logout());
  90. }
  91. public function testLogoutWithToken() {
  92. $this->request
  93. ->expects($this->once())
  94. ->method('getCookie')
  95. ->with('oc_token')
  96. ->willReturn('MyLoginToken');
  97. $user = $this->getMock('\\OCP\\IUser');
  98. $user
  99. ->expects($this->once())
  100. ->method('getUID')
  101. ->willReturn('JohnDoe');
  102. $this->userSession
  103. ->expects($this->once())
  104. ->method('getUser')
  105. ->willReturn($user);
  106. $this->config
  107. ->expects($this->once())
  108. ->method('deleteUserValue')
  109. ->with('JohnDoe', 'login_token', 'MyLoginToken');
  110. $this->urlGenerator
  111. ->expects($this->once())
  112. ->method('linkToRouteAbsolute')
  113. ->with('core.login.showLoginForm')
  114. ->willReturn('/login');
  115. $expected = new RedirectResponse('/login');
  116. $this->assertEquals($expected, $this->loginController->logout());
  117. }
  118. public function testShowLoginFormForLoggedInUsers() {
  119. $this->userSession
  120. ->expects($this->once())
  121. ->method('isLoggedIn')
  122. ->willReturn(true);
  123. $expectedResponse = new RedirectResponse(\OC_Util::getDefaultPageUrl());
  124. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('', '', ''));
  125. }
  126. public function testShowLoginFormWithErrorsInSession() {
  127. $this->userSession
  128. ->expects($this->once())
  129. ->method('isLoggedIn')
  130. ->willReturn(false);
  131. $this->session
  132. ->expects($this->once())
  133. ->method('get')
  134. ->with('loginMessages')
  135. ->willReturn(
  136. [
  137. [
  138. 'ErrorArray1',
  139. 'ErrorArray2',
  140. ],
  141. [
  142. 'MessageArray1',
  143. 'MessageArray2',
  144. ],
  145. ]
  146. );
  147. $expectedResponse = new TemplateResponse(
  148. 'core',
  149. 'login',
  150. [
  151. 'ErrorArray1' => true,
  152. 'ErrorArray2' => true,
  153. 'messages' => [
  154. 'MessageArray1',
  155. 'MessageArray2',
  156. ],
  157. 'loginName' => '',
  158. 'user_autofocus' => true,
  159. 'canResetPassword' => true,
  160. 'alt_login' => [],
  161. 'rememberLoginAllowed' => \OC_Util::rememberLoginAllowed(),
  162. 'rememberLoginState' => 0,
  163. ],
  164. 'guest'
  165. );
  166. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('', '', ''));
  167. }
  168. /**
  169. * @return array
  170. */
  171. public function passwordResetDataProvider() {
  172. return [
  173. [
  174. true,
  175. true,
  176. ],
  177. [
  178. false,
  179. false,
  180. ],
  181. ];
  182. }
  183. /**
  184. * @dataProvider passwordResetDataProvider
  185. */
  186. public function testShowLoginFormWithPasswordResetOption($canChangePassword,
  187. $expectedResult) {
  188. $this->userSession
  189. ->expects($this->once())
  190. ->method('isLoggedIn')
  191. ->willReturn(false);
  192. $this->config
  193. ->expects($this->once())
  194. ->method('getSystemValue')
  195. ->with('lost_password_link')
  196. ->willReturn(false);
  197. $user = $this->getMock('\\OCP\\IUser');
  198. $user
  199. ->expects($this->once())
  200. ->method('canChangePassword')
  201. ->willReturn($canChangePassword);
  202. $this->userManager
  203. ->expects($this->once())
  204. ->method('get')
  205. ->with('LdapUser')
  206. ->willReturn($user);
  207. $expectedResponse = new TemplateResponse(
  208. 'core',
  209. 'login',
  210. [
  211. 'messages' => [],
  212. 'loginName' => 'LdapUser',
  213. 'user_autofocus' => false,
  214. 'canResetPassword' => $expectedResult,
  215. 'alt_login' => [],
  216. 'rememberLoginAllowed' => \OC_Util::rememberLoginAllowed(),
  217. 'rememberLoginState' => 0,
  218. ],
  219. 'guest'
  220. );
  221. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('LdapUser', '', ''));
  222. }
  223. public function testShowLoginFormForUserNamedNull() {
  224. $this->userSession
  225. ->expects($this->once())
  226. ->method('isLoggedIn')
  227. ->willReturn(false);
  228. $this->config
  229. ->expects($this->once())
  230. ->method('getSystemValue')
  231. ->with('lost_password_link')
  232. ->willReturn(false);
  233. $user = $this->getMock('\\OCP\\IUser');
  234. $user
  235. ->expects($this->once())
  236. ->method('canChangePassword')
  237. ->willReturn(false);
  238. $this->userManager
  239. ->expects($this->once())
  240. ->method('get')
  241. ->with('0')
  242. ->willReturn($user);
  243. $expectedResponse = new TemplateResponse(
  244. 'core',
  245. 'login',
  246. [
  247. 'messages' => [],
  248. 'loginName' => '0',
  249. 'user_autofocus' => false,
  250. 'canResetPassword' => false,
  251. 'alt_login' => [],
  252. 'rememberLoginAllowed' => \OC_Util::rememberLoginAllowed(),
  253. 'rememberLoginState' => 0,
  254. ],
  255. 'guest'
  256. );
  257. $this->assertEquals($expectedResponse, $this->loginController->showLoginForm('0', '', ''));
  258. }
  259. public function testLoginWithInvalidCredentials() {
  260. $user = $this->getMock('\OCP\IUser');
  261. $password = 'secret';
  262. $loginPageUrl = 'some url';
  263. $this->userManager->expects($this->once())
  264. ->method('checkPassword')
  265. ->will($this->returnValue(false));
  266. $this->urlGenerator->expects($this->once())
  267. ->method('linkToRoute')
  268. ->with('core.login.showLoginForm')
  269. ->will($this->returnValue($loginPageUrl));
  270. $this->userSession->expects($this->never())
  271. ->method('createSessionToken');
  272. $expected = new \OCP\AppFramework\Http\RedirectResponse($loginPageUrl);
  273. $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, ''));
  274. }
  275. public function testLoginWithValidCredentials() {
  276. $user = $this->getMock('\OCP\IUser');
  277. $password = 'secret';
  278. $indexPageUrl = 'some url';
  279. $this->userManager->expects($this->once())
  280. ->method('checkPassword')
  281. ->will($this->returnValue($user));
  282. $this->userSession->expects($this->once())
  283. ->method('createSessionToken')
  284. ->with($this->request, $user->getUID(), $password);
  285. $this->twoFactorManager->expects($this->once())
  286. ->method('isTwoFactorAuthenticated')
  287. ->with($user)
  288. ->will($this->returnValue(false));
  289. $this->urlGenerator->expects($this->once())
  290. ->method('linkToRoute')
  291. ->with('files.view.index')
  292. ->will($this->returnValue($indexPageUrl));
  293. $expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl);
  294. $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null));
  295. }
  296. public function testLoginWithValidCredentialsAndRedirectUrl() {
  297. $user = $this->getMock('\OCP\IUser');
  298. $user->expects($this->any())
  299. ->method('getUID')
  300. ->will($this->returnValue('jane'));
  301. $password = 'secret';
  302. $originalUrl = 'another%20url';
  303. $redirectUrl = 'http://localhost/another url';
  304. $this->userManager->expects($this->once())
  305. ->method('checkPassword')
  306. ->with('jane', $password)
  307. ->will($this->returnValue($user));
  308. $this->userSession->expects($this->once())
  309. ->method('createSessionToken')
  310. ->with($this->request, $user->getUID(), $password);
  311. $this->userSession->expects($this->once())
  312. ->method('isLoggedIn')
  313. ->with()
  314. ->will($this->returnValue(true));
  315. $this->urlGenerator->expects($this->once())
  316. ->method('getAbsoluteURL')
  317. ->with(urldecode($originalUrl))
  318. ->will($this->returnValue($redirectUrl));
  319. $expected = new \OCP\AppFramework\Http\RedirectResponse(urldecode($redirectUrl));
  320. $this->assertEquals($expected, $this->loginController->tryLogin($user->getUID(), $password, $originalUrl));
  321. }
  322. public function testLoginWithTwoFactorEnforced() {
  323. $user = $this->getMock('\OCP\IUser');
  324. $password = 'secret';
  325. $challengeUrl = 'challenge/url';
  326. $this->userManager->expects($this->once())
  327. ->method('checkPassword')
  328. ->will($this->returnValue($user));
  329. $this->userSession->expects($this->once())
  330. ->method('createSessionToken')
  331. ->with($this->request, $user->getUID(), $password);
  332. $this->twoFactorManager->expects($this->once())
  333. ->method('isTwoFactorAuthenticated')
  334. ->with($user)
  335. ->will($this->returnValue(true));
  336. $this->twoFactorManager->expects($this->once())
  337. ->method('prepareTwoFactorLogin')
  338. ->with($user);
  339. $this->urlGenerator->expects($this->once())
  340. ->method('linkToRoute')
  341. ->with('core.TwoFactorChallenge.selectChallenge')
  342. ->will($this->returnValue($challengeUrl));
  343. $expected = new \OCP\AppFramework\Http\RedirectResponse($challengeUrl);
  344. $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null));
  345. }
  346. }