From 7ecbc20890b92ca49da49b2521cb1557ad31b99a Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:36:26 +0900 Subject: [PATCH 01/20] =?UTF-8?q?docs:=20s3=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8304cf69..f8f17edb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,4 +36,16 @@ logging: hibernate: orm: jdbc: - bind: trace \ No newline at end of file + bind: trace +cloud: + aws: + s3: + bucket: ${CLOUD_AWS_S3_BUCKET_NAME} + credentials: + access-key: ${CLOUD_AWS_CREDENTIALS_ACCESS_KEY} + secret-key: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} + region: + static: ${CLOUD_AWS_REGION_STATIC} + auto: false + stack: + auto: false From a394781925479ad9db13e04db228c903df62039b Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:37:30 +0900 Subject: [PATCH 02/20] =?UTF-8?q?refactor:=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=20=EC=A0=91=EA=B7=BC=EC=A7=80=EC=8B=9C=EC=9E=90=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD,=20=EB=A7=A4=EC=A7=81=20=EB=84=98=EB=B2=84=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/coffeemeet/server/user/domain/Birth.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/coffeemeet/server/user/domain/Birth.java b/src/main/java/coffeemeet/server/user/domain/Birth.java index 506fe396..e772f1db 100644 --- a/src/main/java/coffeemeet/server/user/domain/Birth.java +++ b/src/main/java/coffeemeet/server/user/domain/Birth.java @@ -2,21 +2,22 @@ import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.util.StringUtils; @Getter @Embeddable -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Birth { private static final int BIRTH_LENGTH = 4; - @Column(nullable = false, length = 4) + @Column(nullable = false, length = BIRTH_LENGTH) String year; - @Column(nullable = false, length = 4) + @Column(nullable = false, length = BIRTH_LENGTH) String day; public Birth(String year, String day) { From 18b42af1d2df0ac1cb63ab9ca011a02946c0bf3f Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:37:52 +0900 Subject: [PATCH 03/20] =?UTF-8?q?chore:=20cloud=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 903c2868..b6e90037 100644 --- a/build.gradle +++ b/build.gradle @@ -65,9 +65,12 @@ dependencies { /* Docs & UI */ testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' - testImplementation "com.epages:restdocs-api-spec-mockmvc:${restdocsApiSpecVersion}" + testImplementation 'com.epages:restdocs-api-spec-mockmvc:${restdocsApiSpecVersion}' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' swaggerUI 'org.webjars:swagger-ui:4.11.1' + + /* Cloud */ + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' } tasks.named('test') { From eabc8d04995f0b2e501f2d08bd234e953f718d42 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:39:45 +0900 Subject: [PATCH 04/20] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=B3=B8=EA=B0=92?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD,=20AttributeOv?= =?UTF-8?q?erride=EB=A1=9C=20column=20=EC=A4=91=EB=B3=B5=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/user/domain/Certification.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/main/java/coffeemeet/server/user/domain/Certification.java b/src/main/java/coffeemeet/server/user/domain/Certification.java index 3c6b2577..4a472578 100644 --- a/src/main/java/coffeemeet/server/user/domain/Certification.java +++ b/src/main/java/coffeemeet/server/user/domain/Certification.java @@ -1,20 +1,22 @@ package coffeemeet.server.user.domain; +import jakarta.persistence.AttributeOverride; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import jakarta.persistence.Embedded; import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.util.StringUtils; @Getter @Embeddable -@NoArgsConstructor public class Certification { + private static final String DEFAULT_EMAIL = "default@default.com"; + private static final String DEFAULT = "default"; + @Embedded @Column(nullable = false) - private CompanyEmail companyEmail; + @AttributeOverride(name = "email", column = @Column(name = "company_email")) + private Email companyEmail; @Column(nullable = false) private String businessCardUrl; @@ -25,24 +27,15 @@ public class Certification { @Column(nullable = false) private String department; - public Certification(CompanyEmail companyEmail, String businessCardUrl, String department) { - validateBusinessCardUrl(businessCardUrl); - validateDepartment(department); - this.companyEmail = companyEmail; - this.businessCardUrl = businessCardUrl; - this.department = department; - } - - private void validateBusinessCardUrl(String businessCardUrl) { - if (!StringUtils.hasText(businessCardUrl)) { - throw new IllegalArgumentException("올바르지 않은 명함 url입니다."); - } + public Certification() { + this.companyEmail = new Email(DEFAULT_EMAIL); + this.businessCardUrl = DEFAULT; + this.department = DEFAULT; + isCertificated = false; } - private void validateDepartment(String department) { - if (!StringUtils.hasText(department)) { - throw new IllegalArgumentException("올바르지 않은 부서 이름입니다."); - } + public void updateBusinessCardUrl(String newBusinessCardUrl) { + this.businessCardUrl = newBusinessCardUrl; } public void certificate() { From 02d7de179cc47a04432eeade26d92834fedae079 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:40:02 +0900 Subject: [PATCH 05/20] =?UTF-8?q?refactor:=20CompanyEmail=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/user/domain/CompanyEmail.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/main/java/coffeemeet/server/user/domain/CompanyEmail.java diff --git a/src/main/java/coffeemeet/server/user/domain/CompanyEmail.java b/src/main/java/coffeemeet/server/user/domain/CompanyEmail.java deleted file mode 100644 index a9522bfe..00000000 --- a/src/main/java/coffeemeet/server/user/domain/CompanyEmail.java +++ /dev/null @@ -1,26 +0,0 @@ -package coffeemeet.server.user.domain; - -import coffeemeet.server.common.util.Patterns; -import jakarta.persistence.Embeddable; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Embeddable -@NoArgsConstructor -public class CompanyEmail { - - private String companyEmail; - - public CompanyEmail(String companyEmail) { - validateCompanyEmail(companyEmail); - this.companyEmail = companyEmail; - } - - private void validateCompanyEmail(String companyEmail) { - if (!Patterns.EMAIL_PATTERN.matcher(companyEmail).matches()) { - throw new IllegalArgumentException("올바르지 않은 이메일입니다."); - } - } - -} From f9f8e354a9244db3f292c70431dd23d1fbc5ef4c Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:40:49 +0900 Subject: [PATCH 06/20] =?UTF-8?q?refactor:=20=EC=A0=91=EA=B7=BC=EC=A7=80?= =?UTF-8?q?=EC=8B=9C=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/coffeemeet/server/user/domain/Email.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/coffeemeet/server/user/domain/Email.java b/src/main/java/coffeemeet/server/user/domain/Email.java index 14cd302e..e52f12d3 100644 --- a/src/main/java/coffeemeet/server/user/domain/Email.java +++ b/src/main/java/coffeemeet/server/user/domain/Email.java @@ -2,12 +2,13 @@ import coffeemeet.server.common.util.Patterns; import jakarta.persistence.Embeddable; +import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @Embeddable -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Email { private String email; From 1673e63e832bdd0ecf1d7b623d8111650ac6a02b Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:41:13 +0900 Subject: [PATCH 07/20] =?UTF-8?q?refactor:=20=EC=A0=91=EA=B7=BC=EC=A7=80?= =?UTF-8?q?=EC=8B=9C=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/coffeemeet/server/user/domain/OAuthInfo.java | 3 ++- src/main/java/coffeemeet/server/user/domain/Profile.java | 3 ++- .../java/coffeemeet/server/user/domain/ReportInfo.java | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/coffeemeet/server/user/domain/OAuthInfo.java b/src/main/java/coffeemeet/server/user/domain/OAuthInfo.java index da841c4c..16055bbe 100644 --- a/src/main/java/coffeemeet/server/user/domain/OAuthInfo.java +++ b/src/main/java/coffeemeet/server/user/domain/OAuthInfo.java @@ -3,13 +3,14 @@ import jakarta.persistence.Embeddable; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.util.StringUtils; @Getter @Embeddable -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class OAuthInfo { @Enumerated(value = EnumType.STRING) diff --git a/src/main/java/coffeemeet/server/user/domain/Profile.java b/src/main/java/coffeemeet/server/user/domain/Profile.java index 10aaa25a..97b82806 100644 --- a/src/main/java/coffeemeet/server/user/domain/Profile.java +++ b/src/main/java/coffeemeet/server/user/domain/Profile.java @@ -3,6 +3,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import jakarta.persistence.Embedded; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,7 +11,7 @@ @Getter @Embeddable -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Profile { private static final int NICKNAME_MAX_LENGTH = 20; diff --git a/src/main/java/coffeemeet/server/user/domain/ReportInfo.java b/src/main/java/coffeemeet/server/user/domain/ReportInfo.java index cee774c8..1bf0c209 100644 --- a/src/main/java/coffeemeet/server/user/domain/ReportInfo.java +++ b/src/main/java/coffeemeet/server/user/domain/ReportInfo.java @@ -3,15 +3,16 @@ import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import java.time.LocalDateTime; +import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @Embeddable -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class ReportInfo { - private static final int REPORT_COUNT_MIN_LENGTH = 0; + private static final int REPORT_MIN_COUNT = 0; @Column(nullable = false) private int reportedCount; @@ -27,13 +28,13 @@ public ReportInfo(int reportedCount, LocalDateTime sanctionPeriod) { } private void validateReportedCount(int reportedCount) { - if (reportedCount < 0) { + if (reportedCount < REPORT_MIN_COUNT) { throw new IllegalArgumentException("올바르지 않은 신고횟수입니다."); } } private void validateSanctionPeriod(LocalDateTime sanctionPeriod) { - if (sanctionPeriod != null) { + if (sanctionPeriod == null) { throw new IllegalArgumentException("올바르지 않은 제재 기간입니다."); } } From 051155345a19888f15b1791bda713e53e34674cf Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:41:55 +0900 Subject: [PATCH 08/20] =?UTF-8?q?feat:=20=EB=AA=85=ED=95=A8=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/coffeemeet/server/user/domain/User.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/coffeemeet/server/user/domain/User.java b/src/main/java/coffeemeet/server/user/domain/User.java index b7e9f0f5..3cef5706 100644 --- a/src/main/java/coffeemeet/server/user/domain/User.java +++ b/src/main/java/coffeemeet/server/user/domain/User.java @@ -57,4 +57,8 @@ public User( this.profile = profile; } + public void updateBusinessCardUrl(String newBusinessCardUrl) { + certification.updateBusinessCardUrl(newBusinessCardUrl); + } + } From cee7e4d112c5b7eb6e94d0dc01d7d4a2bff9de67 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:42:51 +0900 Subject: [PATCH 09/20] =?UTF-8?q?feat:=20s3=20=ED=82=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/BusinessCardS3KeyGenerator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/coffeemeet/server/certification/service/BusinessCardS3KeyGenerator.java diff --git a/src/main/java/coffeemeet/server/certification/service/BusinessCardS3KeyGenerator.java b/src/main/java/coffeemeet/server/certification/service/BusinessCardS3KeyGenerator.java new file mode 100644 index 00000000..052bf629 --- /dev/null +++ b/src/main/java/coffeemeet/server/certification/service/BusinessCardS3KeyGenerator.java @@ -0,0 +1,14 @@ +package coffeemeet.server.certification.service; + +import java.time.LocalDateTime; +import java.util.UUID; +import org.springframework.stereotype.Service; + +@Service +public class BusinessCardS3KeyGenerator { + + public String generate() { + return String.format("BusinessCard-%s-%s", LocalDateTime.now(), UUID.randomUUID()); + } + +} From 9dda8b47a7541f95ba87b2fdd7d9895b88fe11b4 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:43:25 +0900 Subject: [PATCH 10/20] =?UTF-8?q?feat:=20s3=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/common/config/S3Config.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/coffeemeet/server/common/config/S3Config.java diff --git a/src/main/java/coffeemeet/server/common/config/S3Config.java b/src/main/java/coffeemeet/server/common/config/S3Config.java new file mode 100644 index 00000000..67f8409a --- /dev/null +++ b/src/main/java/coffeemeet/server/common/config/S3Config.java @@ -0,0 +1,37 @@ +package coffeemeet.server.common.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +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 { + + private final String accessKey; + private final String secretKey; + private final String region; + + public S3Config( + @Value("${cloud.aws.credentials.access-key}") String accessKey, + @Value("${cloud.aws.credentials.secret-key}") String secretKey, + @Value("${cloud.aws.region.static}") String region) { + this.accessKey = accessKey; + this.secretKey = secretKey; + this.region = region; + } + + @Bean + public AmazonS3 amazonS3Client() { + BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder + .standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .build(); + } + +} From b8cdb87a7049bd77d8d10ea61b69c3dc8aee0dc7 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:45:40 +0900 Subject: [PATCH 11/20] =?UTF-8?q?feat:=20s3=20upload,=20delete,=20getUrl?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/common/media/S3MediaService.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/java/coffeemeet/server/common/media/S3MediaService.java diff --git a/src/main/java/coffeemeet/server/common/media/S3MediaService.java b/src/main/java/coffeemeet/server/common/media/S3MediaService.java new file mode 100644 index 00000000..0d0f5932 --- /dev/null +++ b/src/main/java/coffeemeet/server/common/media/S3MediaService.java @@ -0,0 +1,34 @@ +package coffeemeet.server.common.media; + +import com.amazonaws.services.s3.AmazonS3; +import java.io.File; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class S3MediaService { + + private final AmazonS3 amazonS3; + private final String bucketName; + + public S3MediaService( + AmazonS3 amazonS3, + @Value("${cloud.aws.s3.bucket}") String bucketName + ) { + this.amazonS3 = amazonS3; + this.bucketName = bucketName; + } + + public void upload(String key, File file) { + amazonS3.putObject(bucketName, key, file); + } + + public void delete(String key) { + amazonS3.deleteObject(bucketName, key); + } + + public String getUrl(String key) { + return amazonS3.getUrl(bucketName, key).toExternalForm(); + } + +} From 17197a1e4c53f8a8a9ef50dc056432c96a0eb1ea Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:47:50 +0900 Subject: [PATCH 12/20] =?UTF-8?q?feat:=20File=20=EB=B3=80=ED=99=98=20?= =?UTF-8?q?=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20Util=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/common/util/FileUtils.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/coffeemeet/server/common/util/FileUtils.java diff --git a/src/main/java/coffeemeet/server/common/util/FileUtils.java b/src/main/java/coffeemeet/server/common/util/FileUtils.java new file mode 100644 index 00000000..caf7f615 --- /dev/null +++ b/src/main/java/coffeemeet/server/common/util/FileUtils.java @@ -0,0 +1,42 @@ +package coffeemeet.server.common.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class FileUtils { + + private static final String MULTIPART_FILE_TRANSFER_ERROR = "MULTIPART FILE을 FILE로 변환 중 오류가 발생했습니다."; + private static final String FILE_DELETE_ERROR = "FILE 삭제 중 오류가 발생했습니다."; + + public static class FileIOException extends RuntimeException { + + public FileIOException(String message, Throwable e) { + super(message, e); + } + + } + + public static File convertMultipartFileToFile(MultipartFile multipartFile) { + try { + File file = File.createTempFile("temp", multipartFile.getOriginalFilename()); + multipartFile.transferTo(file); + return file; + } catch (IOException e) { + throw new FileIOException(MULTIPART_FILE_TRANSFER_ERROR, e); + } + } + + public static void delete(File file) { + try { + Files.delete(file.toPath()); + } catch (IOException e) { + throw new FileIOException(FILE_DELETE_ERROR, e); + } + } + +} From b42e405db4e612db807a597657ac7f19e4d4c948 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:48:16 +0900 Subject: [PATCH 13/20] =?UTF-8?q?feat:=20=EB=AA=85=ED=95=A8=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/user/service/UserService.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/coffeemeet/server/user/service/UserService.java diff --git a/src/main/java/coffeemeet/server/user/service/UserService.java b/src/main/java/coffeemeet/server/user/service/UserService.java new file mode 100644 index 00000000..9502914a --- /dev/null +++ b/src/main/java/coffeemeet/server/user/service/UserService.java @@ -0,0 +1,23 @@ +package coffeemeet.server.user.service; + +import coffeemeet.server.user.domain.User; +import coffeemeet.server.user.repository.UserRepository; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserRepository userRepository; + + @Transactional + public void updateBusinessCardUrl(Long userId, String businessCardUrl) { + User user = userRepository.findById(userId) + .orElseThrow(EntityNotFoundException::new); // 에러 어떻게 처리할꺼임? + user.updateBusinessCardUrl(businessCardUrl); + } + +} From ad808905c3d23938729a77e8403c6729945f1cb3 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:49:29 +0900 Subject: [PATCH 14/20] =?UTF-8?q?feat:=20=EB=AA=85=ED=95=A8=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20controller=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CertificationController.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/coffeemeet/server/certification/controller/CertificationController.java diff --git a/src/main/java/coffeemeet/server/certification/controller/CertificationController.java b/src/main/java/coffeemeet/server/certification/controller/CertificationController.java new file mode 100644 index 00000000..59eb9616 --- /dev/null +++ b/src/main/java/coffeemeet/server/certification/controller/CertificationController.java @@ -0,0 +1,38 @@ +package coffeemeet.server.certification.controller; + +import static org.springframework.http.HttpStatus.CREATED; + +import coffeemeet.server.certification.service.CertificationService; +import coffeemeet.server.common.util.FileUtils; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/certification") +public class CertificationController { + + private final CertificationService certificationService; + + @PostMapping("/users/{userId}/business-card") + @ResponseStatus(CREATED) + public void uploadBusinessCard( + @PathVariable("userId") + @NotNull(message = "유저 ID는 null일 수 없습니다.") + long userId, + @RequestPart("businessCard") + @NotNull(message = "명함 이미지는 null일 수 없습니다.") + MultipartFile businessCard + ) { + certificationService.uploadBusinessCard(userId, + FileUtils.convertMultipartFileToFile(businessCard)); + } + +} From efa39214dab2a385a1d79a78f6d89f018874f6ed Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 10:49:51 +0900 Subject: [PATCH 15/20] =?UTF-8?q?feat:=20=EB=AA=85=ED=95=A8=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20service=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CertificationService.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/coffeemeet/server/certification/service/CertificationService.java diff --git a/src/main/java/coffeemeet/server/certification/service/CertificationService.java b/src/main/java/coffeemeet/server/certification/service/CertificationService.java new file mode 100644 index 00000000..61b9831c --- /dev/null +++ b/src/main/java/coffeemeet/server/certification/service/CertificationService.java @@ -0,0 +1,26 @@ +package coffeemeet.server.certification.service; + +import coffeemeet.server.common.media.S3MediaService; +import coffeemeet.server.common.util.FileUtils; +import coffeemeet.server.user.service.UserService; +import java.io.File; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CertificationService { + + private final S3MediaService s3MediaService; + private final UserService userService; + private final BusinessCardS3KeyGenerator businessCardS3KeyGenerator; + + public void uploadBusinessCard(long userId, File file) { + String key = businessCardS3KeyGenerator.generate(); + + s3MediaService.upload(key, file); + userService.updateBusinessCardUrl(userId, s3MediaService.getUrl(key)); + + FileUtils.delete(file); + } +} From 237ccbac81907b98e0d7878307637751eac4a95c Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 11:03:28 +0900 Subject: [PATCH 16/20] =?UTF-8?q?chore:=20=EC=8C=8D=EB=94=B0=EC=98=B4?= =?UTF-8?q?=ED=91=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 158 +++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/build.gradle b/build.gradle index b6e90037..4cecab6f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,119 +1,119 @@ import org.hidetake.gradle.swagger.generator.GenerateSwaggerUI buildscript { - ext { - restdocsApiSpecVersion = '0.18.3' // restdocsApiSpecVersion 버전 변수 설정 - } + ext { + restdocsApiSpecVersion = '0.18.3' // restdocsApiSpecVersion 버전 변수 설정 + } } plugins { - id 'java' - id 'org.springframework.boot' version '3.1.4' - id 'io.spring.dependency-management' version '1.1.3' - id 'com.epages.restdocs-api-spec' version "${restdocsApiSpecVersion}" - id 'org.hidetake.swagger.generator' version '2.18.2' + id 'java' + id 'org.springframework.boot' version '3.1.4' + id 'io.spring.dependency-management' version '1.1.3' + id 'com.epages.restdocs-api-spec' version "${restdocsApiSpecVersion}" + id 'org.hidetake.swagger.generator' version '2.18.2' } group = 'coffee-meet' version = '0.0.1-SNAPSHOT' java { - sourceCompatibility = '17' + sourceCompatibility = '17' } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } ext { - set('snippetsDir', file("build/generated-snippets")) + set('snippetsDir', file("build/generated-snippets")) } dependencies { - /* Database */ - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-data-redis' - runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'com.h2database:h2' - - /* Spring */ - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - - /* JWT */ - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' - implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' - - /* Lombok */ - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - - /* Test */ - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation group: 'org.instancio', name: 'instancio-junit', version: '3.0.0' - - /* TestContainer */ - testImplementation "org.testcontainers:testcontainers:1.19.0" - testImplementation "org.testcontainers:junit-jupiter:1.19.0" - - /* Docs & UI */ - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' - testImplementation 'com.epages:restdocs-api-spec-mockmvc:${restdocsApiSpecVersion}' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' - swaggerUI 'org.webjars:swagger-ui:4.11.1' - - /* Cloud */ - implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + /* Database */ + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'com.h2database:h2' + + /* Spring */ + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + + /* JWT */ + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' + implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' + implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' + + /* Lombok */ + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + /* Test */ + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation group: 'org.instancio', name: 'instancio-junit', version: '3.0.0' + + /* TestContainer */ + testImplementation "org.testcontainers:testcontainers:1.19.0" + testImplementation "org.testcontainers:junit-jupiter:1.19.0" + + /* Docs & UI */ + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + testImplementation "com.epages:restdocs-api-spec-mockmvc:${restdocsApiSpecVersion}" + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' + swaggerUI 'org.webjars:swagger-ui:4.11.1' + + /* Cloud */ + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } swaggerSources { - sample { - setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml")) - } + sample { + setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml")) + } } openapi3 { - servers = [ - { url = "http://localhost:8080" }, - { url = "http://13.209.253.204:8080" } - ] - title = "API 문서" - description = "RestDocsWithSwagger Docs" - version = "0.0.1" - format = "yaml" + servers = [ + { url = "http://localhost:8080" }, + { url = "http://13.209.253.204:8080" } + ] + title = "API 문서" + description = "RestDocsWithSwagger Docs" + version = "0.0.1" + format = "yaml" } tasks.withType(GenerateSwaggerUI) { - dependsOn 'openapi3' - doFirst { - def swaggerUIFile = file("${openapi3.outputDirectory}/openapi3.yaml") - - def securitySchemesContent = " securitySchemes:\n" + \ - " APIKey:\n" + \ - " type: apiKey\n" + \ - " name: Authorization\n" + \ - " in: header\n" + \ - "security:\n" + - " - APIKey: [] # Apply the security scheme here" - - swaggerUIFile.append securitySchemesContent - } + dependsOn 'openapi3' + doFirst { + def swaggerUIFile = file("${openapi3.outputDirectory}/openapi3.yaml") + + def securitySchemesContent = " securitySchemes:\n" + \ + " APIKey:\n" + \ + " type: apiKey\n" + \ + " name: Authorization\n" + \ + " in: header\n" + \ + "security:\n" + + " - APIKey: [] # Apply the security scheme here" + + swaggerUIFile.append securitySchemesContent + } } bootJar { - dependsOn generateSwaggerUISample - from("${generateSwaggerUISample.outputDir}") { - into 'static/docs' - } + dependsOn generateSwaggerUISample + from("${generateSwaggerUISample.outputDir}") { + into 'static/docs' + } } From afd0f7f0e4fdf6962b72026c5c7c5122a3f5ad1a Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 11:57:18 +0900 Subject: [PATCH 17/20] =?UTF-8?q?refactor:=20CompanyEmail=20=EC=9E=AC?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=20=EB=82=B4=EB=B6=80=EC=97=90=20=ED=9A=8C?= =?UTF-8?q?=EC=82=AC=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/user/domain/CompanyEmail.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/coffeemeet/server/user/domain/CompanyEmail.java diff --git a/src/main/java/coffeemeet/server/user/domain/CompanyEmail.java b/src/main/java/coffeemeet/server/user/domain/CompanyEmail.java new file mode 100644 index 00000000..a9522bfe --- /dev/null +++ b/src/main/java/coffeemeet/server/user/domain/CompanyEmail.java @@ -0,0 +1,26 @@ +package coffeemeet.server.user.domain; + +import coffeemeet.server.common.util.Patterns; +import jakarta.persistence.Embeddable; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Embeddable +@NoArgsConstructor +public class CompanyEmail { + + private String companyEmail; + + public CompanyEmail(String companyEmail) { + validateCompanyEmail(companyEmail); + this.companyEmail = companyEmail; + } + + private void validateCompanyEmail(String companyEmail) { + if (!Patterns.EMAIL_PATTERN.matcher(companyEmail).matches()) { + throw new IllegalArgumentException("올바르지 않은 이메일입니다."); + } + } + +} From 5a80ad25c29be5473ceb7c16c70de18d63fe21c4 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 11:57:35 +0900 Subject: [PATCH 18/20] =?UTF-8?q?refactor:=20BaseEntity=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/coffeemeet/server/admin/domain/Admin.java | 4 +++- src/main/java/coffeemeet/server/report/domain/Report.java | 3 ++- src/main/java/coffeemeet/server/user/domain/User.java | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/coffeemeet/server/admin/domain/Admin.java b/src/main/java/coffeemeet/server/admin/domain/Admin.java index 2f122938..c5f4341c 100644 --- a/src/main/java/coffeemeet/server/admin/domain/Admin.java +++ b/src/main/java/coffeemeet/server/admin/domain/Admin.java @@ -1,5 +1,6 @@ package coffeemeet.server.admin.domain; +import coffeemeet.server.common.entity.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; @@ -12,7 +13,7 @@ @Getter @Table(name = "admins") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Admin { +public class Admin extends BaseEntity { @Id @Column(nullable = false) @@ -20,4 +21,5 @@ public class Admin { @Column(nullable = false) private String password; + } diff --git a/src/main/java/coffeemeet/server/report/domain/Report.java b/src/main/java/coffeemeet/server/report/domain/Report.java index 1e1259f6..1ec564b5 100644 --- a/src/main/java/coffeemeet/server/report/domain/Report.java +++ b/src/main/java/coffeemeet/server/report/domain/Report.java @@ -1,5 +1,6 @@ package coffeemeet.server.report.domain; +import coffeemeet.server.common.entity.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -16,7 +17,7 @@ @Getter @Table(name = "reports") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Report { +public class Report extends BaseEntity { private static final int TITLE_MAX_LENGTH = 20; private static final int REASON_MAX_LENGTH = 200; diff --git a/src/main/java/coffeemeet/server/user/domain/User.java b/src/main/java/coffeemeet/server/user/domain/User.java index 3cef5706..811aa3d9 100644 --- a/src/main/java/coffeemeet/server/user/domain/User.java +++ b/src/main/java/coffeemeet/server/user/domain/User.java @@ -1,6 +1,7 @@ package coffeemeet.server.user.domain; import coffeemeet.server.chatting_room.domain.ChattingRoom; +import coffeemeet.server.common.entity.AdvancedBaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; @@ -20,7 +21,7 @@ @Table(name = "users") @Where(clause = "is_deleted = false") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class User { +public class User extends AdvancedBaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From 267cda5bd2e03329d4da938750993252e1dec73f Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 11:59:31 +0900 Subject: [PATCH 19/20] refactor: Email -> CompanyEmail --- .../java/coffeemeet/server/user/domain/Certification.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/coffeemeet/server/user/domain/Certification.java b/src/main/java/coffeemeet/server/user/domain/Certification.java index 4a472578..e398f4b9 100644 --- a/src/main/java/coffeemeet/server/user/domain/Certification.java +++ b/src/main/java/coffeemeet/server/user/domain/Certification.java @@ -1,6 +1,5 @@ package coffeemeet.server.user.domain; -import jakarta.persistence.AttributeOverride; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import jakarta.persistence.Embedded; @@ -15,8 +14,7 @@ public class Certification { @Embedded @Column(nullable = false) - @AttributeOverride(name = "email", column = @Column(name = "company_email")) - private Email companyEmail; + private CompanyEmail companyEmail; @Column(nullable = false) private String businessCardUrl; @@ -28,7 +26,7 @@ public class Certification { private String department; public Certification() { - this.companyEmail = new Email(DEFAULT_EMAIL); + this.companyEmail = new CompanyEmail(DEFAULT_EMAIL); this.businessCardUrl = DEFAULT; this.department = DEFAULT; isCertificated = false; From 146a38abcb2ce90608a935bd511b3c46369deaa7 Mon Sep 17 00:00:00 2001 From: sangminnim Date: Mon, 23 Oct 2023 12:06:01 +0900 Subject: [PATCH 20/20] =?UTF-8?q?refactor:=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0,=20IllegalArgumentException=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/coffeemeet/server/user/service/UserService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/coffeemeet/server/user/service/UserService.java b/src/main/java/coffeemeet/server/user/service/UserService.java index 9502914a..66625ce2 100644 --- a/src/main/java/coffeemeet/server/user/service/UserService.java +++ b/src/main/java/coffeemeet/server/user/service/UserService.java @@ -2,7 +2,6 @@ import coffeemeet.server.user.domain.User; import coffeemeet.server.user.repository.UserRepository; -import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -16,7 +15,7 @@ public class UserService { @Transactional public void updateBusinessCardUrl(Long userId, String businessCardUrl) { User user = userRepository.findById(userId) - .orElseThrow(EntityNotFoundException::new); // 에러 어떻게 처리할꺼임? + .orElseThrow(IllegalArgumentException::new); user.updateBusinessCardUrl(businessCardUrl); }