Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into frontend/feature/2…
Browse files Browse the repository at this point in the history
…18-bookmarks-page
  • Loading branch information
NazireAta committed May 15, 2024
2 parents c2bdf3b + cab3f01 commit 6fbb1be
Show file tree
Hide file tree
Showing 55 changed files with 2,160 additions and 530 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.group1.cuisines.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.group1.cuisines.dao.response.ErrorResponse;
import com.group1.cuisines.entities.User;
import com.group1.cuisines.repositories.UserRepository;
import com.group1.cuisines.services.JwtService;
import com.group1.cuisines.services.UserService;
import io.jsonwebtoken.ExpiredJwtException;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
Expand All @@ -14,63 +19,96 @@
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final UserRepository userRepository;
private final JwtService jwtService;
private final UserService userService;
private final ObjectMapper objectMapper;

private static final Logger logger = LoggerFactory.getLogger(UserService.class);

@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
try {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;

if (
StringUtils.isEmpty(authHeader) ||
!org.springframework.util.StringUtils.startsWithIgnoreCase(
authHeader,
"Bearer "
)
) {
logger.info("No JWT token found in request headers");
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
userEmail = jwtService.extractUsername(jwt);
if (
StringUtils.isNotEmpty(userEmail) &&
SecurityContextHolder.getContext().getAuthentication() == null
) {
UserDetails userDetails = userService
.userDetailsService()
.loadUserByUsername(userEmail);
if (jwtService.isTokenValid(jwt, userDetails)) {
SecurityContext context =
SecurityContextHolder.createEmptyContext();
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
if (
StringUtils.isEmpty(authHeader) ||
!org.springframework.util.StringUtils.startsWithIgnoreCase(
authHeader,
"Bearer "
)
) {
logger.info("No JWT token found in request headers");
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
userEmail = jwtService.extractUsername(jwt);
if (
StringUtils.isNotEmpty(userEmail) &&
SecurityContextHolder.getContext().getAuthentication() == null
) {
UserDetails userDetails = userDetailsService().loadUserByUsername(userEmail);
if (jwtService.isTokenValid(jwt, userDetails)) {
SecurityContext context =
SecurityContextHolder.createEmptyContext();
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
context.setAuthentication(authToken);
SecurityContextHolder.setContext(context);
context.setAuthentication(authToken);
SecurityContextHolder.setContext(context);
}
}
}
catch (ExpiredJwtException e ){
logger.info("JWT token has expired");
ErrorResponse errorResponse = new ErrorResponse(HttpServletResponse.SC_UNAUTHORIZED, "JWT token has expired");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
return;

}
filterChain.doFilter(request, response);
}

public UserDetailsService userDetailsService() {
return new UserDetailsService() {

@Override
public UserDetails loadUserByUsername(String usernameOrEmail) {
logger.debug("Attempting to find user by email or username: {}", usernameOrEmail);

User user = userRepository.findByEmailOrUsername(usernameOrEmail, usernameOrEmail)
.orElseThrow(() -> new UsernameNotFoundException("User not found with username or email : " + usernameOrEmail));

return user;
}

};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@
@RequiredArgsConstructor
public class SecurityConfiguration {

private final UserService userService;

private final JwtAuthenticationFilter jwtAuthenticationFilter;


@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
Expand Down Expand Up @@ -69,7 +66,7 @@ public PasswordEncoder passwordEncoder() {
public AuthenticationProvider authenticationProvider() { // Authentication provider
DaoAuthenticationProvider authProvider =
new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService.userDetailsService());
authProvider.setUserDetailsService(jwtAuthenticationFilter.userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.group1.cuisines.dto.*;
import com.group1.cuisines.entities.Comment;
import com.group1.cuisines.entities.User;
import com.group1.cuisines.services.AuthenticationService;
import com.group1.cuisines.services.RecipeService;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
Expand All @@ -20,6 +21,8 @@
public class RecipeController {
@Autowired
private RecipeService recipeService;
@Autowired
private AuthenticationService authenticationService;


@GetMapping("/recipes/{recipeId}")
Expand All @@ -45,14 +48,13 @@ public ResponseEntity<List<RecipeDto>> getRecipes(@RequestParam(required = false

@PostMapping("/recipes")
public ResponseEntity<?> createRecipe(@RequestBody NewRecipeDto newRecipe) throws Exception{
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authenticationService.getUser().map(User::getUsername).orElse(null);

// Check if the user is authenticated
if (authentication == null || authentication.getPrincipal().equals("anonymousUser")) {
if (username == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Authentication required.");
}

String username = authentication.getName();
RecipeDetailDto recipeDetails = recipeService.createRecipe(newRecipe, username);
if (recipeDetails != null) {
return ResponseEntity.status(HttpStatus.CREATED).body(recipeDetails);
Expand All @@ -62,14 +64,12 @@ public ResponseEntity<?> createRecipe(@RequestBody NewRecipeDto newRecipe) throw
}
@DeleteMapping("/recipes/{id}")
public ResponseEntity<?> deleteRecipe(@PathVariable Integer id) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authenticationService.getUser().map(User::getUsername).orElse(null);

// Check if the user is authenticated
if (authentication == null || authentication.getPrincipal().equals("anonymousUser")) {
if (username == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Authentication required.");
}

String username = authentication.getName();
if (recipeService.deleteRecipe(id, username)) {
return ResponseEntity.status(HttpStatus.NO_CONTENT).body("Recipe deleted successfully.");
} else {
Expand All @@ -78,12 +78,11 @@ public ResponseEntity<?> deleteRecipe(@PathVariable Integer id) {
}
@PostMapping("/recipes/{recipeId}/rating")
public ResponseEntity<?> rateRecipe(@PathVariable Integer recipeId, @RequestBody RatingDto ratingDto) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication.getPrincipal().equals("anonymousUser")) {
String username = authenticationService.getUser().map(User::getUsername).orElse(null);
if (username == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Authentication required.");
}

String username = authentication.getName(); // Assuming the username can be obtained like this
boolean success = recipeService.rateRecipe(recipeId, username, ratingDto.getRating());

if (success) {
Expand All @@ -95,12 +94,11 @@ public ResponseEntity<?> rateRecipe(@PathVariable Integer recipeId, @RequestBody

@PostMapping("/recipes/{recipeId}/bookmarks")
public ResponseEntity<?> bookmarkRecipe(@PathVariable Integer recipeId) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication.getPrincipal().equals("anonymousUser")) {
String username = authenticationService.getUser().map(User::getUsername).orElse(null);
if (username == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Authentication required.");
}

String username = authentication.getName(); // Assuming the username can be obtained like this
boolean success = recipeService.bookmarkRecipe(recipeId, username);

if (success) {
Expand All @@ -112,8 +110,8 @@ public ResponseEntity<?> bookmarkRecipe(@PathVariable Integer recipeId) {

@GetMapping("/recipes/{recipeId}/bookmarks")
public ResponseEntity<?> getBookmarks(@PathVariable Integer recipeId) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication.getPrincipal().equals("anonymousUser")) {
String username = authenticationService.getUser().map(User::getUsername).orElse(null);
if (username == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Authentication required.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -30,20 +32,43 @@ public class SearchController {

@GetMapping("/users")
public ResponseEntity<?> searchUsers(@RequestParam(required = false) String q) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Integer currentUserId = null;
if (authentication != null && authentication.isAuthenticated() && !authentication.getPrincipal().equals("anonymousUser")) {
currentUserId = ((User) authentication.getPrincipal()).getId();
}
else{
currentUserId = null;
}
List<User> users = userService.searchUsers(q);
if (users.isEmpty()) {
// Return a custom message with a "No Content" status when no users are found
return ResponseEntity.ok(new ErrorResponse(204,"No users found"));
}
return ResponseEntity.ok(new SuccessResponse<>(200, users.stream().map(user -> new UserDto(
user.getId(),
user.getUsername(),
user.getFirstName(),
user.getLastName(),
user.getFollowerCount(),
user.getFollowingCount(),
user.getRecipeCount()
)).collect(Collectors.toList()), "Users fetched successfully"));
Integer finalCurrentUserId = currentUserId;
List<UserDto> userDtos = users.stream().map(user -> {
Integer currentId = finalCurrentUserId;
boolean isSelf = user.getId().equals(currentId); // Check if the current user is the same as the user in the list
boolean isFollowing = false;
if (currentId != null && !isSelf) {
isFollowing = userService.isFollowing(currentId, user.getId()); // Checking following status
}
return new UserDto(
user.getId(),
user.getUsername(),
user.getFirstName(),
user.getLastName(),
isFollowing,
user.getFollowerCount(),
user.getFollowingCount(),
user.getRecipeCount()


);
}).collect(Collectors.toList());

return ResponseEntity.ok(new SuccessResponse<>(200, userDtos, "Users fetched successfully"));


}

Expand Down
Loading

0 comments on commit 6fbb1be

Please sign in to comment.