/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserServiceTest.java

https://gitlab.com/unofficial-mirrors/eclipse-che · Java · 426 lines · 342 code · 67 blank · 17 comment · 0 complexity · fcba34915612c375851f95988053a1d0 MD5 · raw file

  1. /*******************************************************************************
  2. * Copyright (c) 2012-2016 Codenvy, S.A.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * Codenvy, S.A. - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.che.api.user.server;
  12. import com.google.common.collect.ImmutableMap;
  13. import com.google.gson.Gson;
  14. import com.google.gson.reflect.TypeToken;
  15. import com.jayway.restassured.response.Response;
  16. import org.eclipse.che.account.api.AccountManager;
  17. import org.eclipse.che.account.spi.AccountValidator;
  18. import org.eclipse.che.api.core.ConflictException;
  19. import org.eclipse.che.api.core.model.user.User;
  20. import org.eclipse.che.api.core.rest.ApiExceptionMapper;
  21. import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
  22. import org.eclipse.che.api.user.server.model.impl.UserImpl;
  23. import org.eclipse.che.api.user.shared.dto.UserDto;
  24. import org.eclipse.che.commons.env.EnvironmentContext;
  25. import org.eclipse.che.commons.subject.Subject;
  26. import org.eclipse.che.commons.subject.SubjectImpl;
  27. import org.eclipse.che.dto.server.DtoFactory;
  28. import org.everrest.assured.EverrestJetty;
  29. import org.everrest.core.Filter;
  30. import org.everrest.core.GenericContainerRequest;
  31. import org.everrest.core.RequestFilter;
  32. import org.mockito.Answers;
  33. import org.mockito.ArgumentCaptor;
  34. import org.mockito.Captor;
  35. import org.mockito.Mock;
  36. import org.mockito.testng.MockitoTestNGListener;
  37. import org.testng.annotations.BeforeMethod;
  38. import org.testng.annotations.Listeners;
  39. import org.testng.annotations.Test;
  40. import java.util.Map;
  41. import static com.jayway.restassured.RestAssured.given;
  42. import static java.util.Collections.emptyList;
  43. import static org.eclipse.che.dto.server.DtoFactory.newDto;
  44. import static org.everrest.assured.JettyHttpServer.ADMIN_USER_NAME;
  45. import static org.everrest.assured.JettyHttpServer.ADMIN_USER_PASSWORD;
  46. import static org.everrest.assured.JettyHttpServer.SECURE_PATH;
  47. import static org.mockito.Matchers.any;
  48. import static org.mockito.Matchers.anyBoolean;
  49. import static org.mockito.Mockito.verify;
  50. import static org.mockito.Mockito.when;
  51. import static org.mockito.MockitoAnnotations.initMocks;
  52. import static org.testng.Assert.assertEquals;
  53. /**
  54. * Tests for {@link UserService}
  55. *
  56. * @author Eugene Veovodin
  57. * @author Max Shaposhnik
  58. */
  59. @Listeners({EverrestJetty.class, MockitoTestNGListener.class})
  60. public class UserServiceTest {
  61. @SuppressWarnings("unused")
  62. private static final ApiExceptionMapper MAPPER = new ApiExceptionMapper();
  63. @SuppressWarnings("unused")
  64. private static final EnvironmentFilter FILTER = new EnvironmentFilter();
  65. private static final Subject SUBJECT = new SubjectImpl("user", "user123", "token", false);
  66. @Mock(answer = Answers.RETURNS_MOCKS)
  67. private UserManager userManager;
  68. @Mock
  69. private AccountManager accountManager;
  70. @Mock
  71. private TokenValidator tokenValidator;
  72. @Mock
  73. private UserLinksInjector linksInjector;
  74. private UserValidator userValidator;
  75. @Captor
  76. private ArgumentCaptor<User> userCaptor;
  77. private UserService userService;
  78. @BeforeMethod
  79. public void initService() {
  80. initMocks(this);
  81. userValidator = new UserValidator(new AccountValidator(accountManager));
  82. // Return the incoming instance when injectLinks is called
  83. when(linksInjector.injectLinks(any(), any())).thenAnswer(inv -> inv.getArguments()[0]);
  84. userService = new UserService(userManager, tokenValidator, userValidator, linksInjector, true);
  85. }
  86. @Test
  87. public void shouldCreateUserFromToken() throws Exception {
  88. when(tokenValidator.validateToken("token_value")).thenReturn(new UserImpl("id", "test@eclipse.org", "test"));
  89. final Response response = given().auth()
  90. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  91. .when()
  92. .contentType("application/json")
  93. .post(SECURE_PATH + "/user?token=token_value");
  94. assertEquals(response.statusCode(), 201);
  95. verify(userManager).create(userCaptor.capture(), anyBoolean());
  96. final User user = userCaptor.getValue();
  97. assertEquals(user.getEmail(), "test@eclipse.org");
  98. assertEquals(user.getName(), "test");
  99. }
  100. @Test
  101. public void shouldCreateUserFromEntity() throws Exception {
  102. final UserDto newUser = newDto(UserDto.class).withName("test")
  103. .withEmail("test@codenvy.com")
  104. .withPassword("password12345");
  105. final Response response = given().auth()
  106. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  107. .when()
  108. .body(newUser)
  109. .contentType("application/json")
  110. .post(SECURE_PATH + "/user");
  111. assertEquals(response.statusCode(), 201);
  112. verify(userManager).create(userCaptor.capture(), anyBoolean());
  113. final User user = userCaptor.getValue();
  114. assertEquals(user.getEmail(), "test@codenvy.com");
  115. assertEquals(user.getName(), "test");
  116. assertEquals(user.getPassword(), "password12345");
  117. }
  118. @Test
  119. public void shouldNotCreateUserFromEntityWhenPasswordIsNotValid() throws Exception {
  120. final UserDto newUser = newDto(UserDto.class).withName("test")
  121. .withEmail("test@codenvy.com")
  122. .withPassword("1");
  123. final Response response = given().auth()
  124. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  125. .when()
  126. .body(newUser)
  127. .contentType("application/json")
  128. .post(SECURE_PATH + "/user");
  129. assertEquals(response.statusCode(), 400);
  130. assertEquals(unwrapError(response), "Password should contain at least 8 characters");
  131. }
  132. @Test
  133. public void shouldNotCreateUserIfTokenIsNotValid() throws Exception {
  134. when(tokenValidator.validateToken("token_value")).thenThrow(new ConflictException("error"));
  135. final Response response = given().auth()
  136. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  137. .when()
  138. .contentType("application/json")
  139. .post(SECURE_PATH + "/user?token=token_value");
  140. assertEquals(response.statusCode(), 409);
  141. assertEquals(unwrapError(response), "error");
  142. }
  143. @Test
  144. public void shouldNotCreateUserFromEntityIfEntityIsNull() throws Exception {
  145. final Response response = given().auth()
  146. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  147. .when()
  148. .contentType("application/json")
  149. .post(SECURE_PATH + "/user");
  150. assertEquals(response.statusCode(), 400);
  151. assertEquals(unwrapError(response), "User required");
  152. }
  153. @Test
  154. public void shouldNotCreateUserFromEntityIfEmailIsNull() throws Exception {
  155. final UserDto newUser = newDto(UserDto.class).withName("test")
  156. .withPassword("password12345");
  157. final Response response = given().auth()
  158. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  159. .when()
  160. .body(newUser)
  161. .contentType("application/json")
  162. .post(SECURE_PATH + "/user");
  163. assertEquals(response.statusCode(), 400);
  164. assertEquals(unwrapError(response), "User email required");
  165. }
  166. @Test
  167. public void shouldNotCreateUserFromEntityIfNameIsNull() throws Exception {
  168. final UserDto newUser = newDto(UserDto.class).withEmail("test@codenvy.com")
  169. .withPassword("password12345");
  170. final Response response = given().auth()
  171. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  172. .when()
  173. .body(newUser)
  174. .contentType("application/json")
  175. .post(SECURE_PATH + "/user");
  176. assertEquals(response.statusCode(), 400);
  177. assertEquals(unwrapError(response), "User name required");
  178. }
  179. @Test
  180. public void shouldNotCreateUserFromEntityIfPasswordIsNotValid() throws Exception {
  181. final UserDto newUser = newDto(UserDto.class).withEmail("test@codenvy.com")
  182. .withName("test")
  183. .withPassword("1");
  184. final Response response = given().auth()
  185. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  186. .when()
  187. .body(newUser)
  188. .contentType("application/json")
  189. .post(SECURE_PATH + "/user");
  190. assertEquals(response.statusCode(), 400);
  191. assertEquals(unwrapError(response), "Password should contain at least 8 characters");
  192. }
  193. @Test
  194. public void shouldBeAbleToGetCurrentUser() throws Exception {
  195. when(userManager.getById(SUBJECT.getUserId())).thenReturn(copySubject());
  196. final Response response = given().auth()
  197. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  198. .when()
  199. .get(SECURE_PATH + "/user");
  200. assertEquals(response.getStatusCode(), 200);
  201. }
  202. @Test
  203. public void shouldBeAbleToGetUserById() throws Exception {
  204. final UserImpl testUser = copySubject();
  205. when(userManager.getById(SUBJECT.getUserId())).thenReturn(testUser);
  206. final Response response = given().auth()
  207. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  208. .when()
  209. .get(SECURE_PATH + "/user/" + SUBJECT.getUserId());
  210. assertEquals(response.getStatusCode(), 200);
  211. final UserDto fetchedUser = unwrapDto(response, UserDto.class);
  212. assertEquals(fetchedUser.getId(), testUser.getId());
  213. assertEquals(fetchedUser.getName(), testUser.getName());
  214. assertEquals(fetchedUser.getEmail(), testUser.getEmail());
  215. }
  216. @Test
  217. public void shouldBeAbleToFindUserByEmail() throws Exception {
  218. final UserImpl testUser = copySubject();
  219. when(userManager.getByEmail(testUser.getEmail())).thenReturn(testUser);
  220. final Response response = given().auth()
  221. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  222. .when()
  223. .get(SECURE_PATH + "/user/find?email=" + testUser.getEmail());
  224. assertEquals(response.getStatusCode(), 200);
  225. final UserDto fetchedUser = unwrapDto(response, UserDto.class);
  226. assertEquals(fetchedUser.getId(), testUser.getId());
  227. assertEquals(fetchedUser.getName(), testUser.getName());
  228. assertEquals(fetchedUser.getEmail(), testUser.getEmail());
  229. }
  230. @Test
  231. public void shouldBeAbleToFindUserByName() throws Exception {
  232. final UserImpl testUser = copySubject();
  233. when(userManager.getByName(testUser.getName())).thenReturn(testUser);
  234. final Response response = given().auth()
  235. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  236. .when()
  237. .get(SECURE_PATH + "/user/find?name=" + testUser.getName());
  238. assertEquals(response.getStatusCode(), 200);
  239. final UserDto fetchedUser = unwrapDto(response, UserDto.class);
  240. assertEquals(fetchedUser.getId(), testUser.getId());
  241. assertEquals(fetchedUser.getName(), testUser.getName());
  242. assertEquals(fetchedUser.getEmail(), testUser.getEmail());
  243. }
  244. @Test
  245. public void shouldNotFindUserByNameOrEmailWhenBothSpecified() throws Exception {
  246. final UserImpl testUser = copySubject();
  247. when(userManager.getByName(testUser.getName())).thenReturn(testUser);
  248. final Response response = given().auth()
  249. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  250. .when()
  251. .get(SECURE_PATH + "/user/find?" +
  252. "name=" + testUser.getName() +
  253. "&email=" + testUser.getEmail());
  254. assertEquals(response.getStatusCode(), 400);
  255. assertEquals(unwrapError(response), "Expected either user's email or name, while both values received");
  256. }
  257. @Test
  258. public void shouldNotFindUserByNameOrEmailWhenBothAreEmpty() throws Exception {
  259. final UserImpl testUser = copySubject();
  260. when(userManager.getByName(testUser.getName())).thenReturn(testUser);
  261. final Response response = given().auth()
  262. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  263. .when()
  264. .get(SECURE_PATH + "/user/find");
  265. assertEquals(response.getStatusCode(), 400);
  266. assertEquals(unwrapError(response), "Missed user's email or name");
  267. }
  268. @Test
  269. public void shouldUpdatePassword() throws Exception {
  270. final UserImpl testUser = copySubject();
  271. when(userManager.getById(testUser.getId())).thenReturn(testUser);
  272. final Response response = given().auth()
  273. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  274. .contentType("application/x-www-form-urlencoded")
  275. .body("password=password12345")
  276. .when()
  277. .post(SECURE_PATH + "/user/password");
  278. verify(userManager).update(userCaptor.capture());
  279. final User fetchedUser = userCaptor.getValue();
  280. assertEquals(fetchedUser.getPassword(), "password12345");
  281. }
  282. @Test
  283. public void shouldNotUpdatePasswordIfPasswordContainsOnlyDigits() throws Exception {
  284. final UserImpl testUser = copySubject();
  285. when(userManager.getById(testUser.getId())).thenReturn(testUser);
  286. final Response response = given().auth()
  287. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  288. .contentType("application/x-www-form-urlencoded")
  289. .body("password=1234567890")
  290. .when()
  291. .post(SECURE_PATH + "/user/password");
  292. assertEquals(response.getStatusCode(), 400);
  293. assertEquals(unwrapError(response), "Password should contain letters and digits");
  294. }
  295. @Test
  296. public void shouldNotUpdatePasswordIfPasswordContainsLessThan8Chars() throws Exception {
  297. final UserImpl testUser = copySubject();
  298. when(userManager.getById(testUser.getId())).thenReturn(testUser);
  299. final Response response = given().auth()
  300. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  301. .contentType("application/x-www-form-urlencoded")
  302. .body("password=0xf")
  303. .when()
  304. .post(SECURE_PATH + "/user/password");
  305. assertEquals(response.getStatusCode(), 400);
  306. assertEquals(unwrapError(response), "Password should contain at least 8 characters");
  307. }
  308. @Test
  309. public void shouldNotUpdatePasswordIfPasswordIsNull() throws Exception {
  310. final UserImpl testUser = copySubject();
  311. when(userManager.getById(testUser.getId())).thenReturn(testUser);
  312. final Response response = given().auth()
  313. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  314. .contentType("application/x-www-form-urlencoded")
  315. .when()
  316. .post(SECURE_PATH + "/user/password");
  317. assertEquals(response.getStatusCode(), 400);
  318. assertEquals(unwrapError(response), "Password required");
  319. }
  320. @Test
  321. public void shouldRemoveUser() throws Exception {
  322. final Response response = given().auth()
  323. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  324. .when()
  325. .delete(SECURE_PATH + "/user/" + SUBJECT.getUserId());
  326. assertEquals(response.getStatusCode(), 204);
  327. verify(userManager).remove(SUBJECT.getUserId());
  328. }
  329. @Test
  330. public void shouldBeAbleToGetSettings() throws Exception {
  331. final Response response = given().auth()
  332. .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
  333. .when()
  334. .get(SECURE_PATH + "/user/settings");
  335. assertEquals(response.getStatusCode(), 200);
  336. final Map<String, String> settings = new Gson().fromJson(response.print(),
  337. new TypeToken<Map<String, String>>() {}.getType());
  338. assertEquals(settings, ImmutableMap.of("che.auth.user_self_creation", "true"));
  339. }
  340. @Filter
  341. public static class EnvironmentFilter implements RequestFilter {
  342. public void doFilter(GenericContainerRequest request) {
  343. EnvironmentContext.getCurrent().setSubject(SUBJECT);
  344. }
  345. }
  346. private static <T> T unwrapDto(Response response, Class<T> dtoClass) {
  347. return DtoFactory.getInstance().createDtoFromJson(response.body().print(), dtoClass);
  348. }
  349. private static String unwrapError(Response response) {
  350. return unwrapDto(response, ServiceError.class).getMessage();
  351. }
  352. private static UserImpl copySubject() {
  353. return new UserImpl(SUBJECT.getUserId(),
  354. SUBJECT.getUserName() + "@codenvy.com",
  355. SUBJECT.getUserName(),
  356. null,
  357. emptyList());
  358. }
  359. }