perf(security): cambio subject token de email a id de usuario

parent 60898b64
package com.example.apprecetas.recipe.application.impl;
import com.example.apprecetas.exception.EntityNotFoundException;
import com.example.apprecetas.recipe.application.CreateRecipeUseCase;
import com.example.apprecetas.recipe.domain.entity.Recipe;
import com.example.apprecetas.recipe.domain.repository.CreateRecipeRepository;
import com.example.apprecetas.recipe.infrastructure.mapper.RecipeMapper;
import com.example.apprecetas.recipe.infrastructure.repository.mongodb.RecipeDocument;
import com.example.apprecetas.user.domain.repository.ReadUserRepository;
import com.example.apprecetas.user.infrastructure.repository.mongodb.UserDocument;
import lombok.RequiredArgsConstructor;
import org.mapstruct.factory.Mappers;
import org.springframework.security.core.context.SecurityContextHolder;
......@@ -27,15 +25,11 @@ public class CreateRecipeUseCaseImpl implements CreateRecipeUseCase {
public Recipe create(Recipe recipe) {
RecipeDocument recipeDocument = mapper.mapDocument(recipe);
// Get email from token
String email = SecurityContextHolder.getContext().getAuthentication().getName();
// Search user
UserDocument user = readUserRepository.readByEmail(email)
.orElseThrow(() -> new EntityNotFoundException("Usuario con email " + email + " no encontrado"));
// Get idUser from token
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
// Put userId to recipe
recipeDocument.setUserId(user.getId());
recipeDocument.setUserId(userId);
RecipeDocument savedRecipe = createRecipeRepository.create(recipeDocument);
return mapper.mapDocument(savedRecipe);
......
......@@ -4,7 +4,6 @@ import com.example.apprecetas.recipe.application.ReadRecipeUseCase;
import com.example.apprecetas.recipe.infrastructure.controller.dto.output.RecipeOutputDto;
import com.example.apprecetas.recipe.infrastructure.mapper.RecipeMapper;
import com.example.apprecetas.user.application.ReadUserUseCase;
import com.example.apprecetas.user.domain.entity.User;
import lombok.RequiredArgsConstructor;
import org.mapstruct.factory.Mappers;
import org.springframework.data.domain.Page;
......@@ -34,14 +33,13 @@ public class ReadRecipeController {
public ResponseEntity<Page<RecipeOutputDto>> readAll(@RequestParam(required = false, defaultValue = "0") int page,
@RequestParam(required = false, defaultValue = "6") int size) {
Pageable pageable = PageRequest.of(page, size);
String email = SecurityContextHolder.getContext().getAuthentication().getName();
User user = readUserUseCase.readByEmail(email);
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
if (service.readAllByUser(user.getId(), pageable).isEmpty()) {
if (service.readAllByUser(userId, pageable).isEmpty()) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.ok().body(service.readAllByUser(user.getId(), pageable).map(mapper::map));
return ResponseEntity.ok().body(service.readAllByUser(userId, pageable).map(mapper::map));
}
}
......@@ -23,10 +23,10 @@ public class JwtTokenProvider {
private final SecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
public String generateToken(String email) {
public String generateToken(String id) {
long jwtExpirationMs = 3600000; // 1 hora en milisegundos
return Jwts.builder()
.subject(email)
.subject(id)
.issuedAt(new Date())
.expiration(Date.from(Instant.now().plus(jwtExpirationMs, ChronoUnit.MILLIS)))
.signWith(secretKey)
......@@ -42,7 +42,7 @@ public class JwtTokenProvider {
}
}
public String getUsernameFromToken(String token) {
public String getUserIdFromToken(String token) {
return Jwts.parser()
.verifyWith(secretKey)
.build()
......@@ -52,8 +52,8 @@ public class JwtTokenProvider {
}
public Authentication getAuthentication(String token) {
String email = getUsernameFromToken(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
String userId = getUserIdFromToken(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(userId);
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
......
......@@ -15,12 +15,12 @@ public class CustomUserDetailsServiceImpl implements UserDetailsService {
private final ReadUserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return userRepository.readByEmail(email)
.map(user -> User.withUsername(user.getEmail())
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
return userRepository.readById(id)
.map(user -> User.withUsername(user.getId())
.password(user.getPassword())
.roles(user.getRole().name())
.build())
.orElseThrow(() -> new UsernameNotFoundException("Usuario con email " + email + " no encontrado"));
.orElseThrow(() -> new UsernameNotFoundException("Usuario con id " + id + " no encontrado"));
}
}
......@@ -5,6 +5,7 @@ import com.example.apprecetas.exception.UnprocessableEntityException;
import com.example.apprecetas.security.jwt.JwtTokenProvider;
import com.example.apprecetas.user.application.CreateUserUseCase;
import com.example.apprecetas.user.application.ReadUserUseCase;
import com.example.apprecetas.user.domain.entity.User;
import com.example.apprecetas.user.infrastructure.controller.dto.AuthResponse;
import com.example.apprecetas.user.infrastructure.controller.dto.LoginRequest;
import com.example.apprecetas.user.infrastructure.controller.dto.UserInputDto;
......@@ -18,6 +19,7 @@ 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.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
......@@ -33,6 +35,7 @@ import java.util.stream.Collectors;
public class AuthController {
private final AuthenticationManager authenticationManager;
private final PasswordEncoder passwordEncoder;
private final JwtTokenProvider jwtTokenProvider;
private final ReadUserUseCase readUserService;
private final CreateUserUseCase createUserService;
......@@ -48,22 +51,18 @@ public class AuthController {
.collect(Collectors.joining("; "));
throw new UnprocessableEntityException(errorMsg);
}
try {
readUserService.readByEmail(loginRequest.getEmail());
User user = readUserService.readByEmail(loginRequest.getEmail());
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getEmail(),
loginRequest.getPassword()
)
);
if(!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword()))
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Contraseña incorrecta");
String token = jwtTokenProvider.generateToken(authentication.getName());
String token = jwtTokenProvider.generateToken(user.getId());
return ResponseEntity.ok(new AuthResponse(token));
} catch (EntityNotFoundException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Usuario no encontrado");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Contraseña incorrecta");
}
}
......@@ -76,15 +75,17 @@ public class AuthController {
.collect(Collectors.joining("; "));
throw new UnprocessableEntityException(errorMsg);
}
try {
URI location = URI.create("/user");
UserOutputDto userOutputDto = mapper.map(createUserService.create(mapper.map(userInputDto)));
User createdUser = createUserService.create(mapper.map(userInputDto));
String token = jwtTokenProvider.generateToken(userOutputDto.getEmail());
String token = jwtTokenProvider.generateToken(createdUser.getId());
return ResponseEntity.created(location).body(new AuthResponse(token));
} catch (Exception e) {
throw new UnprocessableEntityException("Usuario ya registrado. Cambie sus credenciales.");
throw new UnprocessableEntityException("Usuario ya registrado. Cambie el email.");
}
}
......
package com.example.apprecetas.user.infrastructure.controller;
import com.example.apprecetas.user.application.ReadUserUseCase;
import com.example.apprecetas.user.domain.entity.User;
import com.example.apprecetas.user.infrastructure.controller.dto.UserOutputDto;
import com.example.apprecetas.user.infrastructure.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
......@@ -25,9 +24,8 @@ public class ReadUserController {
@GetMapping("/me")
public ResponseEntity<UserOutputDto> readMe() {
String email = SecurityContextHolder.getContext().getAuthentication().getName();
User user = service.readByEmail(email);
return ResponseEntity.ok().body(mapper.map(service.readById(user.getId())));
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
return ResponseEntity.ok().body(mapper.map(service.readById(userId)));
}
@GetMapping
......
......@@ -3,7 +3,6 @@ package com.example.apprecetas.user.infrastructure.controller;
import com.example.apprecetas.exception.UnprocessableEntityException;
import com.example.apprecetas.user.application.ReadUserUseCase;
import com.example.apprecetas.user.application.UpdateUserUseCase;
import com.example.apprecetas.user.domain.entity.User;
import com.example.apprecetas.user.infrastructure.controller.dto.UserInputDto;
import com.example.apprecetas.user.infrastructure.controller.dto.UserOutputDto;
import com.example.apprecetas.user.infrastructure.mapper.UserMapper;
......@@ -39,9 +38,8 @@ public class UpdateUserController {
.collect(Collectors.joining("; "));
throw new UnprocessableEntityException(errorMsg);
}
String email = SecurityContextHolder.getContext().getAuthentication().getName();
User user = readUserUseCase.readByEmail(email);
return ResponseEntity.ok().body(mapper.map(service.updateById(user.getId(), mapper.map(userInputDto))));
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
return ResponseEntity.ok().body(mapper.map(service.updateById(userId, mapper.map(userInputDto))));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment