backend/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java

87 lines
3.6 KiB
Java

package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.JWTTokenUtils;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.JWTResponse;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.UnauthorizedException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.UserNotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.JWTUserDetailsService;
import java.security.Principal;
import javax.validation.Valid;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/auth")
public class AuthenticationController {
private final AuthenticationManager authenticationManager;
private final UserRepository userRepository;
private final JWTTokenUtils jwtTokenUtils;
private final JWTUserDetailsService userDetailsService;
public AuthenticationController(
AuthenticationManager authenticationManager,
UserRepository userRepository,
JWTTokenUtils jwtTokenUtils,
JWTUserDetailsService userDetailsService) {
this.authenticationManager = authenticationManager;
this.userRepository = userRepository;
this.jwtTokenUtils = jwtTokenUtils;
this.userDetailsService = userDetailsService;
}
@PostMapping("/login")
public JWTResponse login(@Valid @RequestBody JWTRequest authenticationRequest)
throws UnauthorizedException, UserNotFoundException {
final UserDetails userDetails;
if (authenticationRequest.getUsernameOrEmail().contains("@")) {
// usernameOrEmail contains an email, so fetch the corresponding username
final User user =
userRepository.findByEmailIgnoreCase(
authenticationRequest.getUsernameOrEmail());
if (user == null) {
throw new UserNotFoundException();
}
authenticate(user.getUsername(), authenticationRequest.getPassword());
userDetails = userDetailsService.loadUserByUsername(user.getUsername());
} else {
// usernameOrEmail contains a username, authenticate with that then
authenticate(
authenticationRequest.getUsernameOrEmail(),
authenticationRequest.getPassword());
userDetails =
userDetailsService.loadUserByUsername(
authenticationRequest.getUsernameOrEmail());
}
final String token = jwtTokenUtils.generateToken(userDetails);
return new JWTResponse(token);
}
@GetMapping("/profile")
public User profile(final Principal principal) {
return userRepository.findByUsername(principal.getName());
}
private void authenticate(String username, String password) throws UnauthorizedException {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new UnauthorizedException(true, e);
} catch (BadCredentialsException e) {
throw new UnauthorizedException(false, e);
}
}
}