From f258824bf0bf271183a960e61f7a8ae6a41e69f3 Mon Sep 17 00:00:00 2001 From: Lee kangmin Date: Thu, 5 Sep 2024 12:01:13 +0900 Subject: [PATCH] =?UTF-8?q?[#225]=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/speech/up/api/converter/WavToRaw.java | 121 ++++++++++++++---- .../api/etri/service/VoiceToTextService.java | 48 +++---- .../up/auth/config/WebSecurityConfig.java | 8 +- .../up/auth/entity/CustomOAuth2User.java | 23 +++- .../auth/filter/JwtAuthenticationFilter.java | 34 +++-- .../speech/up/auth/provider/JwtProvider.java | 9 +- .../implement/OAuth2UserServiceImplement.java | 4 +- .../speech/up/common/enums/StatusCode.java | 1 + .../exception/custom/CustomIOException.java | 6 +- .../handler/ExceptionController.java | 14 ++ .../up/record/service/RecordService.java | 25 ++-- .../up/auth/entity/CustomOAuth2UserTest.java | 3 +- 12 files changed, 208 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/speech/up/api/converter/WavToRaw.java b/src/main/java/com/speech/up/api/converter/WavToRaw.java index de1ce27..69d7d21 100644 --- a/src/main/java/com/speech/up/api/converter/WavToRaw.java +++ b/src/main/java/com/speech/up/api/converter/WavToRaw.java @@ -1,8 +1,16 @@ package com.speech.up.api.converter; -import javax.sound.sampled.*; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; import java.util.Arrays; +import java.util.Optional; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + import org.springframework.web.multipart.MultipartFile; import jakarta.validation.constraints.NotNull; @@ -20,31 +28,98 @@ public WavToRaw() { super(); } - // WAV 파일을 읽어 PCM 데이터를 바이트 배열로 반환 - public byte[] convertToRawPcm(MultipartFile multipartFile) throws UnsupportedAudioFileException, IOException { - File file = File.createTempFile("uploaded-", ".wav"); - // MultipartFile 데이터를 임시 파일로 저장 - multipartFile.transferTo(file); - try (AudioInputStream sourceStream = AudioSystem.getAudioInputStream(file)) { - AudioFormat sourceFormat = sourceStream.getFormat(); - AudioFormat targetFormat = FORMAT; + // WAV 파일을 읽어 PCM 데이터를 Optional로 반환 + public Optional convertToRawPcm(MultipartFile multipartFile) { + Optional tempFile = createTempFile(multipartFile); + if (tempFile.isEmpty()) { + return Optional.empty(); // 파일 생성 실패 시 빈 Optional 반환 + } - if (!AudioSystem.isConversionSupported(targetFormat, sourceFormat)) { - throw new UnsupportedAudioFileException("The source format is not supported."); - } + Optional pcmData = processAudioFile(tempFile.get()); + deleteTempFile(tempFile.get()); - try (AudioInputStream convertedStream = AudioSystem.getAudioInputStream(targetFormat, sourceStream); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + return pcmData; + } - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = convertedStream.read(buffer)) != -1) { - byteArrayOutputStream.write(buffer, 0, bytesRead); - } + // MultipartFile을 임시 파일로 변환 + private Optional createTempFile(MultipartFile multipartFile) { + try { + File tempFile = File.createTempFile("uploaded-", ".wav"); + multipartFile.transferTo(tempFile); // MultipartFile을 임시 파일로 저장 + return Optional.of(tempFile); + } catch (IOException e) { + log.error("임시 파일 생성 실패: {}", e.getMessage()); + return Optional.empty(); // 파일 생성 실패 시 빈 Optional 반환 + } + } - byte[] rawPcmData = byteArrayOutputStream.toByteArray(); - return formatWav2Raw(rawPcmData); + // 임시 파일 삭제 + private void deleteTempFile(File tempFile) { + if (!fileExists(tempFile)) { + return; // 파일이 존재하지 않으면 조기 리턴 + } + + if (!tempFile.delete()) { + log.warn("임시 파일 삭제 실패: {}", tempFile.getPath()); + } + } + + // 파일 존재 여부 확인 + private boolean fileExists(File file) { + return file != null && file.exists(); + } + + // 파일을 처리하여 PCM 데이터로 변환 + private Optional processAudioFile(File file) { + Optional sourceStream = getAudioInputStream(file); + if (sourceStream.isEmpty()) { + return Optional.empty(); // AudioInputStream 생성 실패 시 빈 Optional 반환 + } + + Optional convertedStream = convertAudioStream(sourceStream.get()); + if (convertedStream.isEmpty()) { + return Optional.empty(); // AudioStream 변환 실패 시 빈 Optional 반환 + } + + return readPcmData(convertedStream.get()); + } + + // 오디오 파일을 AudioInputStream으로 가져오기 + private Optional getAudioInputStream(File file) { + try { + return Optional.of(AudioSystem.getAudioInputStream(file)); + } catch (UnsupportedAudioFileException | IOException e) { + log.error("오디오 스트림 생성 실패: {}", e.getMessage()); + return Optional.empty(); // AudioInputStream 생성 실패 시 빈 Optional 반환 + } + } + + // 소스 포맷을 변환 가능 여부 확인 및 변환 + private Optional convertAudioStream(AudioInputStream sourceStream) { + AudioFormat sourceFormat = sourceStream.getFormat(); + + if (!AudioSystem.isConversionSupported(FORMAT, sourceFormat)) { + log.error("변환할 수 없는 오디오 포맷: {}", sourceFormat); + return Optional.empty(); // 변환 불가 시 빈 Optional 반환 + } + + return Optional.of(AudioSystem.getAudioInputStream(FORMAT, sourceStream)); + } + + // PCM 데이터를 읽고 반환 + private Optional readPcmData(AudioInputStream convertedStream) { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = convertedStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, bytesRead); } + + byte[] rawPcmData = byteArrayOutputStream.toByteArray(); + return Optional.of(formatWav2Raw(rawPcmData)); // PCM 데이터로 변환 + } catch (IOException e) { + log.error("PCM 데이터 읽기 실패: {}", e.getMessage()); + return Optional.empty(); // PCM 데이터 읽기 실패 시 빈 Optional 반환 } } @@ -52,4 +127,4 @@ public byte[] convertToRawPcm(MultipartFile multipartFile) throws UnsupportedAud private byte[] formatWav2Raw(@NotNull final byte[] audioFileContent) { return Arrays.copyOfRange(audioFileContent, HEADER_SIZE, audioFileContent.length); } -} \ No newline at end of file +} diff --git a/src/main/java/com/speech/up/api/etri/service/VoiceToTextService.java b/src/main/java/com/speech/up/api/etri/service/VoiceToTextService.java index 613ed57..cb5525f 100644 --- a/src/main/java/com/speech/up/api/etri/service/VoiceToTextService.java +++ b/src/main/java/com/speech/up/api/etri/service/VoiceToTextService.java @@ -9,6 +9,7 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Base64; +import java.util.Objects; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; @@ -22,10 +23,12 @@ import com.speech.up.api.etri.dto.ResponseRecognitionDto; import com.speech.up.api.etri.type.ApiType; import com.speech.up.api.etri.url.UrlCollector; +import com.speech.up.common.enums.StatusCode; +import com.speech.up.common.exception.custom.CustomIOException; import com.speech.up.common.exception.http.BadRequestException; -import com.speech.up.report.service.ReportService; import com.speech.up.record.entity.RecordEntity; import com.speech.up.record.repository.RecordRepository; +import com.speech.up.report.service.ReportService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -55,10 +58,13 @@ public void callRecognitionApi(String script, Long recordId) { String audioContents = encodeAudioToBase64(recordEntity.getAudio()); RequestPronunciationDto pronunciationRequest = createPronunciationRequest(audioContents, script); - RequestRecognitionDto recognizedRequest = createRecognizedRequest(audioContents, recordEntity.getLanguageCode()); + RequestRecognitionDto recognizedRequest = createRecognizedRequest(audioContents, + recordEntity.getLanguageCode()); - ResponseEntity recognizedResponse = sendPostRequest(ApiType.RECOGNITION, recognizedRequest, ResponseRecognitionDto.class); - ResponseEntity pronunciationResponse = sendPostRequest(ApiType.PRONUNCIATION, pronunciationRequest, ResponsePronunciationApiDto.class); + ResponseEntity recognizedResponse = sendPostRequest(ApiType.RECOGNITION, + recognizedRequest, ResponseRecognitionDto.class); + ResponseEntity pronunciationResponse = sendPostRequest(ApiType.PRONUNCIATION, + pronunciationRequest, ResponsePronunciationApiDto.class); handleApiResponses(recognizedResponse, pronunciationResponse); @@ -67,7 +73,8 @@ public void callRecognitionApi(String script, Long recordId) { saveReportIfValid(recognizedBody, pronunciationBody, recordEntity); } catch (IOException e) { - throw new RuntimeException("Error during API request", e); + log.error(e.getMessage(), e); + throw new CustomIOException(StatusCode.IO_ERROR); } } @@ -88,21 +95,17 @@ private RequestRecognitionDto createRecognizedRequest(String audioContents, Stri return RequestRecognitionDto.createRecognition("reserved field", audioContents, languageCode); } - private ResponseEntity sendPostRequest(ApiType apiType, Object requestDTO, Class responseType) throws IOException { + private ResponseEntity sendPostRequest(ApiType apiType, Object requestDTO, Class responseType) throws + IOException { URL url = getUrl(apiType); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); configureConnection(con); - - try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { - String jsonRequest = gson.toJson(requestDTO); - log.info("Sending request to {} API: {}", apiType, jsonRequest); - wr.write(jsonRequest.getBytes(StandardCharsets.UTF_8)); - wr.flush(); - } + DataOutputStream wr = new DataOutputStream(con.getOutputStream()); + String jsonRequest = gson.toJson(requestDTO); + wr.write(jsonRequest.getBytes(StandardCharsets.UTF_8)); + wr.flush(); int responseCode = con.getResponseCode(); - log.info("Response code from {} API: {}", apiType, responseCode); - if (responseCode != HttpURLConnection.HTTP_OK) { String errorResponse = readErrorResponse(con); log.error("Error response from {} API: {}", apiType, errorResponse); @@ -130,12 +133,11 @@ private void configureConnection(HttpURLConnection con) throws ProtocolException } private String readErrorResponse(HttpURLConnection con) throws IOException { - try (InputStream errorStream = con.getErrorStream()) { - if (errorStream != null) { - return new String(errorStream.readAllBytes(), StandardCharsets.UTF_8); - } else { - return "No error stream available"; - } + InputStream errorStream = con.getErrorStream(); + if (Objects.nonNull(errorStream)) { + return new String(errorStream.readAllBytes(), StandardCharsets.UTF_8); + } else { + return "No error stream available"; } } @@ -153,7 +155,7 @@ private void handleApiResponses(ResponseEntity recognize private void saveReportIfValid(ResponseRecognitionDto recognizedBody, ResponsePronunciationApiDto pronunciationBody, RecordEntity recordEntity) { - if (recognizedBody != null && pronunciationBody != null) { + if (Objects.nonNull(recognizedBody) && Objects.nonNull(pronunciationBody)) { String recognized = recognizedBody.getReturn_object().getRecognized(); Double score = pronunciationBody.getReturn_object().getScore(); reportService.saveReport(recordEntity, recognized, score); diff --git a/src/main/java/com/speech/up/auth/config/WebSecurityConfig.java b/src/main/java/com/speech/up/auth/config/WebSecurityConfig.java index ceff0af..8f423c0 100644 --- a/src/main/java/com/speech/up/auth/config/WebSecurityConfig.java +++ b/src/main/java/com/speech/up/auth/config/WebSecurityConfig.java @@ -25,8 +25,8 @@ import com.speech.up.auth.filter.JwtAuthenticationFilter; import com.speech.up.auth.handler.OAuth2SuccessHandler; +import com.speech.up.common.enums.StatusCode; -import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @@ -69,7 +69,7 @@ protected SecurityFilterChain configure(HttpSecurity httpSecurity) throws Except "/report", "/scripts", "/script-write", "/scripts-list", "/replies/**", "/admin/view", "/page/me", "/speech-record", "reports/**", "/").permitAll() .requestMatchers("/api/boards").hasAnyRole("ADMIN_USER", "GENERAL_USER") - .requestMatchers("/users/me").hasAnyRole("ADMIN_USER", "GENERAL_USER","BAN_USER") + .requestMatchers("/users/me").hasAnyRole("ADMIN_USER", "GENERAL_USER", "BAN_USER") .requestMatchers("/speech-record").hasAnyRole("ADMIN_USER", "GENERAL_USER") .requestMatchers("/speech-record/**").hasAnyRole("ADMIN_USER", "GENERAL_USER") .requestMatchers("/speech-scripts/**").hasAnyRole("ADMIN_USER", "GENERAL_USER") @@ -108,9 +108,9 @@ class FailedAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws - IOException, ServletException { + IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_FORBIDDEN); - response.getWriter().write("{\"code\" : \"NP\", \"message\" : \"No Permission\"}"); + response.getWriter().write(String.valueOf(StatusCode.NO_AUTHORIZATION)); } } diff --git a/src/main/java/com/speech/up/auth/entity/CustomOAuth2User.java b/src/main/java/com/speech/up/auth/entity/CustomOAuth2User.java index fb3d43d..199d47e 100644 --- a/src/main/java/com/speech/up/auth/entity/CustomOAuth2User.java +++ b/src/main/java/com/speech/up/auth/entity/CustomOAuth2User.java @@ -1,9 +1,16 @@ package com.speech.up.auth.entity; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.user.OAuth2User; import lombok.AllArgsConstructor; @@ -14,19 +21,31 @@ public class CustomOAuth2User implements OAuth2User { private String userId; + private String authorities; // 사용자 권한을 쉼표로 구분된 문자열로 저장 @Override public Map getAttributes() { - return null; + Map attributes = new HashMap<>(); + attributes.put("userId", userId); + return attributes; } @Override public Collection getAuthorities() { - return null; + return Objects.isNull(authorities) ? parseAuthorities(authorities) : Set.of(); } @Override public String getName() { return this.userId; } + + // 권한 문자열을 파싱하여 GrantedAuthority의 컬렉션으로 변환 + private Collection parseAuthorities(String authorities) { + return Arrays.stream(authorities.split(",")) + .map(String::trim) + .filter(auth -> !auth.isEmpty()) + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/com/speech/up/auth/filter/JwtAuthenticationFilter.java b/src/main/java/com/speech/up/auth/filter/JwtAuthenticationFilter.java index c48b325..7cd3bda 100644 --- a/src/main/java/com/speech/up/auth/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/speech/up/auth/filter/JwtAuthenticationFilter.java @@ -4,21 +4,21 @@ import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import com.speech.up.auth.provider.JwtProvider; +import com.speech.up.common.enums.StatusCode; import com.speech.up.user.entity.UserEntity; import com.speech.up.user.repository.UserRepository; @@ -28,7 +28,9 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { @@ -40,31 +42,33 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { protected void doFilterInternal(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable FilterChain filterChain) throws ServletException, IOException { try { - assert filterChain != null; - assert request != null; + assert Objects.nonNull(filterChain); + assert Objects.nonNull(request); String token = parseBearerToken(request); - if(token == null){ + if (token.equals(String.valueOf(StatusCode.NO_AUTHORIZATION))) { filterChain.doFilter(request, response); return; } String socialId = jwtProvider.validate(token); - if(socialId == null){ + if (socialId == null) { filterChain.doFilter(request, response); return; } UserEntity userEntity = userRepository.findBySocialId(socialId) - .orElseThrow(() -> new NoSuchElementException("not found UserEntity by socialId : " + socialId));; + .orElseThrow(() -> new NoSuchElementException("not found UserEntity by socialId : " + socialId)); + ; String role = userEntity.getAuthorization(); List authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority(role)); SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); - AbstractAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(socialId, token, authorities); + AbstractAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(socialId, token, + authorities); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); securityContext.setAuthentication(authenticationToken); SecurityContextHolder.setContext(securityContext); - }catch(Exception exception){ + } catch (Exception exception) { throw new IOException("JWT Authentication 이 실패 했으니 확인 : ", exception); } @@ -74,10 +78,16 @@ protected void doFilterInternal(@Nullable HttpServletRequest request, @Nullable private String parseBearerToken(HttpServletRequest request) { String authorization = request.getHeader("Authorization"); boolean hasAuthorization = StringUtils.hasText(authorization); - if(!hasAuthorization){return null;} + if (!hasAuthorization) { + log.warn("Authorization header is empty"); + return String.valueOf(StatusCode.NO_AUTHORIZATION); + } boolean isBearer = authorization.startsWith("Bearer "); - if(!isBearer){return null;} + if (!isBearer) { + log.warn("Authorization header is invalid"); + return String.valueOf(StatusCode.NO_AUTHORIZATION); + } return authorization.substring(7); } diff --git a/src/main/java/com/speech/up/auth/provider/JwtProvider.java b/src/main/java/com/speech/up/auth/provider/JwtProvider.java index 9687895..e1a6be3 100644 --- a/src/main/java/com/speech/up/auth/provider/JwtProvider.java +++ b/src/main/java/com/speech/up/auth/provider/JwtProvider.java @@ -5,7 +5,10 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Date; +import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -16,6 +19,7 @@ @Component public class JwtProvider { + private static final Logger log = LoggerFactory.getLogger(JwtProvider.class); @Value("${jwt.secret.key}") private String secretKey; @@ -40,9 +44,8 @@ public String validate(String jwt) { .getBody() .getSubject(); } catch (NullPointerException nullPointerException) { + log.error("Invalid JWT"); throw new IllegalArgumentException("JwtProvider 클래스에 문제 있으니 확인해라."); - } catch (Exception exception) { - throw new IllegalArgumentException(exception); } return subject; } @@ -50,7 +53,7 @@ public String validate(String jwt) { public String getHeader(HttpServletRequest request) { String authorization = request.getHeader("Authorization"); - if (authorization != null && authorization.startsWith("Bearer ")) { + if (Objects.nonNull(authorization) && authorization.startsWith("Bearer ")) { authorization = authorization.substring(7); } diff --git a/src/main/java/com/speech/up/auth/service/implement/OAuth2UserServiceImplement.java b/src/main/java/com/speech/up/auth/service/implement/OAuth2UserServiceImplement.java index 9cdc725..18a3ed4 100644 --- a/src/main/java/com/speech/up/auth/service/implement/OAuth2UserServiceImplement.java +++ b/src/main/java/com/speech/up/auth/service/implement/OAuth2UserServiceImplement.java @@ -31,8 +31,6 @@ public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2Authenticatio Provider provider = new Provider(oAuth2User); UserEntity userEntity = provider.getUser(ProviderType.valueOf(oauthClientName.toUpperCase())); - assert userEntity != null; - if (!userRepository.existsBySocialId(userEntity.getSocialId())) { userRepository.save(userEntity); } else { @@ -42,7 +40,7 @@ public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2Authenticatio UserEntity updateUserAccess = UserEntity.updateUserAccess(user); userRepository.save(updateUserAccess); } - return new CustomOAuth2User(userEntity.getSocialId()); + return new CustomOAuth2User(userEntity.getSocialId(), userEntity.getAuthorization()); } } diff --git a/src/main/java/com/speech/up/common/enums/StatusCode.java b/src/main/java/com/speech/up/common/enums/StatusCode.java index d8104a2..6ca3cc0 100644 --- a/src/main/java/com/speech/up/common/enums/StatusCode.java +++ b/src/main/java/com/speech/up/common/enums/StatusCode.java @@ -8,6 +8,7 @@ public enum StatusCode { IO_ERROR(1, "IO Error"), NO_SCRIPTS(1001, "No Scripts"), NO_RECORDS(2002, "No Records"), + NO_AUTHORIZATION(403, "No Authorization"), NO_FILES(2003, "No Files"); private final int code; diff --git a/src/main/java/com/speech/up/common/exception/custom/CustomIOException.java b/src/main/java/com/speech/up/common/exception/custom/CustomIOException.java index 76ccc8d..a5bf6c1 100644 --- a/src/main/java/com/speech/up/common/exception/custom/CustomIOException.java +++ b/src/main/java/com/speech/up/common/exception/custom/CustomIOException.java @@ -1,15 +1,11 @@ package com.speech.up.common.exception.custom; -import java.io.IOException; - -import org.springframework.http.HttpStatus; - import com.speech.up.common.enums.StatusCode; import lombok.Getter; @Getter -public abstract class CustomIOException extends IOException { +public class CustomIOException extends RuntimeException { private final StatusCode errorCode; public CustomIOException(StatusCode errorCode) { diff --git a/src/main/java/com/speech/up/common/exception/handler/ExceptionController.java b/src/main/java/com/speech/up/common/exception/handler/ExceptionController.java index ea3e51e..ab1b9c6 100644 --- a/src/main/java/com/speech/up/common/exception/handler/ExceptionController.java +++ b/src/main/java/com/speech/up/common/exception/handler/ExceptionController.java @@ -1,5 +1,7 @@ package com.speech.up.common.exception.handler; +import java.io.IOException; + import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; @@ -15,6 +17,7 @@ @ControllerAdvice public class ExceptionController { + @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity> handleMethodArgumentNotValidException( MethodArgumentNotValidException exception) { @@ -67,6 +70,7 @@ public ResponseEntity> handleCustomException(CustomIl HttpStatusCode.valueOf(exception.getErrorCode().getCode()) ); } + @ExceptionHandler(CustomIOException.class) public ResponseEntity> handleCustomException(CustomIOException exception) { ApiExceptionResponse responseDto = ApiExceptionResponse.builder() @@ -80,4 +84,14 @@ public ResponseEntity> handleCustomException(CustomIO ); } + @ExceptionHandler(NullPointerException.class) + public ResponseEntity> handleNullPointerException(NullPointerException exception) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + + @ExceptionHandler(IOException.class) + public ResponseEntity> handleIOException(IOException exception) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } diff --git a/src/main/java/com/speech/up/record/service/RecordService.java b/src/main/java/com/speech/up/record/service/RecordService.java index 402cb8b..9ccfbe9 100644 --- a/src/main/java/com/speech/up/record/service/RecordService.java +++ b/src/main/java/com/speech/up/record/service/RecordService.java @@ -1,5 +1,16 @@ package com.speech.up.record.service; +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.sound.sampled.UnsupportedAudioFileException; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + import com.speech.up.api.converter.WavToRaw; import com.speech.up.record.entity.RecordEntity; import com.speech.up.record.repository.RecordRepository; @@ -12,16 +23,6 @@ import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -import javax.sound.sampled.UnsupportedAudioFileException; - @Service @RequiredArgsConstructor public class RecordService { @@ -50,9 +51,9 @@ public RecordAddDto.Response addRecord(MultipartFile file, String languageCode, .orElseThrow(() -> new EntityNotFoundException("script not found by scriptId : " + scriptId)); WavToRaw wavToRaw = new WavToRaw(); - byte[] audio = wavToRaw.convertToRawPcm(file); + Optional audio = wavToRaw.convertToRawPcm(file); RecordAddDto.Request request = new RecordAddDto.Request(file, languageCode, scriptEntity); - RecordEntity recordEntity = RecordEntity.create(audio, request, scriptEntity); + RecordEntity recordEntity = RecordEntity.create(audio.orElse(null), request, scriptEntity); return RecordAddDto.toResponse(recordRepository.save(recordEntity)); } diff --git a/src/test/java/com/speech/up/auth/entity/CustomOAuth2UserTest.java b/src/test/java/com/speech/up/auth/entity/CustomOAuth2UserTest.java index 281cff1..1cf27d8 100644 --- a/src/test/java/com/speech/up/auth/entity/CustomOAuth2UserTest.java +++ b/src/test/java/com/speech/up/auth/entity/CustomOAuth2UserTest.java @@ -18,7 +18,8 @@ class CustomOAuth2UserTest { void testGetName() { // Given String userId = "test-user"; - CustomOAuth2User customOAuth2User = new CustomOAuth2User(userId); + String authorities = "test-authorities"; + CustomOAuth2User customOAuth2User = new CustomOAuth2User(userId,authorities); // When String name = customOAuth2User.getName();