package org.datasurvey.web.rest; import java.net.URI; import java.net.URISyntaxException; import java.util.*; import java.util.Collections; import javax.validation.Valid; import javax.validation.constraints.Pattern; import org.datasurvey.config.Constants; import org.datasurvey.domain.User; import org.datasurvey.repository.UserRepository; import org.datasurvey.security.AuthoritiesConstants; import org.datasurvey.service.MailService; import org.datasurvey.service.UserService; import org.datasurvey.service.dto.AdminUserDTO; import org.datasurvey.web.rest.errors.BadRequestAlertException; import org.datasurvey.web.rest.errors.EmailAlreadyUsedException; import org.datasurvey.web.rest.errors.LoginAlreadyUsedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import tech.jhipster.web.util.HeaderUtil; import tech.jhipster.web.util.PaginationUtil; import tech.jhipster.web.util.ResponseUtil; /** * REST controller for managing users. *

* This class accesses the {@link User} entity, and needs to fetch its collection of authorities. *

* For a normal use-case, it would be better to have an eager relationship between User and Authority, * and send everything to the client side: there would be no View Model and DTO, a lot less code, and an outer-join * which would be good for performance. *

* We use a View Model and a DTO for 3 reasons: *

*

* Another option would be to have a specific JPA entity graph to handle this case. */ @RestController @RequestMapping("/api/admin") public class UserResource { private static final List ALLOWED_ORDERED_PROPERTIES = Collections.unmodifiableList( Arrays.asList( "id", "login", "firstName", "lastName", "email", "activated", "langKey", "createdBy", "createdDate", "lastModifiedBy", "lastModifiedDate" ) ); private final Logger log = LoggerFactory.getLogger(UserResource.class); @Value("${jhipster.clientApp.name}") private String applicationName; private final UserService userService; private final UserRepository userRepository; private final MailService mailService; public UserResource(UserService userService, UserRepository userRepository, MailService mailService) { this.userService = userService; this.userRepository = userRepository; this.mailService = mailService; } /** * {@code POST /admin/users} : Creates a new user. *

* Creates a new user if the login and email are not already used, and sends an * mail with an activation link. * The user needs to be activated on creation. * * @param userDTO the user to create. * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new user, or with status {@code 400 (Bad Request)} if the login or email is already in use. * @throws URISyntaxException if the Location URI syntax is incorrect. * @throws BadRequestAlertException {@code 400 (Bad Request)} if the login or email is already in use. */ @PostMapping("/users") @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") public ResponseEntity createUser(@Valid @RequestBody AdminUserDTO userDTO) throws URISyntaxException { log.debug("REST request to save User : {}", userDTO); if (userDTO.getId() != null) { throw new BadRequestAlertException("A new user cannot already have an ID", "userManagement", "idexists"); // Lowercase the user login before comparing with database } else if (userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).isPresent()) { throw new LoginAlreadyUsedException(); } else if (userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).isPresent()) { throw new EmailAlreadyUsedException(); } else { User newUser = userService.createUser(userDTO); mailService.sendCreationEmail(newUser); return ResponseEntity .created(new URI("/api/admin/users/" + newUser.getLogin())) .headers(HeaderUtil.createAlert(applicationName, "userManagement.created", newUser.getLogin())) .body(newUser); } } /** * {@code PUT /admin/users} : Updates an existing User. * * @param userDTO the user to update. * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated user. * @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already in use. * @throws LoginAlreadyUsedException {@code 400 (Bad Request)} if the login is already in use. */ @PutMapping("/users") @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") public ResponseEntity updateUser(@Valid @RequestBody AdminUserDTO userDTO) { log.debug("REST request to update User : {}", userDTO); Optional existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()); if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) { throw new EmailAlreadyUsedException(); } existingUser = userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()); if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) { throw new LoginAlreadyUsedException(); } Optional updatedUser = userService.updateUser(userDTO); return ResponseUtil.wrapOrNotFound( updatedUser, HeaderUtil.createAlert(applicationName, "userManagement.updated", userDTO.getLogin()) ); } /** * {@code GET /admin/users} : get all users with all the details - calling this are only allowed for the administrators. * * @param pageable the pagination information. * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body all users. */ @GetMapping("/users") @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") public ResponseEntity> getAllUsers(Pageable pageable) { log.debug("REST request to get all User for an admin"); if (!onlyContainsAllowedProperties(pageable)) { return ResponseEntity.badRequest().build(); } final Page page = userService.getAllManagedUsers(pageable); HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); } private boolean onlyContainsAllowedProperties(Pageable pageable) { return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains); } /** * {@code GET /admin/users/:login} : get the "login" user. * * @param login the login of the user to find. * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the "login" user, or with status {@code 404 (Not Found)}. */ @GetMapping("/users/{login}") @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") public ResponseEntity getUser(@PathVariable @Pattern(regexp = Constants.LOGIN_REGEX) String login) { log.debug("REST request to get User : {}", login); return ResponseUtil.wrapOrNotFound(userService.getUserWithAuthoritiesByLogin(login).map(AdminUserDTO::new)); } /** * {@code DELETE /admin/users/:login} : delete the "login" User. * * @param login the login of the user to delete. * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. */ @DeleteMapping("/users/{login}") @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") public ResponseEntity deleteUser(@PathVariable @Pattern(regexp = Constants.LOGIN_REGEX) String login) { log.debug("REST request to delete User: {}", login); userService.deleteUser(login); return ResponseEntity.noContent().headers(HeaderUtil.createAlert(applicationName, "userManagement.deleted", login)).build(); } }