UserResource.java 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package rocks.zipcode.io.web.rest;
  2. import rocks.zipcode.io.config.Constants;
  3. import rocks.zipcode.io.domain.User;
  4. import rocks.zipcode.io.repository.UserRepository;
  5. import rocks.zipcode.io.security.AuthoritiesConstants;
  6. import rocks.zipcode.io.service.MailService;
  7. import rocks.zipcode.io.service.UserService;
  8. import rocks.zipcode.io.service.dto.UserDTO;
  9. import rocks.zipcode.io.web.rest.errors.BadRequestAlertException;
  10. import rocks.zipcode.io.web.rest.errors.EmailAlreadyUsedException;
  11. import rocks.zipcode.io.web.rest.errors.LoginAlreadyUsedException;
  12. import rocks.zipcode.io.web.rest.util.HeaderUtil;
  13. import rocks.zipcode.io.web.rest.util.PaginationUtil;
  14. import com.codahale.metrics.annotation.Timed;
  15. import io.github.jhipster.web.util.ResponseUtil;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18. import org.springframework.data.domain.Page;
  19. import org.springframework.data.domain.Pageable;
  20. import org.springframework.http.HttpHeaders;
  21. import org.springframework.http.HttpStatus;
  22. import org.springframework.http.ResponseEntity;
  23. import org.springframework.security.access.prepost.PreAuthorize;
  24. import org.springframework.web.bind.annotation.*;
  25. import javax.validation.Valid;
  26. import java.net.URI;
  27. import java.net.URISyntaxException;
  28. import java.util.*;
  29. /**
  30. * REST controller for managing users.
  31. * <p>
  32. * This class accesses the User entity, and needs to fetch its collection of authorities.
  33. * <p>
  34. * For a normal use-case, it would be better to have an eager relationship between User and Authority,
  35. * and send everything to the client side: there would be no View Model and DTO, a lot less code, and an outer-join
  36. * which would be good for performance.
  37. * <p>
  38. * We use a View Model and a DTO for 3 reasons:
  39. * <ul>
  40. * <li>We want to keep a lazy association between the user and the authorities, because people will
  41. * quite often do relationships with the user, and we don't want them to get the authorities all
  42. * the time for nothing (for performance reasons). This is the #1 goal: we should not impact our users'
  43. * application because of this use-case.</li>
  44. * <li> Not having an outer join causes n+1 requests to the database. This is not a real issue as
  45. * we have by default a second-level cache. This means on the first HTTP call we do the n+1 requests,
  46. * but then all authorities come from the cache, so in fact it's much better than doing an outer join
  47. * (which will get lots of data from the database, for each HTTP call).</li>
  48. * <li> As this manages users, for security reasons, we'd rather have a DTO layer.</li>
  49. * </ul>
  50. * <p>
  51. * Another option would be to have a specific JPA entity graph to handle this case.
  52. */
  53. @RestController
  54. @RequestMapping("/api")
  55. public class UserResource {
  56. private final Logger log = LoggerFactory.getLogger(UserResource.class);
  57. private final UserService userService;
  58. private final UserRepository userRepository;
  59. private final MailService mailService;
  60. public UserResource(UserService userService, UserRepository userRepository, MailService mailService) {
  61. this.userService = userService;
  62. this.userRepository = userRepository;
  63. this.mailService = mailService;
  64. }
  65. /**
  66. * POST /users : Creates a new user.
  67. * <p>
  68. * Creates a new user if the login and email are not already used, and sends an
  69. * mail with an activation link.
  70. * The user needs to be activated on creation.
  71. *
  72. * @param userDTO the user to create
  73. * @return the ResponseEntity with status 201 (Created) and with body the new user, or with status 400 (Bad Request) if the login or email is already in use
  74. * @throws URISyntaxException if the Location URI syntax is incorrect
  75. * @throws BadRequestAlertException 400 (Bad Request) if the login or email is already in use
  76. */
  77. @PostMapping("/users")
  78. @Timed
  79. @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
  80. public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO userDTO) throws URISyntaxException {
  81. log.debug("REST request to save User : {}", userDTO);
  82. if (userDTO.getId() != null) {
  83. throw new BadRequestAlertException("A new user cannot already have an ID", "userManagement", "idexists");
  84. // Lowercase the user login before comparing with database
  85. } else if (userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).isPresent()) {
  86. throw new LoginAlreadyUsedException();
  87. } else if (userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).isPresent()) {
  88. throw new EmailAlreadyUsedException();
  89. } else {
  90. User newUser = userService.createUser(userDTO);
  91. mailService.sendCreationEmail(newUser);
  92. return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin()))
  93. .headers(HeaderUtil.createAlert( "userManagement.created", newUser.getLogin()))
  94. .body(newUser);
  95. }
  96. }
  97. /**
  98. * PUT /users : Updates an existing User.
  99. *
  100. * @param userDTO the user to update
  101. * @return the ResponseEntity with status 200 (OK) and with body the updated user
  102. * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already in use
  103. * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already in use
  104. */
  105. @PutMapping("/users")
  106. @Timed
  107. @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
  108. public ResponseEntity<UserDTO> updateUser(@Valid @RequestBody UserDTO userDTO) {
  109. log.debug("REST request to update User : {}", userDTO);
  110. Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail());
  111. if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) {
  112. throw new EmailAlreadyUsedException();
  113. }
  114. existingUser = userRepository.findOneByLogin(userDTO.getLogin().toLowerCase());
  115. if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) {
  116. throw new LoginAlreadyUsedException();
  117. }
  118. Optional<UserDTO> updatedUser = userService.updateUser(userDTO);
  119. return ResponseUtil.wrapOrNotFound(updatedUser,
  120. HeaderUtil.createAlert("userManagement.updated", userDTO.getLogin()));
  121. }
  122. /**
  123. * GET /users : get all users.
  124. *
  125. * @param pageable the pagination information
  126. * @return the ResponseEntity with status 200 (OK) and with body all users
  127. */
  128. @GetMapping("/users")
  129. @Timed
  130. public ResponseEntity<List<UserDTO>> getAllUsers(Pageable pageable) {
  131. final Page<UserDTO> page = userService.getAllManagedUsers(pageable);
  132. HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/users");
  133. return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
  134. }
  135. /**
  136. * @return a string list of the all of the roles
  137. */
  138. @GetMapping("/users/authorities")
  139. @Timed
  140. @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
  141. public List<String> getAuthorities() {
  142. return userService.getAuthorities();
  143. }
  144. /**
  145. * GET /users/:login : get the "login" user.
  146. *
  147. * @param login the login of the user to find
  148. * @return the ResponseEntity with status 200 (OK) and with body the "login" user, or with status 404 (Not Found)
  149. */
  150. @GetMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
  151. @Timed
  152. public ResponseEntity<UserDTO> getUser(@PathVariable String login) {
  153. log.debug("REST request to get User : {}", login);
  154. return ResponseUtil.wrapOrNotFound(
  155. userService.getUserWithAuthoritiesByLogin(login)
  156. .map(UserDTO::new));
  157. }
  158. /**
  159. * DELETE /users/:login : delete the "login" User.
  160. *
  161. * @param login the login of the user to delete
  162. * @return the ResponseEntity with status 200 (OK)
  163. */
  164. @DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
  165. @Timed
  166. @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
  167. public ResponseEntity<Void> deleteUser(@PathVariable String login) {
  168. log.debug("REST request to delete User: {}", login);
  169. userService.deleteUser(login);
  170. return ResponseEntity.ok().headers(HeaderUtil.createAlert( "userManagement.deleted", login)).build();
  171. }
  172. }