Compare commits
	
		
			10 Commits
		
	
	
		
			189245ef42
			...
			c3dd337c7d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | c3dd337c7d | ||
|   | d14ae93f95 | ||
|   | b39307f7d9 | ||
|   | acd85c93e0 | ||
|   | 38b0f46f7f | ||
|   | fa920bd840 | ||
|   | 80a04c4614 | ||
| 300d3b7a32 | |||
| 64569c4f81 | |||
| d769bee503 | 
							
								
								
									
										30
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								pom.xml
									
									
									
									
									
								
							| @ -30,10 +30,6 @@ | ||||
| 		<java.version>21</java.version> | ||||
| 	</properties> | ||||
| 	<dependencies> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-data-jpa</artifactId> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-data-rest</artifactId> | ||||
| @ -58,6 +54,32 @@ | ||||
| 			<artifactId>spring-boot-starter-test</artifactId> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-data-jdbc</artifactId> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-security</artifactId> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.security</groupId> | ||||
| 			<artifactId>spring-security-test</artifactId> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-devtools</artifactId> | ||||
| 			<scope>runtime</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-actuator</artifactId> | ||||
| 		</dependency> | ||||
| 	</dependencies> | ||||
| 
 | ||||
| 	<build> | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| package com.guams.review; | ||||
| 
 | ||||
| import com.guams.review.modele.Post; | ||||
| import com.guams.review.modele.User; | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										34
									
								
								src/main/java/com/guams/review/configuration/Advice.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/main/java/com/guams/review/configuration/Advice.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| package com.guams.review.configuration; | ||||
| 
 | ||||
| import com.guams.review.exception.AlreadyExistsException; | ||||
| import com.guams.review.exception.InvalidNameOrPasswordException; | ||||
| import com.guams.review.exception.NotFoundException; | ||||
| import com.guams.review.exception.ForbiddenExecption; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.web.bind.annotation.ControllerAdvice; | ||||
| import org.springframework.web.bind.annotation.ExceptionHandler; | ||||
| 
 | ||||
| @ControllerAdvice | ||||
| public class Advice { | ||||
| 
 | ||||
|     @ExceptionHandler(value = NotFoundException.class) | ||||
|     public ResponseEntity<Object> handleNotFound(NotFoundException exception) { | ||||
|         return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND); | ||||
|     } | ||||
| 
 | ||||
|     @ExceptionHandler(value = AlreadyExistsException.class) | ||||
|     public ResponseEntity<Object> handleAlreadyExists(AlreadyExistsException exception) { | ||||
|         return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); | ||||
|     } | ||||
| 
 | ||||
|     @ExceptionHandler(value = InvalidNameOrPasswordException.class) | ||||
|     public ResponseEntity<Object> handleInvalidNameOrPassword(InvalidNameOrPasswordException exception) { | ||||
|         return new ResponseEntity<>(exception.getMessage(), HttpStatus.FORBIDDEN); | ||||
|     } | ||||
| 
 | ||||
