package it.demo.twitterlike.server.web.api; import it.demo.twitterlike.server.domain.Message; import it.demo.twitterlike.server.domain.User; import it.demo.twitterlike.server.repository.MessageRepository; import it.demo.twitterlike.server.repository.UserRepository; import it.demo.twitterlike.server.repository.utils.RepositoryUtils; import it.demo.twitterlike.server.service.UserService; import it.demo.twitterlike.server.web.api.domain.MessageResource; import it.demo.twitterlike.server.web.api.domain.UserResource; import it.demo.twitterlike.server.web.api.support.MessageResourceAssembler; import it.demo.twitterlike.server.web.api.support.UserResourceAssembler; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.data.web.PageableDefault; import org.springframework.data.web.PagedResourcesAssembler; import org.springframework.hateoas.PagedResources; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.bind.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiOperation; import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; @RestController @RequestMapping(value = ApiEndpoints.API_ENDPOINT_PEOPLE, produces = { "application/hal+json", "application/json" , "application/xml"}) @Api( position = 1, value = "User Rest API", description = "Secured API for managing persons follow list") public class UserRestController extends AbstractApiController { private static final String LOGIN_PREFIX = "/{login:.+}"; private static final String TARGET_SUFFIX = "/{targets:.+}"; public final static Log LOG = LogFactory.getLog(UserRestController.class); private final UserRepository userRepository; private final MessageRepository messageRepository; private final UserService userService; @Autowired public UserRestController(UserResourceAssembler userResourceAssembler, UserService userService, UserRepository userRepository, MessageRepository messageRepository, MessageResourceAssembler messageResourceAssembler) { super(messageResourceAssembler, userResourceAssembler); this.userRepository = userRepository; this.userService = userService; this.messageRepository = messageRepository; } @RequestMapping(value = ME_PREFIX, method = RequestMethod.GET) @ApiOperation(value = "me", notes = "Retrieves the authenticated user") @ApiResponses(value = { @ApiResponse(response = String.class, code = HttpServletResponse.SC_FORBIDDEN, message = "FORBIDDEN the source user is not authenticated.") }) public HttpEntity<UserResource> getMe( @AuthenticationPrincipal UserDetails userDetails) throws ResourceNotFoundException { return getUserById(userDetails.getUsername()); } @RequestMapping(value = LOGIN_PREFIX, method = RequestMethod.GET) public HttpEntity<UserResource> getUserById( @PathVariable("login") String login) throws ResourceNotFoundException { return new ResponseEntity<>( userResourceAssembler.toResource(getUser(login)), HttpStatus.OK); } @RequestMapping(method = RequestMethod.GET) @ApiOperation(value = "find-all", notes = "Retrieves all users") public HttpEntity<PagedResources<UserResource>> findAll( @PageableDefault(size = 10, page = 0) Pageable pageable, PagedResourcesAssembler<User> assembler) throws ResourceNotFoundException { return doReturnUserPagedResult(assembler, userRepository.findAll(pageable)); } @RequestMapping(value = LOGIN_PREFIX + "/followers", method = RequestMethod.GET) @ApiOperation(value = "get-followers", notes = "Retrieves the persons following the given person") public HttpEntity<PagedResources<UserResource>> getUserFollowers( @PathVariable String login, @PageableDefault(size = 10, page = 0) Pageable pageable, PagedResourcesAssembler<User> assembler) throws ResourceNotFoundException { return doReturnUserPagedResult(assembler, userRepository.findFollowersByLogin(existUser(login), pageable)); } @RequestMapping(value = ME_PREFIX + "/follows", method = RequestMethod.GET) @ApiOperation(value = "get-following", notes = "Retrieves the persons the authenticated user is following") public HttpEntity<PagedResources<UserResource>> getUserFollowing( @AuthenticationPrincipal UserDetails userDetails, @PageableDefault(size = 10, page = 0) Pageable pageable, PagedResourcesAssembler<User> assembler) throws ResourceNotFoundException { return getUserFollowing(userDetails.getUsername(), pageable, assembler); } @RequestMapping(value = LOGIN_PREFIX + "/follows", method = RequestMethod.GET) @ApiOperation(value = "get-following", notes = "Retrieves the persons the given user is following") public HttpEntity<PagedResources<UserResource>> getUserFollowing( @PathVariable String login, @PageableDefault(size = 10, page = 0) Pageable pageable, PagedResourcesAssembler<User> assembler) throws ResourceNotFoundException { return doReturnUserPagedResult(assembler, userRepository .findFollowingsByLogin(existUser(login), pageable)); } @RequestMapping(value = LOGIN_PREFIX + "/messages", method = RequestMethod.GET) @ApiOperation(value = "get-messages", notes = "Retrieves the messages posted by given user") public HttpEntity<PagedResources<MessageResource>> getUserMessages( @PathVariable String login, @PageableDefault(size = 10, page = 0) Pageable pageable, PagedResourcesAssembler<Message> assembler) throws ResourceNotFoundException { return doReturnMessagePagedResult(assembler, messageRepository.findMessagesByAuthorLogin(existUser(login), pageable)); } @RequestMapping(value = ME_PREFIX + "/follows/" + TARGET_SUFFIX, method = RequestMethod.POST) @ApiOperation(response = Void.class, value = "follow", notes = "Makes the source person follow the target person. Caller must be the source user for consistency.") @ApiResponses(value = { @ApiResponse(response = String.class, code = HttpServletResponse.SC_NOT_FOUND, message = "NOT FOUND one or both the given users to link can't be found."), @ApiResponse(response = String.class, code = HttpServletResponse.SC_FORBIDDEN, message = "FORBIDDEN the source user is not the one calling this API.") }) @ResponseStatus(HttpStatus.CREATED) public void follow(@AuthenticationPrincipal UserDetails userDetails, @PathVariable String[] targets) { userService.follow(userDetails.getUsername(), targets); } @RequestMapping(value = ME_PREFIX + "/follows/" + TARGET_SUFFIX, method = RequestMethod.DELETE) @ApiOperation(response = Void.class, value = "unfollow", notes = "Makes the authenticated user unfollow the target user") @ApiResponses(value = { @ApiResponse(response = String.class, code = HttpServletResponse.SC_NOT_FOUND, message = "NOT FOUND one or both the given users to link can't be found."), @ApiResponse(response = String.class, code = HttpServletResponse.SC_FORBIDDEN, message = "FORBIDDEN the source user is not the one calling this API.") }) public void unfollow(@AuthenticationPrincipal UserDetails userDetails, @PathVariable String[] targets) { userService.unfollow(userDetails.getUsername(), targets); } protected String existUser(String login) throws ResourceNotFoundException { return existEntity(userRepository, login); } protected User getUser(String login) throws ResourceNotFoundException { return RepositoryUtils.getEntity(userRepository, login); } }