authentification partiellement finie

This commit is contained in:
Guams 2024-12-17 21:58:04 +01:00
parent acd85c93e0
commit b39307f7d9
10 changed files with 148 additions and 10 deletions

22
pom.xml
View File

@ -58,6 +58,28 @@
<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>

View File

@ -1,5 +1,7 @@
package com.guams.review.configuration;
import com.guams.review.exception.AlreadyExistsException;
import com.guams.review.exception.InvalidNameOrPasswordException;
import com.guams.review.exception.NotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -13,4 +15,14 @@ public class Advice {
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.UNAUTHORIZED);
}
}

View File

@ -0,0 +1,45 @@
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.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;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SpringSecurityConfig {
private final AuthorService authorService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth ->
auth.requestMatchers("/api/authors/login", "/api/authors/register").permitAll()
.anyRequest().authenticated()).build();
}
@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();
}
}

View File

@ -1,13 +1,21 @@
package com.guams.review.controller;
import com.guams.review.exception.AlreadyExistsException;
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.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.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@ -21,7 +29,11 @@ import java.util.UUID;
@RequiredArgsConstructor
public class AuthorController {
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
private final AuthorService authorService;
private final AuthorRepository authorRepository;
private final Mapper mapper;
@GetMapping
@ -35,12 +47,6 @@ public class AuthorController {
return mapper.mapAuthor(author);
}
@PostMapping
public ReturnableAuthor addUser(@RequestBody Author author) {
Assert.isNull(author.getId(), "Author id must be null");
return authorService.insert(author);
}
@PutMapping("/{id}")
public void updateUser(@PathVariable UUID id, @RequestBody Author updatedAuthor) {
Author authorToUpdate = authorService.findById(id).orElseThrow(() -> new NotFoundException("Author not found"));
@ -70,4 +76,24 @@ public class AuthorController {
Author author = authorService.findById(id).orElseThrow(() -> new NotFoundException("Author not found"));
return authorService.listPublicationOfAuthor(author.getId());
}
@PostMapping("/login")
public void authorLogin(@RequestBody Author author) {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(author.getName(), author.getPassword()));
}
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).setPassword(""), HttpStatus.CREATED);
}
}

View File

@ -0,0 +1,7 @@
package com.guams.review.exception;
public class AlreadyExistsException extends RuntimeException {
public AlreadyExistsException(String message) {
super(message);
}
}

View File

@ -0,0 +1,7 @@
package com.guams.review.exception;
public class InvalidNameOrPasswordException extends RuntimeException {
public InvalidNameOrPasswordException(String message) {
super(message);
}
}

View File

@ -21,4 +21,6 @@ public interface AuthorRepository extends CrudRepository<Author, UUID> {
void deletePublication(UUID authorId, Long postId);
List<Author> findAll();
Author findByName(String name);
}

View File

@ -26,6 +26,9 @@ public class Author {
@Column("password")
String password;
// @Column("role")
// String role;
@Column("profile_picture")
byte[] profilePicture;
}

View File

@ -7,16 +7,19 @@ 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.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.List;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
@Service
@RequiredArgsConstructor
public class AuthorService
public class AuthorService implements UserDetailsService
{
private final Mapper mapper;
private final AuthorRepository authorRepository;
@ -53,4 +56,13 @@ public class AuthorService
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("USER"))); // temporaire pour le role
}
}

View File

@ -1,3 +1,5 @@
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/reviewDB
spring.datasource.username=postgres