package com.guams.review.controller; import com.guams.review.configuration.JwtTokenUtil; import com.guams.review.exception.AlreadyExistsException; import com.guams.review.exception.UnauthorizedExecption; import com.guams.review.exception.InvalidNameOrPasswordException; import com.guams.review.exception.NotFoundException; import com.guams.review.model.AuthorRepository; import com.guams.review.model.dao.Author; import com.guams.review.model.dao.AuthorToken; import com.guams.review.model.dao.Post; import com.guams.review.service.AuthorService; import com.guams.review.service.mapper.Mapper; import com.guams.review.service.mapper.ReturnableAuthor; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.util.Assert; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.List; import java.util.UUID; @RestController @RequestMapping(path = "api/authors") @RequiredArgsConstructor public class AuthorController { private final PasswordEncoder passwordEncoder; private final AuthenticationManager authenticationManager; private final AuthorService authorService; private final JwtTokenUtil jwtTokenUtil; private final AuthorRepository authorRepository; private final Mapper mapper; @GetMapping public List getUsers() { return authorService.list(); } @GetMapping("/{id}") public ReturnableAuthor findUser(@PathVariable UUID id) { Author author = authorService.findById(id).orElseThrow(() -> new NotFoundException("Author not found")); return mapper.mapAuthor(author); } @PutMapping("/{id}") public ReturnableAuthor updateUser(@PathVariable UUID id, @RequestBody Author updatedAuthor, Authentication authentication) { Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); if (passwordEncoder.matches(updatedAuthor.getPassword(), authorToUpdate.getPassword())) { return authorService.insert(updatedAuthor .setId(authorToUpdate.getId()) .setRole(authorToUpdate.getRole()) .setPassword(authorToUpdate.getPassword())); } else { throw new UnauthorizedExecption("You are not authorized to update this author"); } } // @PutMapping("/{id}/password") // public void changePassword(@PathVariable UUID id, @RequestBody Author updatedAuthor, Authentication authentication) { // Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); // if (passwordEncoder.matches(updatedAuthor.getPassword(), authorToUpdate.getPassword())) {} // } @PutMapping(value = "{id}/avatar", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) public Author updateUserAvatar(@PathVariable UUID id, @RequestPart MultipartFile avatar, Authentication authentication) throws IOException { Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); ReturnableAuthor authorToReturn = authorService.insert(authorToUpdate.setProfilePicture(avatar.getBytes())); return new Author() .setId(authorToReturn.getId()) .setName(authorToReturn.getName()) .setProfilePicture(null) .setRole(authorToReturn.getRole()) .setPassword(""); } @GetMapping("/{id}/avatar") public byte[] getProfilePicture(@PathVariable UUID id) { Author author = authorService.findById(id).orElseThrow(() -> new NotFoundException("Author not found")); return author.getProfilePicture(); } @DeleteMapping("/{id}") public void deleteUser(@PathVariable UUID id, Authentication authentication) { Author authorToDelete = authorService.verifyIfUserIsAuthorized(authentication, id); authorService.delete(authorToDelete); } @PutMapping("/{id}/posts") public void updateUserPosts(@PathVariable("id") UUID authorId, @RequestBody Long postId, Authentication authentication) { Author author = authorService.verifyIfUserIsAuthorized(authentication, authorId); authorService.insertPublications(author.getId(), postId); } @GetMapping("/{id}/posts") public List getUserPosts(@PathVariable UUID id) { Author author = authorService.findById(id).orElseThrow(() -> new NotFoundException("Author not found")); return authorService.listPublicationOfAuthor(author.getId()); } @PostMapping("/login") public AuthorToken authorLogin(@RequestBody Author author) { try { Author concernedAuthor = authorService.findByName(author.getName()).orElseThrow(() -> new NotFoundException("Author not found")); authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(concernedAuthor.getId(), author.getPassword()) ); String token = jwtTokenUtil.generateToken(concernedAuthor.getId().toString()); return new AuthorToken().setToken(token); } catch (Exception e) { throw new InvalidNameOrPasswordException(e.getMessage()); } } @PostMapping("/register") public ResponseEntity authorRegister(@RequestBody Author author) { Assert.isNull(author.getId(), "Author id must be null"); if (authorService.findByName(author.getName()).isPresent()) { throw new AlreadyExistsException("Author already exists"); } author.setPassword(passwordEncoder.encode(author.getPassword())); return new ResponseEntity<>(authorRepository.save(author.setRole("READER")).setPassword(""), HttpStatus.CREATED); } @GetMapping(value = "/me", produces = "application/json") public Author getAuthenticatedUser(Authentication authentication) { if (authentication == null || !authentication.isAuthenticated()) { throw new UnauthorizedExecption("You are not authorized to access this resource"); } Author author = authorService.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); return author.setPassword("").setProfilePicture(null); } }