-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] 이동봉사자, 이동봉사 중개 자체 회원가입 API 구현 #23
Changes from all commits
fff25d3
00e982b
d38f986
d5b823d
330127b
ac9d023
30485c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.pawwithu.connectdog.common.s3; | ||
|
||
import com.amazonaws.services.s3.AmazonS3Client; | ||
import com.amazonaws.services.s3.model.DeleteObjectRequest; | ||
import com.amazonaws.services.s3.model.ObjectMetadata; | ||
import com.pawwithu.connectdog.error.exception.custom.BadRequestException; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.UUID; | ||
|
||
import static com.pawwithu.connectdog.error.ErrorCode.INVALID_FILE_UPLOAD; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class FileService { | ||
|
||
private final AmazonS3Client amazonS3Client; | ||
|
||
@Value("${cloud.aws.s3.bucket.name}") | ||
private String bucketName; | ||
|
||
@Value("${cloud.aws.s3.bucket.url}") | ||
private String defaultUrl; | ||
|
||
public String uploadFile(MultipartFile multipartFile, String imageType) { | ||
if (multipartFile == null || multipartFile.isEmpty()) return null; | ||
|
||
String savedFileName = getSavedFileName(multipartFile, imageType); | ||
ObjectMetadata metadata = new ObjectMetadata(); | ||
|
||
try (InputStream inputStream = multipartFile.getInputStream()) { | ||
amazonS3Client.putObject(bucketName, savedFileName, inputStream, metadata); | ||
} catch (IOException e) { | ||
log.error("Failed to upload image", e); | ||
throw new BadRequestException(INVALID_FILE_UPLOAD); | ||
} | ||
return getResourceUrl(savedFileName); | ||
} | ||
|
||
public void deleteFile(String fileUrl) { | ||
String fileName = getFileNameFromResourceUrl(fileUrl); | ||
amazonS3Client.deleteObject(new DeleteObjectRequest(bucketName, fileName)); | ||
} | ||
|
||
// imageType: volunteer -> "volunteer" | ||
private String getSavedFileName(MultipartFile multipartFile, String imageType) { | ||
return String.format("%s/%s-%s", | ||
imageType, getRandomUUID(), multipartFile.getOriginalFilename()); | ||
} | ||
|
||
private String getRandomUUID() { | ||
return UUID.randomUUID().toString().replace("-", ""); | ||
} | ||
|
||
private String getResourceUrl(String savedFileName) { | ||
return amazonS3Client.getResourceUrl(bucketName, savedFileName); | ||
} | ||
|
||
private String getFileNameFromResourceUrl(String fileUrl) { | ||
return fileUrl.replace(defaultUrl + "/", ""); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.pawwithu.connectdog.config; | ||
|
||
import com.amazonaws.auth.AWSStaticCredentialsProvider; | ||
import com.amazonaws.auth.BasicAWSCredentials; | ||
import com.amazonaws.services.s3.AmazonS3Client; | ||
import com.amazonaws.services.s3.AmazonS3ClientBuilder; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class S3Config { | ||
|
||
@Value("${cloud.aws.credentials.access-key}") | ||
private String accessKey; | ||
|
||
@Value("${cloud.aws.credentials.secret-key}") | ||
private String secretKey; | ||
|
||
@Value("${cloud.aws.region.static}") | ||
private String region; | ||
|
||
@Bean | ||
public AmazonS3Client amazonS3Client() { | ||
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); | ||
|
||
return (AmazonS3Client) AmazonS3ClientBuilder | ||
.standard() | ||
.withRegion(region) | ||
.withCredentials(new AWSStaticCredentialsProvider(credentials)) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.pawwithu.connectdog.domain.auth.dto.request; | ||
|
||
import com.pawwithu.connectdog.domain.intermediary.entity.Intermediary; | ||
import com.pawwithu.connectdog.domain.intermediary.entity.IntermediaryRole; | ||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
|
||
public record IntermediarySignUpRequest(@Email(message="이메일 형식에 맞지 않습니다.") | ||
@NotBlank(message = "이메일은 필수 입력 값입니다.") String email, | ||
@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d).{10,}$|^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[~!@#$%^&*()+|=?]).{8,}$", | ||
message = "영문+숫자 10자 이상 또는 영문+숫자+특수기호 8자 이상을 입력해 주세요.") String password, | ||
String name, | ||
@Pattern(regexp = "^(http|https)://[a-zA-Z0-9-.]+\\.[a-zA-Z]{2,}(/\\S*)?$", | ||
message = "url 형식을 입력해 주세요.") String url, | ||
Boolean isOptionAgr) { | ||
|
||
public static Intermediary toEntity(IntermediarySignUpRequest request, String authImage) { | ||
return Intermediary.builder() | ||
.email(request.email) | ||
.password(request.password) | ||
.name(request.name) | ||
.url(request.url) | ||
.authImage(authImage) | ||
.isOptionAgr(request.isOptionAgr) | ||
.role(IntermediaryRole.INTERMEDIARY) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,17 +76,17 @@ private MimeMessage createEmailForm(String email) throws MessagingException, Uns | |
/** | ||
* 메일 전송 | ||
*/ | ||
public EmailResponse sendEmail(EmailRequest emailRequest) throws BadRequestException { | ||
public EmailResponse sendEmail(EmailRequest request) throws BadRequestException { | ||
// 이메일 중복 검사 | ||
if (volunteerRepository.existsByEmail(emailRequest.email())) { | ||
if (volunteerRepository.existsByEmail(request.email())) { | ||
throw new BadRequestException(ALREADY_EXIST_EMAIL); | ||
} | ||
if (intermediaryRepository.existsByEmail(emailRequest.email())) { | ||
if (intermediaryRepository.existsByEmail(request.email())) { | ||
throw new BadRequestException(ALREADY_EXIST_EMAIL); | ||
} | ||
try{ | ||
// 메일전송에 필요한 정보 설정 | ||
MimeMessage emailForm = createEmailForm(emailRequest.email()); | ||
MimeMessage emailForm = createEmailForm(request.email()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 보니까 request dto 파라미터명을 request로 전부 수정했네요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 테스트 코드를 작성하다가 들었던 생각인데! dto에 넣을 request 이름을 개별 메소드마다 다르게 지정할 때 변경해야 하는 번거로움이 있더라고요! request 앞에는 사용할 Dto record의 이름이 들어가니까 괜찮다고 판단해서 바꿨습니다! |
||
emailSender.send(emailForm); | ||
return new EmailResponse(authNum); | ||
}catch (UnsupportedEncodingException | MessagingException e){ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request, file 한 번에 받는 형식 잘 구현한 것 같습니다 👍