|     @ExceptionHandler(value = ForbiddenExecption.class) | ||||
|     public ResponseEntity<Object> handleUnauthorizedExecption(ForbiddenExecption exception) { | ||||
|         return new ResponseEntity<>(exception.getMessage(), HttpStatus.FORBIDDEN); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,55 @@ | ||||
| package com.guams.review.configuration; | ||||
| import com.guams.review.service.AuthorService; | ||||
| import io.jsonwebtoken.JwtException; | ||||
| import jakarta.servlet.FilterChain; | ||||
| import jakarta.servlet.ServletException; | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | ||||
| import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.web.filter.OncePerRequestFilter; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| @Component | ||||
| public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||||
| 
 | ||||
|     private final JwtTokenUtil jwtTokenUtil; | ||||
|     private final AuthorService authorService; | ||||
| 
 | ||||
|     public JwtAuthenticationFilter(JwtTokenUtil jwtTokenUtil, AuthorService authorService) { | ||||
|         this.jwtTokenUtil = jwtTokenUtil; | ||||
|         this.authorService = authorService; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) | ||||
|             throws ServletException, IOException { | ||||
|         final String authHeader = request.getHeader("Authorization"); | ||||
| 
 | ||||
|         if (authHeader != null && authHeader.startsWith("Bearer ")) { | ||||
|             String token = authHeader.substring(7); // Retire le préfixe "Bearer " | ||||
|             try { | ||||
|                 String username = jwtTokenUtil.extractUsername(token); // Récupère l'utilisateur du token | ||||
| 
 | ||||
|                 if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { | ||||
|                     UserDetails userDetails = authorService.loadUserByUsername(username); | ||||
| 
 | ||||
|                     if (jwtTokenUtil.validateToken(token, userDetails)) { | ||||
|                         UsernamePasswordAuthenticationToken authentication = | ||||
|                                 new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | ||||
|                         authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||||
|                         SecurityContextHolder.getContext().setAuthentication(authentication); // Met à jour le contexte | ||||
|                     } | ||||
|                 } | ||||
|             } catch (JwtException e) { | ||||
|                 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         filterChain.doFilter(request, response); // Continue le traitement | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,50 @@ | ||||
| package com.guams.review.configuration; | ||||
| 
 | ||||
| import io.jsonwebtoken.Jwts; | ||||
| import io.jsonwebtoken.SignatureAlgorithm; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import java.util.Date; | ||||
| 
 | ||||
| @Component | ||||
| public class JwtTokenUtil { | ||||
| 
 | ||||
|     private final String SECRET_KEY = "9f87d7a0eb7dea860b98adf6bb94feefe4a33698022733bb012d662d92db8081"; | ||||
|     private final long EXPIRATION_TIME = 1000 * 60 * 60 * 10; // 10 heures | ||||
| 
 | ||||
|     public String generateToken(String username) { | ||||
|         return Jwts.builder() | ||||
|                 .setSubject(username) | ||||
|                 .setIssuedAt(new Date()) | ||||
|                 .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) | ||||
|                 .signWith(SignatureAlgorithm.HS256, SECRET_KEY) | ||||
|                 .compact(); | ||||
|     } | ||||
| 
 | ||||
|     public String extractUsername(String token) { | ||||
|         return Jwts.parser() | ||||
|                 .setSigningKey(SECRET_KEY) | ||||
|                 .parseClaimsJws(token) | ||||
|                 .getBody() | ||||
|                 .getSubject(); | ||||
|     } | ||||
| 
 | ||||
|     public boolean validateToken(String token, UserDetails userDetails) { | ||||
|         String username = extractUsername(token); | ||||
|         return username.equals(userDetails.getUsername()) && !isTokenExpired(token); | ||||
|     } | ||||
| 
 | ||||
|     private boolean isTokenExpired(String token) { | ||||
|         return extractExpiration(token).before(new Date()); | ||||
|     } | ||||
| 
 | ||||
|     private Date extractExpiration(String token) { | ||||
|         return Jwts.parser() | ||||
|                 .setSigningKey(SECRET_KEY) | ||||
|                 .parseClaimsJws(token) | ||||
|                 .getBody() | ||||
|                 .getExpiration(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,76 @@ | ||||
| package com.guams.review.configuration; | ||||
| import com.guams.review.service.AuthorService; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.http.HttpMethod; | ||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||
| import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | ||||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||||
| import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||||
| import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||||
| import org.springframework.security.web.SecurityFilterChain; | ||||
| import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||||
| import org.springframework.web.cors.CorsConfiguration; | ||||
| import org.springframework.web.cors.CorsConfigurationSource; | ||||
| import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| 
 | ||||
| @Configuration | ||||
| @EnableWebSecurity | ||||
| @RequiredArgsConstructor | ||||
| public class SpringSecurityConfig { | ||||
| 
 | ||||
|     private final AuthorService authorService; | ||||
| 
 | ||||
|     @Bean | ||||
|     public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtAuthenticationFilter jwtAuthenticationFilter) throws Exception { | ||||
|         return http | ||||
|                 .csrf(AbstractHttpConfigurer::disable) | ||||
|                 .cors(cors -> cors.configurationSource(corsConfigurationSource())) // Ajout de la configuration CORS | ||||
|                 .authorizeHttpRequests(auth -> auth | ||||
|                         .requestMatchers(HttpMethod.GET, | ||||
|                                 "/api/authors", | ||||
|                                 "/api/authors/{id}", | ||||
|                                 "/api/authors/{id}/posts", | ||||
|                                 "/api/posts", | ||||
|                                 "/api/posts/{id}").permitAll() // Autorise les GET sur ces routes | ||||
|                         .requestMatchers("/api/authors/login", "/api/authors/register").permitAll() // Autorise sans authentification | ||||
|                         .requestMatchers("/api/authors/me").authenticated() // Requiert authentification | ||||
|                         .anyRequest().authenticated() // Toutes les autres routes nécessitent une authentification | ||||
|                 ) | ||||
|                 .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) // Ajoute le filtre JWT | ||||
|                 .build(); | ||||
|     } | ||||
| 
 | ||||
|     @Bean | ||||
|     public CorsConfigurationSource corsConfigurationSource() { | ||||
|         CorsConfiguration configuration = new CorsConfiguration(); | ||||
|         configuration.setAllowedOrigins(List.of("http://localhost:4200")); // N'autorise que localhost:4200 | ||||
|         configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); // Spécifie les méthodes autorisées | ||||
|         configuration.setAllowedHeaders(List.of("Authorization", "Content-Type")); // Limite les en-têtes autorisés | ||||
|         configuration.setAllowCredentials(true); // Autorise l'utilisation des cookies ou des tokens | ||||
|         configuration.setMaxAge(3600L); // Cache la configuration CORS pendant 1 heure | ||||
| 
 | ||||
|         UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||||
|         source.registerCorsConfiguration("/**", configuration); // Applique les règles à toutes les routes | ||||
|         return source; | ||||
|     } | ||||
| 
 | ||||
|     @Bean | ||||
|     public PasswordEncoder passwordEncoder() { | ||||
|         return new BCryptPasswordEncoder(); | ||||
|     } | ||||
| 
 | ||||
|     @Bean | ||||
|     public AuthenticationManager authenticationManager(HttpSecurity http, PasswordEncoder passwordEncoder) throws Exception { | ||||
|         AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); | ||||
|         authenticationManagerBuilder.userDetailsService(authorService).passwordEncoder(passwordEncoder); | ||||
|         return authenticationManagerBuilder.build(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										124
									
								
								src/main/java/com/guams/review/controller/AuthorController.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								src/main/java/com/guams/review/controller/AuthorController.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | ||||
| package com.guams.review.controller; | ||||
| 
 | ||||
| import com.guams.review.configuration.JwtTokenUtil; | ||||
| import com.guams.review.exception.AlreadyExistsException; | ||||
| import com.guams.review.exception.InvalidNameOrPasswordException; | ||||
| import com.guams.review.exception.NotFoundException; | ||||
| import com.guams.review.exception.ForbiddenExecption; | ||||
| 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<ReturnableAuthor> 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 void updateUser(@PathVariable UUID id, @RequestBody Author updatedAuthor, Authentication authentication) { | ||||
|         Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); | ||||
|         authorService.insert(updatedAuthor.setId(authorToUpdate.getId())); | ||||
|     } | ||||
| 
 | ||||
|     @PutMapping(value = "{id}/avatar", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) | ||||
|     public void updateUserAvatar(@PathVariable UUID id, @RequestPart MultipartFile avatar, Authentication authentication) throws IOException { | ||||
|         Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); | ||||
|         authorService.insert(authorToUpdate.setProfilePicture(avatar.getBytes())); | ||||
|     } | ||||
| 
 | ||||
|     @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 List<Long> postIds, Authentication authentication) { | ||||
|         Author author = authorService.verifyIfUserIsAuthorized(authentication, authorId); | ||||
|         authorService.insertPublications(author.getId(), postIds); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping("/{id}/posts") | ||||
|     public List<Post> 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 { | ||||
|             authenticationManager.authenticate( | ||||
|                     new UsernamePasswordAuthenticationToken(author.getName(), author.getPassword()) | ||||
|             ); | ||||
| 
 | ||||
|             String token = jwtTokenUtil.generateToken(author.getName()); | ||||
|             return new AuthorToken().setToken(token); | ||||
|         } catch (Exception e) { | ||||
|             throw new InvalidNameOrPasswordException(e.getMessage()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @PostMapping("/register") | ||||
|     public ResponseEntity<Author> authorRegister(@RequestBody Author author) { | ||||
|         Assert.isNull(author.getId(), "Author id must be null"); | ||||
|         if (authorRepository.findByName(author.getName()) != null) { | ||||
|             throw new AlreadyExistsException("Author already exists"); | ||||
|         } | ||||
|         author.setPassword(passwordEncoder.encode(author.getPassword())); | ||||
|         return new ResponseEntity<>(authorRepository.save(author.setRole("USER")).setPassword(""), HttpStatus.CREATED); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping(value = "/me", produces = "application/json") | ||||
|     public Author getAuthenticatedUser(Authentication authentication) { | ||||
|         if (authentication == null || !authentication.isAuthenticated()) { | ||||
|             throw new ForbiddenExecption("You are not authorized to access this resource"); | ||||
|         } | ||||
| 
 | ||||
|         String username = authentication.getName(); | ||||
|         Author author = authorRepository.findByName(username); | ||||
| 
 | ||||
|         if (author == null) { | ||||
|             throw new NotFoundException("Author not found"); | ||||
|         } | ||||
| 
 | ||||
|         return author.setPassword(""); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,98 @@ | ||||
| package com.guams.review.controller; | ||||
| 
 | ||||
| import com.guams.review.exception.NotFoundException; | ||||
| import com.guams.review.exception.ForbiddenExecption; | ||||
| import com.guams.review.model.AuthorRepository; | ||||
| import com.guams.review.model.dao.Author; | ||||
| import com.guams.review.model.dao.Post; | ||||
| import com.guams.review.service.AuthorService; | ||||
| import com.guams.review.service.PostService; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.util.Assert; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.time.LocalDate; | ||||
| import java.util.List; | ||||
| 
 | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/api/posts") | ||||
| public class PostController { | ||||
| 
 | ||||
|     private final PostService postService; | ||||
|     private final AuthorService authorService; | ||||
|     private final AuthorRepository authorRepository; | ||||
| 
 | ||||
|     @GetMapping | ||||
|     public List<Post> listPosts() { | ||||
|         return postService.list(); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping("/{id}") | ||||
|     public Post findPost(@PathVariable Long id) { | ||||
|         return postService.findById(id).orElseThrow(() -> new NotFoundException("Post not found")); | ||||
|     } | ||||
| 
 | ||||
|     @PutMapping("/{id}") | ||||
|     public void updatePost(@PathVariable Long id, @RequestBody Post updatedPost, Authentication authentication) { | ||||
|         if (authentication == null) { | ||||
|             throw new ForbiddenExecption("You have to login to do that"); | ||||
|         } | ||||
|         Author authenticatedAuthor = authorRepository.findByName(authentication.getName()); | ||||
|         //Si l'user authent possède ce post | ||||
|         if (authorService.listPublicationOfAuthor(authenticatedAuthor.getId()).stream().map(Post::getId).toList().contains(id)) { | ||||
|             Post postToUpdate = postService.findById(id).orElseThrow(() -> new NotFoundException("Post not found")); | ||||
|             postService.insert(updatedPost | ||||
|                     .setId(postToUpdate.getId()) | ||||
|                     .setIllustration(postToUpdate.getIllustration()) | ||||
|                     .setPublicationDate(postToUpdate.getPublicationDate())); | ||||
|         } else { | ||||
|             throw new ForbiddenExecption("You do not have permission to update this post"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @PutMapping(value = "{id}/illustration", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) | ||||
|     public void updateIllustration(@PathVariable Long id, @RequestPart MultipartFile illustration, Authentication authentication) throws IOException { | ||||
|         if (authentication == null) { | ||||
|             throw new ForbiddenExecption("You have to login to do that"); | ||||
|         } | ||||
|         Author authenticatedAuthor = authorRepository.findByName(authentication.getName()); | ||||
|         if (authorService.listPublicationOfAuthor(authenticatedAuthor.getId()).stream().map(Post::getId).toList().contains(id)) { | ||||
|             Post postToUpdate = postService.findById(id).orElseThrow(() -> new NotFoundException("Post not found")); | ||||
|             postService.insert(postToUpdate.setIllustration(illustration.getBytes())); | ||||
|         } else { | ||||
|             throw new ForbiddenExecption("You do not have permission to update this post"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @PostMapping | ||||
|     public ResponseEntity<Post> addPost(@RequestBody Post postToCreate, Authentication authentication) { | ||||
|         Assert.isNull(postToCreate.getId(), "Post id must be null"); | ||||
|         if (authentication == null) { | ||||
|             throw new ForbiddenExecption("You have to login to do that"); | ||||
|         } | ||||
|         return new ResponseEntity<>(postService.insert(postToCreate.setPublicationDate(LocalDate.now())), HttpStatus.CREATED); | ||||
|     } | ||||
| 
 | ||||
|     @DeleteMapping("{id}") | ||||
|     public void deletePost(@PathVariable Long id, Authentication authentication) { | ||||
|         if (authentication == null) { | ||||
|             throw new ForbiddenExecption("You have to login to do that"); | ||||
|         } | ||||
|         Author authenticatedAuthor = authorRepository.findByName(authentication.getName()); | ||||
|         if (authorService.listPublicationOfAuthor(authenticatedAuthor.getId()).stream().map(Post::getId).toList().contains(id)) { | ||||
|             Post postToDelete = postService.findById(id).orElseThrow(() -> new NotFoundException("Post not found")); | ||||
|             postService.delete(postToDelete.getId()); | ||||
|         } else { | ||||
|             throw new ForbiddenExecption("You do not have permission to delete this post"); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,44 +0,0 @@ | ||||
| package com.guams.review.controller; | ||||
| 
 | ||||
| import com.guams.review.modele.User; | ||||
| import com.guams.review.service.UserService; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.http.HttpEntity; | ||||
| import org.springframework.http.HttpHeaders; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping(path = "api/users") | ||||
| public class UserController | ||||
| { | ||||
|     private final UserService userService; | ||||
| 
 | ||||
|     @Autowired | ||||
|     public UserController(UserService userService) { | ||||
|         this.userService = userService; | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping | ||||
|     public ResponseEntity<List<User>> getUsers() | ||||
|     { | ||||
|         List<User> users = userService.getUsers(); | ||||
|         return new ResponseEntity<>(users, new HttpHeaders(),HttpStatus.OK); | ||||
|     }; | ||||
| 
 | ||||
|     @PostMapping | ||||
|     public ResponseEntity<String> saveUser(@RequestParam User user) | ||||
|     { | ||||
|         userService.saveUser(user); | ||||
|         Optional<User> exists = userService.findById(user.getId()); | ||||
|         if (exists.isPresent()) | ||||
|         { | ||||
|             return new ResponseEntity<>("Created", new HttpHeaders(), HttpStatus.CREATED); | ||||
|         } | ||||
|         return new ResponseEntity<>("Error", new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package com.guams.review.exception; | ||||
| 
 | ||||
| public class AlreadyExistsException extends RuntimeException { | ||||
|     public AlreadyExistsException(String message) { | ||||
|         super(message); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package com.guams.review.exception; | ||||
| 
 | ||||
| public class ForbiddenExecption extends RuntimeException { | ||||
|     public ForbiddenExecption(String message) { | ||||
|         super(message); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package com.guams.review.exception; | ||||
| 
 | ||||
| public class InvalidNameOrPasswordException extends RuntimeException { | ||||
|     public InvalidNameOrPasswordException(String message) { | ||||
|         super(message); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package com.guams.review.exception; | ||||
| 
 | ||||
| public class NotFoundException extends RuntimeException { | ||||
|   public NotFoundException(String message) { | ||||
|     super(message); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										26
									
								
								src/main/java/com/guams/review/model/AuthorRepository.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/main/java/com/guams/review/model/AuthorRepository.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| package com.guams.review.model; | ||||
| 
 | ||||
| import com.guams.review.model.dao.Author; | ||||
| import org.springframework.data.jdbc.repository.query.Modifying; | ||||
| import org.springframework.data.jdbc.repository.query.Query; | ||||
| import org.springframework.data.repository.CrudRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| @Repository | ||||
| public interface AuthorRepository extends CrudRepository<Author, UUID> { | ||||
| 
 | ||||
|     @Modifying | ||||
|     @Query("insert into publication (author_fk, post_fk) values (:authorId, :postId)") | ||||
|     void insertPublication(UUID authorId, Long postId); | ||||
| 
 | ||||
|     @Modifying | ||||
|     @Query("delete from publication where author_fk=:authorId and post_fk=:postId") | ||||
|     void deletePublication(UUID authorId, Long postId); | ||||
| 
 | ||||
|     List<Author> findAll(); | ||||
| 
 | ||||
|     Author findByName(String name); | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/main/java/com/guams/review/model/PostRepository.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/main/java/com/guams/review/model/PostRepository.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| package com.guams.review.model; | ||||
| 
 | ||||
| import com.guams.review.model.dao.Post; | ||||
| import org.springframework.data.jdbc.repository.query.Query; | ||||
| import org.springframework.data.repository.CrudRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| @Repository | ||||
| public interface PostRepository extends CrudRepository<Post, Long> { | ||||
| 
 | ||||
|     @Query("select id, description, illustration, title, body, category, publication_date " + | ||||
|             "from post join publication on post.id=publication.post_fk where publication.author_fk=:authorId") | ||||
|     List<Post> findPostsOfAuthor(UUID authorId); | ||||
| 
 | ||||
|     List<Post> findAll(); | ||||
| } | ||||
							
								
								
									
										39
									
								
								src/main/java/com/guams/review/model/dao/Author.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/main/java/com/guams/review/model/dao/Author.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| package com.guams.review.model.dao; | ||||
| 
 | ||||
| 
 | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
| import org.springframework.data.annotation.Id; | ||||
| import org.springframework.data.relational.core.mapping.Column; | ||||
| import org.springframework.data.relational.core.mapping.Table; | ||||
| import org.springframework.security.core.GrantedAuthority; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | ||||
| 
 | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| 
 | ||||
| @Getter | ||||
| @Setter | ||||
| @Accessors(chain = true) | ||||
| @Table(name = "author") | ||||
| public class Author { | ||||
| 
 | ||||
|     @Id | ||||
|     UUID id; | ||||
| 
 | ||||
|     @Column("name") | ||||
|     String name; | ||||
| 
 | ||||
|     @Column("password") | ||||
|     String password; | ||||
| 
 | ||||
|     @Column("profile_picture") | ||||
|     byte[] profilePicture; | ||||
| 
 | ||||
|     @Column("role") | ||||
|     String role; | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/main/java/com/guams/review/model/dao/AuthorToken.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/main/java/com/guams/review/model/dao/AuthorToken.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| package com.guams.review.model.dao; | ||||
| 
 | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
| 
 | ||||
| @Getter | ||||
| @Setter | ||||
| @Accessors(chain = true) | ||||
| public class AuthorToken { | ||||
|     String token; | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/main/java/com/guams/review/model/dao/Post.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/main/java/com/guams/review/model/dao/Post.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| package com.guams.review.model.dao; | ||||
| 
 | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
| import org.springframework.data.annotation.Id; | ||||
| import org.springframework.data.relational.core.mapping.Column; | ||||
| import org.springframework.data.relational.core.mapping.Table; | ||||
| 
 | ||||
| import java.time.LocalDate; | ||||
| 
 | ||||
| @Getter | ||||
| @Setter | ||||
| @Accessors(chain = true) | ||||
| @Table(name = "post") | ||||
| public class Post { | ||||
|     @Id | ||||
|     Long id; | ||||
|     @Column("description") | ||||
|     String description; | ||||
|     @Column("illustration") | ||||
|     byte[] illustration; | ||||
|     @Column("title") | ||||
|     String title; | ||||
|     @Column("body") | ||||
|     String body; | ||||
|     @Column("category") | ||||
|     String category; | ||||
|     @Column("publication_date") | ||||
|     LocalDate publicationDate; | ||||
| 
 | ||||
| } | ||||
| @ -1,54 +0,0 @@ | ||||
| package com.guams.review.modele; | ||||
| 
 | ||||
| import jakarta.persistence.*; | ||||
| import lombok.Builder; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| 
 | ||||
| @Entity | ||||
| @Getter | ||||
| @Table(name = "POST") | ||||
| public class Post | ||||
| { | ||||
|     @Id | ||||
|     @GeneratedValue | ||||
|     private Long id; | ||||
|     @Column(name = "TITLE", nullable = false) | ||||
|     private String title; | ||||
|     @Column(name = "BODY", nullable = false) | ||||
|     private String body; | ||||
|     @Column(name = "IMAGE") | ||||
|     private String image; | ||||
|     @ManyToOne | ||||
|     @JoinColumn(name = "USER_ID", nullable = false) | ||||
|     private User user; | ||||
| 
 | ||||
|     public Post() | ||||
|     {} | ||||
| 
 | ||||
| 
 | ||||
|     public Post setId(Long id) { | ||||
|         this.id = id; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public Post setTitle(String title) { | ||||
|         this.title = title; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public Post setBody(String body) { | ||||
|         this.body = body; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public Post setImage(String image) { | ||||
|         this.image = image; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public Post setUser(User user) { | ||||
|         this.user = user; | ||||
|         return this; | ||||
|     } | ||||
| } | ||||
| @ -1,51 +0,0 @@ | ||||
| package com.guams.review.modele; | ||||
| 
 | ||||
| 
 | ||||
| import jakarta.persistence.*; | ||||
| import lombok.Builder; | ||||
| import lombok.Getter; | ||||
| import lombok.NoArgsConstructor; | ||||
| import lombok.Setter; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| 
 | ||||
| @Entity | ||||
| @Getter | ||||
| @Table(name = "USERS") | ||||
| public class User { | ||||
| 
 | ||||
|     @Id | ||||
|     @GeneratedValue | ||||
|     private Long id; | ||||
| 
 | ||||
|     @Column(name = "LOGIN", nullable = false, unique = true) | ||||
|     private String login; | ||||
| 
 | ||||
|     @Column(name = "PASSWORD", nullable = false) | ||||
|     private String password; | ||||
| 
 | ||||
|     @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) | ||||
|     private List<Post> posts; | ||||
| 
 | ||||
| 
 | ||||
|     public User setId(Long id) { | ||||
|         this.id = id; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public User setLogin(String login) { | ||||
|         this.login = login; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public User setPassword(String password) { | ||||
|         this.password = password; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public User setPosts(List<Post> posts) { | ||||
|         this.posts = posts; | ||||
|         return this; | ||||
|     } | ||||
| } | ||||
| @ -1,12 +0,0 @@ | ||||
| package com.guams.review.repository; | ||||
| 
 | ||||
| import com.guams.review.modele.User; | ||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| @Repository | ||||
| public interface UserRepository extends JpaRepository<User, Long> | ||||
| { | ||||
| } | ||||
							
								
								
									
										84
									
								
								src/main/java/com/guams/review/service/AuthorService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/main/java/com/guams/review/service/AuthorService.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | ||||
| package com.guams.review.service; | ||||
| 
 | ||||
| import com.guams.review.exception.NotFoundException; | ||||
| import com.guams.review.exception.ForbiddenExecption; | ||||
| import com.guams.review.model.AuthorRepository; | ||||
| import com.guams.review.model.PostRepository; | ||||
| import com.guams.review.model.dao.Author; | ||||
| import com.guams.review.model.dao.Post; | ||||
| import com.guams.review.service.mapper.Mapper; | ||||
| import com.guams.review.service.mapper.ReturnableAuthor; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||||
| import org.springframework.security.core.userdetails.User; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | ||||
| import org.springframework.security.core.userdetails.UserDetailsService; | ||||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| 
 | ||||
| import java.util.*; | ||||
| 
 | ||||
| @Service | ||||
| @RequiredArgsConstructor | ||||
| public class AuthorService implements UserDetailsService | ||||
| { | ||||
|     private final Mapper mapper; | ||||
|     private final AuthorRepository authorRepository; | ||||
|     private final PostRepository postRepository; | ||||
| 
 | ||||
|     public List<ReturnableAuthor> list() { | ||||
|         return authorRepository.findAll().stream() | ||||
|                 .map(mapper::mapAuthor) | ||||
|                 .toList(); | ||||
|     } | ||||
| 
 | ||||
|     public List<Post> listPublicationOfAuthor(UUID authorId) { | ||||
|         return postRepository.findPostsOfAuthor(authorId); | ||||
|     } | ||||
| 
 | ||||
|     public Optional<Author> findById(UUID id) { | ||||
|         return authorRepository.findById(id); | ||||
|     } | ||||
| 
 | ||||
|     public ReturnableAuthor insert(Author author) { | ||||
|         return mapper.mapAuthor(authorRepository.save(author)); | ||||
|     } | ||||
| 
 | ||||
|     @Transactional | ||||
|     public void insertPublications(UUID authorId, List<Long> postIds) { | ||||
|         for (Long postId : postIds) { | ||||
|             authorRepository.deletePublication(authorId, postId); | ||||
|             if (postRepository.findById(postId).isPresent()) { | ||||
|                 authorRepository.insertPublication(authorId, postId); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public Author verifyIfUserIsAuthorized(Authentication authentication, UUID id) { | ||||
|         if (authentication == null || !authentication.isAuthenticated()) { | ||||
|             throw new ForbiddenExecption("You have to login first"); | ||||
|         } | ||||
|         Author author = findById(id).orElseThrow(() -> new NotFoundException("Author not found")); | ||||
|         String username = authentication.getName(); | ||||
|         Author authorAuthenticated = authorRepository.findByName(username); | ||||
|         if (authorAuthenticated.getId().compareTo(author.getId()) != 0 && !authorAuthenticated.getRole().equals("ADMIN")) { | ||||
|             throw new ForbiddenExecption("Specified Author is not authorized to do that"); | ||||
|         } | ||||
|         return author; | ||||
|     } | ||||
| 
 | ||||
|     public void delete(Author author) { | ||||
|         authorRepository.delete(author); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||||
|         Author author = authorRepository.findByName(username); | ||||
|         if (author == null) { | ||||
|             throw new UsernameNotFoundException(username); | ||||
|         } | ||||
|         return new User(author.getName(), author.getPassword(), Collections.singletonList(new SimpleGrantedAuthority(author.getRole()))); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/main/java/com/guams/review/service/PostService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/main/java/com/guams/review/service/PostService.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| package com.guams.review.service; | ||||
| 
 | ||||
| 
 | ||||
| import com.guams.review.model.dao.Post; | ||||
| import com.guams.review.model.PostRepository; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.stereotype.Service; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| @Service | ||||
| @RequiredArgsConstructor | ||||
| public class PostService | ||||
| { | ||||
|     private final PostRepository postRepository; | ||||
| 
 | ||||
|     public List<Post> list() { | ||||
|         return postRepository.findAll(); | ||||
|     } | ||||
| 
 | ||||
|     public Optional<Post> findById(Long id) { | ||||
|         return postRepository.findById(id); | ||||
|     } | ||||
| 
 | ||||
|     public Post insert(Post post) { | ||||
|         return postRepository.save(post); | ||||
|     } | ||||
| 
 | ||||
|     public void delete(Long id) { | ||||
|         postRepository.deleteById(id); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,36 +0,0 @@ | ||||
| package com.guams.review.service; | ||||
| 
 | ||||
| import com.guams.review.modele.Post; | ||||
| import com.guams.review.modele.User; | ||||
| import com.guams.review.repository.UserRepository; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| @Service | ||||
| public class UserService | ||||
| { | ||||
|     private final UserRepository userRepository; | ||||
| 
 | ||||
|     @Autowired | ||||
|     public UserService(UserRepository userRepository) { | ||||
|         this.userRepository = userRepository; | ||||
|     } | ||||
| 
 | ||||
|     public List<User> getUsers() | ||||
|     { | ||||
|         return userRepository.findAll(); | ||||
|     } | ||||
| 
 | ||||
|     public void saveUser(User user) | ||||
|     { | ||||
|         userRepository.save(user); | ||||
|     } | ||||
| 
 | ||||
|     public Optional<User> findById(Long id) | ||||
|     { | ||||
|         return userRepository.findById(id); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/main/java/com/guams/review/service/mapper/Mapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/java/com/guams/review/service/mapper/Mapper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| package com.guams.review.service.mapper; | ||||
| 
 | ||||
| import com.guams.review.model.dao.Author; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| @Component | ||||
| public class Mapper { | ||||
| 
 | ||||
|     public Mapper() {} | ||||
| 
 | ||||
|     public ReturnableAuthor mapAuthor(Author author) { | ||||
|         return new ReturnableAuthor() | ||||
|                 .setId(author.getId()) | ||||
|                 .setName(author.getName()) | ||||
|                 .setRole(author.getRole()) | ||||
|                 .setProfilePicture(author.getProfilePicture()); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| package com.guams.review.service.mapper; | ||||
| 
 | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| @Getter | ||||
| @Setter | ||||
| @Accessors(chain = true) | ||||
| public class ReturnableAuthor { | ||||
|     private UUID id; | ||||
|     private String name; | ||||
|     private byte[] profilePicture; | ||||
|     private String role; | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| spring.security.oauth2.client.registration.github.client-id=Ov23ligoCzKHHyyIzIbS | ||||
| spring.security.oauth2.client.registration.github.client-secret=c660f476763404f41da43e7a3f7e9648f94b107d | ||||
| spring.application.name=reView | ||||
| spring.datasource.url=jdbc:postgresql://localhost:5432/review | ||||
| spring.datasource.url=jdbc:postgresql://localhost:5432/reviewDB | ||||
| spring.datasource.username=postgres | ||||
| spring.datasource.password=Azerty1234 | ||||
| spring.jpa.hibernate.ddl-auto=create-drop | ||||
| spring.jpa.show-sql=true | ||||
							
								
								
									
										31
									
								
								src/main/resources/script.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/resources/script.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| drop table if exists publication; | ||||
| drop table if exists post; | ||||
| drop table if exists author; | ||||
| 
 | ||||
| create table author | ||||
| ( | ||||
|     id              uuid        default gen_random_uuid() primary key, | ||||
|     name            varchar(255) unique        not null, | ||||
|     password        text                       not null, | ||||
|     profile_picture bytea, | ||||
|     role            varchar(50) default 'USER' not null | ||||
| ); | ||||
| 
 | ||||
| create table post | ||||
| ( | ||||
|     id               serial primary key, | ||||
|     description      varchar(512) not null, | ||||
|     illustration     bytea, | ||||
|     title            varchar(50)  not null, | ||||
|     body             text         not null, | ||||
|     category         varchar(50)  not null, | ||||
|     publication_date date         not null | ||||
| ); | ||||
| 
 | ||||
| create table publication | ||||
| ( | ||||
|     author_fk uuid, | ||||
|     post_fk   serial, | ||||
|     foreign key (author_fk) references author (id), | ||||
|     foreign key (post_fk) references post (id) | ||||
| ); | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user