Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.webservice.algorithmchef.client;

import com.webservice.algorithmchef.dto.recipe.CookRcpResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class FoodSafetyApiClient {

private final RestTemplate restTemplate;

public FoodSafetyApiClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

@Value("${foodsafety.cookrcp.base-url}")
private String baseUrl;

@Value("${foodsafety.cookrcp.service-key}")
private String serviceKey;

@Value("${foodsafety.cookrcp.svc-no}")
private String svcNo;

public int getTotalCount() {
String url = String.format("%s/%s/%s/json/1/1",
baseUrl, serviceKey, svcNo);

CookRcpResponse res = restTemplate.getForObject(url, CookRcpResponse.class);

if (res == null || res.getCOOKRCP01() == null) return 0;

try {
return Integer.parseInt(res.getCOOKRCP01().getTotalCount());
} catch (Exception e) {
return 0;
}
}

public List<CookRcpResponse.Item> fetchRange(int start, int end) {
String url = String.format("%s/%s/%s/json/%d/%d",
baseUrl, serviceKey, svcNo, start, end);

CookRcpResponse res = restTemplate.getForObject(url, CookRcpResponse.class);

return Optional.ofNullable(res)
.map(CookRcpResponse::getCOOKRCP01)
.map(CookRcpResponse.Body::getRow)
.orElse(List.of());
}

public List<CookRcpResponse.Item> fetchAll() {
int total = getTotalCount();
if (total <= 0) return List.of();

int pageSize = 200;
List<CookRcpResponse.Item> all = new ArrayList<>(total);

for (int start = 1; start <= total; start += pageSize) {
int end = Math.min(start + pageSize - 1, total);
all.addAll(fetchRange(start, end));
}

return all;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import org.springframework.web.filter.OncePerRequestFilter;

// (⭐수정) algorithmchef 프로젝트의 의존성으로 변경
import com.webservice.algorithmchef.service.UserService;
import com.webservice.algorithmchef.service.UserService;
import com.webservice.algorithmchef.util.JwtUtil;

import io.jsonwebtoken.Claims;
Expand Down Expand Up @@ -60,13 +60,13 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
claims = jwtUtil.getClaims(token);
} catch (Exception e) {
log.warn("유효하지 않은 JWT 토큰: {}", e.getMessage());
// (참고) 여기서 401 Unauthorized를 바로 반환할 수도 있으나,
// (참고) 여기서 401 Unauthorized를 바로 반환할 수도 있으나,
// SecurityConfig의 exceptionHandling에서 처리하도록 위임하는 것이 일반적입니다.
}

// 3. 토큰이 유효하고, 아직 SecurityContext에 인증 정보가 없는 경우
if (claims != null && SecurityContextHolder.getContext().getAuthentication() == null) {

// claims.getSubject()는 User 엔티티의 "userLoginId" (로그인 ID)여야 합니다.
String userLoginId = claims.getSubject();
String status = claims.get("status", String.class); // "status" 클레임 추출
Expand All @@ -84,11 +84,11 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
return; // 필터 체인 중단
}
}

// 6. (정상 사용자) 또는 (임시 사용자가 허용된 URL에 접근한 경우)
// UserDetails를 DB에서 조회하여 인증 토큰 생성
UserDetails userDetails = userService.loadUserByUsername(userLoginId);

UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
Expand All @@ -97,7 +97,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
log.info("SecurityContext에 인증 정보 저장 완료: {}", userLoginId);
}

// 8. 다음 필터로 체인 넘김
filterChain.doFilter(request, response);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.webservice.algorithmchef.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;

private final JwtAuthenticationFilter jwtAuthenticationFilter;


@Bean
Expand All @@ -34,8 +34,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti

http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/auth/login", "/auth/signUp",
"/auth/findPassword", "/auth/findUserId").permitAll()
.requestMatchers("/auth/login", "/auth/signUp",
"/auth/findPassword", "/auth/findUserId").permitAll()
.anyRequest().authenticated());

http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@
@RestController
@RequiredArgsConstructor
public class RecipeReviewController {
private final RecipeReviewService rService;
@PostMapping("/recipe/review")
public ResponseEntity<?> makeReview(@RequestBody RecipeReviewRequest request,
@AuthenticationPrincipal UserDetails userDetails){
try {
String userId = userDetails.getUsername();
RecipeReviewResponse response = rService.makeReview(request, userId);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}

private final RecipeReviewService rService;

@PostMapping("/recipe/review")
public ResponseEntity<?> makeReview(@RequestBody RecipeReviewRequest request,
@AuthenticationPrincipal UserDetails userDetails){
try {
String userId = userDetails.getUsername();
RecipeReviewResponse response = rService.makeReview(request, userId);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.webservice.algorithmchef.controller;

import com.webservice.algorithmchef.model.Recipe;
import com.webservice.algorithmchef.service.RecipeService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/recipes")
@CrossOrigin(origins = "http://localhost:3000")
public class RecipeSearchController {

private final RecipeService recipeService;

public RecipeSearchController(RecipeService recipeService) {
this.recipeService = recipeService;
}

@GetMapping("/search")
public ResponseEntity<?> getRandomRecipe(@RequestParam String ingredient) {

Recipe recipe = recipeService.getRandomRecipeByIngredient(ingredient);

if (recipe == null) {
return ResponseEntity.ok("검색된 레시피가 없습니다.");
}

return ResponseEntity.ok(recipe);
}

@GetMapping("/search-multi")
public ResponseEntity<?> getRandomRecipeMultiple(@RequestParam String ingredients) {

List<String> ingList =
Arrays.stream(ingredients.split(","))
.map(String::trim)
.toList();

Recipe recipe = recipeService.getRandomRecipeByIngredients(ingList);

if (recipe == null) {
return ResponseEntity.ok("해당 재료들을 모두 포함한 레시피가 없습니다.");
}

return ResponseEntity.ok(recipe);
}
}
Loading