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
Expand Up @@ -4,7 +4,8 @@
import org.springframework.http.HttpStatus;

public enum MenteeErrorCode implements ErrorCode {
MENTEE_PROFILE_NOT_FOUND(HttpStatus.NOT_FOUND, "멘티 프로필을 등록한 적이 없음");
MENTEE_PROFILE_NOT_FOUND(HttpStatus.NOT_FOUND, "멘티 프로필을 등록한 적이 없음"),
MENTEE_NOT_FOUND(HttpStatus.NOT_FOUND, "멘티 정보를 찾을 수 없음");

MenteeErrorCode(HttpStatus status, String message) {
this.status = status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import org.springframework.http.HttpStatus;

public enum MentorErrorCode implements ErrorCode {
MENTOR_PROFILE_NOT_FOUND(HttpStatus.NOT_FOUND, "멘토 프로필을 등록한 적이 없음");
MENTOR_PROFILE_NOT_FOUND(HttpStatus.NOT_FOUND, "멘토 프로필을 등록한 적이 없음"),
MENTOR_NOT_FOUND(HttpStatus.NOT_FOUND, "멘토 정보를 찾을 수 없음");

MentorErrorCode(HttpStatus status, String message) {
this.status = status;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package es.princip.ringus.domain.exception;

import es.princip.ringus.global.exception.ErrorCode;
import org.springframework.http.HttpStatus;

public enum ProfileErrorCode implements ErrorCode {
PROFILE_NOT_FOUND(HttpStatus.NOT_FOUND,"프로필을 찾을 수 없음");

ProfileErrorCode(HttpStatus status,String message) {
this.status = status;
this.message = message;
}

private final HttpStatus status;
private final String message;

@Override
public HttpStatus status() {
return this.status;
}

@Override
public String message() {
return this.message;
}

@Override
public String code() {
return this.name();
}
}
24 changes: 24 additions & 0 deletions src/main/java/es/princip/ringus/global/util/StoragePathUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package es.princip.ringus.global.util;

import es.princip.ringus.domain.member.MemberType;
import es.princip.ringus.infra.storage.domain.CertificateType;

public class StoragePathUtil {

private StoragePathUtil() {} // 유틸리티 클래스이므로 인스턴스화 방지

/**
* 증명서 폴더 경로 생성
*/
public static String buildCertificateFolderPath(CertificateType certificateType, Boolean isMentor) {
String roleFolder = isMentor ? "mentor" : "mentee";
return String.format("certificates/%s/%s", roleFolder, certificateType.name().toLowerCase());
}

/**
* 프로필 이미지 폴더 경로 생성
*/
public static String buildProfileFolderPath(MemberType userType) {
return String.format("images/profile/%s", userType.name().toLowerCase());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,42 @@
import es.princip.ringus.domain.exception.MemberErrorCode;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.global.util.ApiResponseWrapper;
import es.princip.ringus.infra.storage.application.StorageService;
import es.princip.ringus.infra.storage.application.StorageCertificateService;
import es.princip.ringus.infra.storage.dto.CertificateUploadRequest;
import es.princip.ringus.infra.storage.dto.ProfileUploadRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/storage")
@RequestMapping("/storage/certificate")
@RequiredArgsConstructor
public class StorageController {

private final StorageService storageService;
public class CertificateController {

private final StorageCertificateService storageCertificateService;
/**
* 멘티 증명서 업로드
*/
@PostMapping("/certificate/mentee")
@PostMapping("/mentee")
public ResponseEntity<ApiResponseWrapper<Void>> uploadMenteeCertificate(
@ModelAttribute CertificateUploadRequest certificateUploadRequest,
HttpSession session
) {
) {

Long memberId = (Long)session.getAttribute("memberId");
if(memberId == null){
throw new CustomRuntimeException(MemberErrorCode.SESSION_EXPIRED);
}

String filePath = storageService.uploadMenteeCertificate(certificateUploadRequest,memberId);
String filePath = storageCertificateService.uploadMenteeCertificate(certificateUploadRequest,memberId);
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, filePath));
}

/**
* 멘토 증명서 업로드
*/
@PostMapping("/certificate/mentor")
@PostMapping("/mentor")
public ResponseEntity<ApiResponseWrapper<Void>> uploadMentorCertificate(
@ModelAttribute CertificateUploadRequest certificateUploadRequest,
HttpSession session
Expand All @@ -53,25 +48,8 @@ public ResponseEntity<ApiResponseWrapper<Void>> uploadMentorCertificate(
throw new CustomRuntimeException(MemberErrorCode.SESSION_EXPIRED);
}

String filePath = storageService.uploadMentorCertificate(certificateUploadRequest, memberId);
String filePath = storageCertificateService.uploadMentorCertificate(certificateUploadRequest, memberId);
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, filePath));
}

/**
* 프로필 이미지 업로드
*/
@PostMapping("/profile/image")
public ResponseEntity<ApiResponseWrapper<Void>> uploadProfileImage(
@ModelAttribute ProfileUploadRequest request,
HttpSession session
) {

Long memberId = (Long)session.getAttribute("memberId");
if(memberId == null){
throw new CustomRuntimeException(MemberErrorCode.SESSION_EXPIRED);
}

String filePath = storageService.uploadProfileImage(request);
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, filePath));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package es.princip.ringus.infra.storage.api;

import es.princip.ringus.domain.exception.MemberErrorCode;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.global.util.ApiResponseWrapper;
import es.princip.ringus.infra.storage.application.StorageProfileImageService;
import es.princip.ringus.infra.storage.dto.ProfileUploadRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/storage/profile")
@RequiredArgsConstructor
public class ProfileImageController {

private final StorageProfileImageService storageProfileService;

/**
* 프로필 이미지 업로드
*/
@PostMapping("/image")
public ResponseEntity<ApiResponseWrapper<Void>> uploadProfileImage(
@ModelAttribute ProfileUploadRequest request,
HttpSession session
) {

Long memberId = (Long)session.getAttribute("memberId");
if(memberId == null){
throw new CustomRuntimeException(MemberErrorCode.SESSION_EXPIRED);
}

String filePath = storageProfileService.uploadProfileImage(request);
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, filePath));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class S3Service {
/**
* S3에 파일 업로드
* @param file 업로드할 파일
* @param folderPath S3에 저장할 폴더 경로 (예: "profile-images/mentor", "certificates/mentee/ENROLLMENT" 등)
* @param folderPath S3에 저장할 폴더 경로 (예: "images/profile/mentor", "certificates/mentee/ENROLLMENT" 등)
* @return 업로드된 파일의 S3 URL
*/
public String uploadFile(MultipartFile file, String folderPath) {
Expand Down Expand Up @@ -53,7 +53,7 @@ public String uploadFile(MultipartFile file, String folderPath) {
/**
* S3에 저장된 파일의 URL 반환
*/
private String getFileUrl(String s3Key) {
protected String getFileUrl(String s3Key) {
return "https://" + bucketName + ".s3.amazonaws.com/" + s3Key;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package es.princip.ringus.infra.storage.application;

import es.princip.ringus.global.util.StoragePathUtil;
import es.princip.ringus.infra.storage.domain.FileMemberRepository;
import es.princip.ringus.infra.storage.dto.CertificateUploadRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class StorageCertificateService {
private final S3Service s3Service;
private final FileMemberRepository fileMemberRepository;

/**
* 멘티 증명서 업로드
*/
@Transactional
public String uploadMenteeCertificate(CertificateUploadRequest request, Long memberId) {
String folderPath = StoragePathUtil.buildCertificateFolderPath(request.certificateType(), false);
String filePath = s3Service.uploadFile(request.file(), folderPath);

fileMemberRepository.save(request.toFileMemberEntity(filePath, memberId));

return filePath;
}

/**
* 멘토 증명서 업로드
*/
@Transactional
public String uploadMentorCertificate(CertificateUploadRequest request, Long memberId) {
String folderPath = StoragePathUtil.buildCertificateFolderPath(request.certificateType(), true);
String filePath = s3Service.uploadFile(request.file(), folderPath);

fileMemberRepository.save(request.toFileMemberEntity(filePath, memberId));

return filePath;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package es.princip.ringus.infra.storage.application;

import es.princip.ringus.global.util.StoragePathUtil;
import es.princip.ringus.infra.storage.dto.ProfileUploadRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class StorageProfileImageService {

private final S3Service s3Service;

/**
* 프로필 이미지 업로드
*/
@Transactional
public String uploadProfileImage(ProfileUploadRequest request) {
String folderPath = StoragePathUtil.buildProfileFolderPath(request.memberType());
return s3Service.uploadFile(request.file(), folderPath);
}

}

This file was deleted.

Loading