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

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