Skip to content

Commit

Permalink
Merge pull request #29 from 2024-ITEC0401/develop
Browse files Browse the repository at this point in the history
Develop: 최종발표 전 완성 본 main 브랜치에 병합
  • Loading branch information
milk-stone authored Dec 9, 2024
2 parents 6cb5288 + 521d16d commit bb979e5
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 71 deletions.
3 changes: 2 additions & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ out/
### Ignore DB Password
src/main/resources/application-secret.yml
dev.env
ec2.dev
ec2.dev
src/main/resources/keystore.p12
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Collections;

Expand All @@ -17,15 +18,17 @@
public class SecurityConfig {

// Security 단에서 Cors 설정하는 익명 클래스
@Bean
CorsConfigurationSource corsConfigurationSource() {
return request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Collections.singletonList("*"));
config.setAllowedOriginPatterns(Collections.singletonList("http://localhost:5173")); // 허용할 origin
config.setAllowCredentials(true);
return config;
};
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOriginPatterns(Collections.singletonList("https://www.look-4-me.com")); // 허용할 origin
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Collections.singletonList("*"));
config.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); // 모든 경로에 대해 CORS 설정 적용
return source;
}

@Bean
Expand All @@ -35,6 +38,12 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource()))
.csrf((csrf) -> csrf.disable())
.headers((headers) -> headers.disable());
// .authorizeRequests(authorizeRequests -> authorizeRequests
// .anyRequest().authenticated() // 모든 요청은 인증 필요
// )
// .requiresChannel(channel -> channel
// .anyRequest().requiresSecure() // 모든 요청을 HTTPS로 요구
// );
return http.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,43 @@
import lombok.Getter;

@Getter
@Builder
public class ClothRequestDto {
// Create, Update 둘 다 이 형식
private String imageUri;
private String name;
private String mainCategory;
private String subCategory;
private String baseColor;
private String pointColor;
private String textile;
private String pattern;
private String season;
private String style;
private String description;
private final String imageUri;
private final String name;
private final String mainCategory;
private final String subCategory;
private final String baseColor;
private final String pointColor;
private final String textile;
private final String pattern;
private final String season;
private final String style;
private final String description;

@Builder
public ClothRequestDto(
String imageUri,
String name,
String mainCategory,
String subCategory,
String baseColor,
String pointColor,
String textile,
String pattern,
String season,
String style,
String description) {
this.imageUri = imageUri;
this.name = name;
this.mainCategory = mainCategory;
this.subCategory = subCategory;
this.baseColor = baseColor;
this.pointColor = pointColor;
this.textile = textile;
this.pattern = pattern;
this.season = season;
this.style = style;
this.description = description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.itec0401.backend.domain.clothing.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
public class DeleteImageUri {
private final String imageUri;

@Builder
public DeleteImageUri(String imageUri) {
this.imageUri = imageUri;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ public interface ClothingService {
List<ClothingData> addClothingInfo(List<Long> clothingIds);
Clothing getClothingEntity(Long id, Authentication authentication);
List<ClothInfoDto> getClothingDetails(Long user_id, Long coordination_id);
List<String> getClothingImages(Long user_id, Long coordination_id);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.itec0401.backend.domain.clothing.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itec0401.backend.domain.clothing.dto.ClothInfoDto;
import com.itec0401.backend.domain.clothing.dto.ClothRequestDto;
import com.itec0401.backend.domain.clothing.dto.DeleteImageUri;
import com.itec0401.backend.domain.clothing.entity.Clothing;
import com.itec0401.backend.domain.clothing.repository.ClothingRepository;
import com.itec0401.backend.domain.coordination.dto.ClothingData;
import com.itec0401.backend.domain.user.entity.User;
import com.itec0401.backend.domain.user.service.UserService;
import com.itec0401.backend.global.exception.ClothingNotFoundException;
import com.itec0401.backend.global.exception.NullResponseFromApiException;
import com.itec0401.backend.global.exception.UserNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -25,6 +29,7 @@
public class ClothingServiceImpl implements ClothingService {
private final ClothingRepository clothingRepository;
private final UserService userService;
private final RestTemplate restTemplate;

@Transactional
public ResponseEntity<Void> createClothing(ClothRequestDto dto, Authentication authentication) {
Expand Down Expand Up @@ -118,16 +123,39 @@ public ResponseEntity<Integer> deleteClothingById(Long id, Authentication authen
}
User validUser = user.get();

Optional<Clothing> clothing = clothingRepository.findByClothingId(id);
if (clothing.isEmpty()) {
throw new ClothingNotFoundException("Clothing not found");
}
Clothing c = clothing.get();
DeleteImageUri deleteImageUri = DeleteImageUri.builder().imageUri(c.getImageUri()).build();

String url = "http://34.64.155.160:5000/delete_image";
try{
// 요청 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");

// HttpEntity 객체 생성 (헤더와 바디 포함)
HttpEntity<Object> requestEntity = new HttpEntity<>(deleteImageUri, headers);

// DELETE 요청 보내기
ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Void.class);
System.out.println(response.getStatusCode());
} catch (ResourceAccessException e){
System.out.println(e.getMessage());
throw new NullResponseFromApiException("Error while using Python API");
}
return new ResponseEntity<>(clothingRepository.deleteByTwoId(validUser.getId(), id), HttpStatus.OK);
}

@Override
public List<ClothingData> addClothingInfo(List<Long> clothingIds){
List<ClothingData> clothingDataDtos = new ArrayList<>();
for (Long id : clothingIds){
Optional<Clothing> clothing = clothingRepository.findById(id);
Optional<Clothing> clothing = clothingRepository.findByClothingId(id);
if (clothing.isEmpty()) {
throw new ClothingNotFoundException("Clothing not found");
throw new ClothingNotFoundException("addClothingInfo : Clothing not found");
}
Clothing c = clothing.get();
clothingDataDtos.add(ClothingData.toDto(c));
Expand Down Expand Up @@ -157,4 +185,13 @@ public List<ClothInfoDto> getClothingDetails(Long user_id, Long coordination_id)
}
return clothInfoDtos;
}

@Override
public List<String> getClothingImages(Long user_id, Long coordination_id){
List<String> clothingImages = new ArrayList<>();
for (Clothing clothing : clothingRepository.findCodiDetails(user_id, coordination_id)){
clothingImages.add(clothing.getImageUri());
}
return clothingImages;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import com.itec0401.backend.domain.coordination.dto.BasicCodiRequestToSpring;
import com.itec0401.backend.domain.coordination.dto.CodiDetails;
import com.itec0401.backend.domain.coordination.dto.CodiInfo;
import com.itec0401.backend.domain.coordination.dto.CodiInfoWithImages;
import com.itec0401.backend.domain.coordination.dto.NLCodiRequestToSpring;
import com.itec0401.backend.domain.coordination.service.CoordinationService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
Expand All @@ -18,26 +19,50 @@
public class CoordinationController {
private final CoordinationService coordinationService;

@Operation(
summary = "Basic 코디 추천 API",
description = "옷 여러개 선택 후 요청하면, 그 옷을 이용해 입을 수 있는 코디를 1개 ~ 10개 추천해줌. " +
"추천된 결과가 바로 DB에 저장됨. " +
"내용을 열람하기 위해서는 특정 코디 상세 정보 열람 API 등을 사용해여함."
)
@PostMapping("/rec/basic")
public ResponseEntity<Void> coordRecommendBasic(@RequestBody BasicCodiRequestToSpring dto, Authentication authentication){
return coordinationService.coordRecommendBasic(dto, authentication);
}

@Operation(
summary = "자연어를 이용한 코디 추천 API",
description = "옷 여러개 선택 + 자연어 한 문장 을 이용해 요청하면, 그 자연어 상황에 맞는 코디를 1개 추천해줌. " +
"추천된 결과는 바로 DB에 저장됨." +
"생성된 코디 결과를 반환값으로 줌."
)
@PostMapping("/rec/natural-language")
public ResponseEntity<Void> coordRecommendUsingNaturalLanguage(@RequestBody NLCodiRequestToSpring dto, Authentication authentication){
public ResponseEntity<CodiInfoWithImages> coordRecommendUsingNaturalLanguage(@RequestBody NLCodiRequestToSpring dto, Authentication authentication){
return coordinationService.coordRecommendUsingNaturalLanguage(dto, authentication);
}

@Operation(
summary = "모든 코디 정보 열람 API",
description = "코디의 상세 정보가 열람됨."
)
@GetMapping
public ResponseEntity<List<CodiInfo>> getAllCoordinationInfos(Authentication authentication){
return coordinationService.getAllCodiInfos(authentication);
public ResponseEntity<List<CodiInfoWithImages>> getAllCoordinationInfos(Authentication authentication){
return coordinationService.getAllCodiInfoWithImages(authentication);
}

@Operation(
summary = "특정 코디 삭제 API",
description = "코디 id로 코디 삭제, 그 코디와 연관된 N:M 중간테이블에 있는 행도 당연히 다 삭제됨."
)
@DeleteMapping("/{id}")
public ResponseEntity<Integer> deleteCoordinationInfo(@PathVariable("id") Long id, Authentication authentication){
return coordinationService.deleteCodiById(id, authentication);
}

@Operation(
summary = "특정 코디 상세 정보 열람 API",
description = "코디의 정보와 코디에 사용되는 옷의 상세 정보를 싹 다 담았음."
)
@GetMapping("/{id}")
public ResponseEntity<CodiDetails> getCoordinationDetails(@PathVariable("id") Long id, Authentication authentication){
return coordinationService.getCoordinationDetails(id, authentication);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.List;

@Getter
Expand All @@ -12,14 +13,16 @@ public class CodiDetails {
private final String name;
private final String description;
private final String hashtags;
private final LocalDateTime createdAt;
private final List<ClothInfoDto> clothingList;

@Builder
public CodiDetails(Long id, String name, String description, String hashtags, List<ClothInfoDto> clothingList) {
public CodiDetails(Long id, String name, String description, String hashtags, LocalDateTime createdAt, List<ClothInfoDto> clothingList) {
this.id = id;
this.name = name;
this.description = description;
this.hashtags = hashtags;
this.createdAt = createdAt;
this.clothingList = clothingList;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.itec0401.backend.domain.coordination.dto;

import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.List;

@Getter
public class CodiInfoWithImages {
private final Long id;
private final String name;
private final String description;
private final String hashtags;
private final LocalDateTime createdAt;
private final List<String> clothingImages;

@Builder
public CodiInfoWithImages(Long id, String name, String description, String hashtags, LocalDateTime createdAt, List<String> clothingImages) {
this.id = id;
this.name = name;
this.description = description;
this.hashtags = hashtags;
this.createdAt = createdAt;
this.clothingImages = clothingImages;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package com.itec0401.backend.domain.coordination.dto;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Getter;

import java.util.List;

@Getter
public class NLCodiRequestToSpring {
private final List<Long> clothing;
private final String natural_language;

@JsonCreator
@Builder
public NLCodiRequestToSpring(List<Long> clothing, String natural_language) {
this.clothing = clothing;
public NLCodiRequestToSpring(@JsonProperty("natural_language") String natural_language) {
this.natural_language = natural_language;
}
}
Loading

0 comments on commit bb979e5

Please sign in to comment.