From 9d8ad90180a01b3e44600bbe1a480f544dbe574f Mon Sep 17 00:00:00 2001 From: Lee SeungHeon <51286325+dev-Crayon@users.noreply.github.com> Date: Sun, 30 Jun 2024 10:28:44 +0900 Subject: [PATCH 1/4] Update README.md --- README.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 660b835..9cf97fd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,30 @@ -# SobokSobok-Server -SobokSobok server with Java, Spring + +## 프로젝트 +# 소복소복 + +> 소중한 사람과 함께하는 복약 체크 서비스 💊 +### 👉 [API 명세서 링크](https://www.notion.so/baejiann120/API-6280231150ca40eeb2de46beb5292931) + +
+ +## 💭 프로젝트 설명 + +> 여러분은 소중한 사람의 건강을 지키기 위해 어떤 노력을 하고 계신가요? +> +> 걱정되는 마음은 있지만, 막상 내가 매일 무언가 행동하는 건 쉽지 않죠. +> 일상이 바쁜 당신을 위해서 소복소복이 여러분의 일을 줄여드려요. +> 소복소복에서는 소중한 사람이 약을 제 때 먹었는지 직접 물어보지 않고도 체크할 수 있거든요. +> +> **나의 복약 체크는 물론, 소중한 사람의 복약까지 확인할 수 있는 ‘소복소복’** +> **우리의 건강을 챙기는 매일의 실천입니다** 🙂 + +
+ +## 💭 프로젝트 핵심 기능 + +- 메인 나의 복약을 체크하고, 상대방이 보내준 응원스티커를 확인할 수 있습니다. +- 공유 소중한 사람의 복약 캘린더를 확인하고, 응원을 보낼 수 있습니다. +- 알림 캘린더 공유 요청과 전송받은 복약 정보를 확인할 수 있습니다. +- 약 추가 내 복약 정보를 추가하고, 소중한 사람에게 복약 일정을 전송할 수 있습니다. + + From c3f37a7b5cad2a10eff6c92673a7a6216d8c1189 Mon Sep 17 00:00:00 2001 From: Lee SeungHeon <51286325+dev-Crayon@users.noreply.github.com> Date: Sun, 30 Jun 2024 10:29:54 +0900 Subject: [PATCH 2/4] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 9cf97fd..923918a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ # 소복소복 > 소중한 사람과 함께하는 복약 체크 서비스 💊 -### 👉 [API 명세서 링크](https://www.notion.so/baejiann120/API-6280231150ca40eeb2de46beb5292931)
From dc2e72322dfa9bfdc1e0d628244521cf22c68227 Mon Sep 17 00:00:00 2001 From: Lee SeungHeon <51286325+dev-Crayon@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:29:28 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[Feat]:=20AWS=20SQS=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?(#142)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SQS 관련 설정 파일 생성 및 구현 application.yml 설정 Related to: #141 --- build.gradle | 4 ++ .../io/sobok/SobokSobok/config/SQSConfig.java | 45 +++++++++++++++++++ .../external/aws/sqs/SQSMessageSender.java | 26 +++++++++++ .../aws/sqs/SQSPushNotificationRequest.java | 11 +++++ 4 files changed, 86 insertions(+) create mode 100644 src/main/java/io/sobok/SobokSobok/config/SQSConfig.java create mode 100644 src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java create mode 100644 src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java diff --git a/build.gradle b/build.gradle index e1a6dc3..f2f0577 100644 --- a/build.gradle +++ b/build.gradle @@ -57,6 +57,10 @@ dependencies { // Health Check implementation 'org.springframework.boot:spring-boot-starter-actuator' + + // AWS + implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1") + implementation 'io.awspring.cloud:spring-cloud-aws-starter-sqs' } tasks.named('bootBuildImage') { diff --git a/src/main/java/io/sobok/SobokSobok/config/SQSConfig.java b/src/main/java/io/sobok/SobokSobok/config/SQSConfig.java new file mode 100644 index 0000000..89599f1 --- /dev/null +++ b/src/main/java/io/sobok/SobokSobok/config/SQSConfig.java @@ -0,0 +1,45 @@ +package io.sobok.SobokSobok.config; + +import io.awspring.cloud.sqs.operations.SqsTemplate; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.sqs.SqsAsyncClient; + +@Configuration +public class SQSConfig { + + @Value("${spring.cloud.aws.credentials.access-key}") + private String AWS_ACCESS_KEY; + + @Value("${spring.cloud.aws.credentials.secret-key}") + private String AWS_SECRET_KEY; + + @Value("${spring.cloud.aws.region.static}") + private String AWS_REGION; + + @Bean + public SqsAsyncClient sqsAsyncClient() { + return SqsAsyncClient.builder() + .credentialsProvider(() -> new AwsCredentials() { + @Override + public String accessKeyId() { + return AWS_ACCESS_KEY; + } + + @Override + public String secretAccessKey() { + return AWS_SECRET_KEY; + } + }) + .region(Region.of(AWS_REGION)) + .build(); + } + + @Bean + public SqsTemplate sqsTemplate() { + return SqsTemplate.newTemplate(sqsAsyncClient()); + } +} diff --git a/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java new file mode 100644 index 0000000..82691b7 --- /dev/null +++ b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSMessageSender.java @@ -0,0 +1,26 @@ +package io.sobok.SobokSobok.external.aws.sqs; + +import io.awspring.cloud.sqs.operations.SendResult; +import io.awspring.cloud.sqs.operations.SqsTemplate; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import software.amazon.awssdk.services.sqs.SqsAsyncClient; + +@Component +public class SQSMessageSender { + + private final SqsTemplate queueMessagingTemplate; + + @Value("${spring.cloud.aws.sqs.name}") + private String QUEUE_NAME; + + public SQSMessageSender(SqsAsyncClient sqsAsyncClient) { + this.queueMessagingTemplate = SqsTemplate.newTemplate(sqsAsyncClient); + } + + public SendResult sendMessage(SQSPushNotificationRequest request) { + return queueMessagingTemplate.send(to -> to + .queue(QUEUE_NAME) + .payload(request)); + } +} diff --git a/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java new file mode 100644 index 0000000..0e630e4 --- /dev/null +++ b/src/main/java/io/sobok/SobokSobok/external/aws/sqs/SQSPushNotificationRequest.java @@ -0,0 +1,11 @@ +package io.sobok.SobokSobok.external.aws.sqs; + +public record SQSPushNotificationRequest( + + String deviceToken, + + String title, + + String content +) { +} From 0d39410ca1cf5882b0ad9ff63ce85b6068d46c10 Mon Sep 17 00:00:00 2001 From: Lee SeungHeon <51286325+dev-Crayon@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:14:21 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[Feat]:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=B0=8F=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C?= =?UTF-8?q?=20platform=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#144)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit iOS, ANDROID 구분용 필드 추가 Related to: #143 --- .../SobokSobok/auth/application/SocialService.java | 5 +++++ .../io/sobok/SobokSobok/auth/domain/Platform.java | 11 +++++++++++ .../java/io/sobok/SobokSobok/auth/domain/User.java | 11 ++++++++++- .../io/sobok/SobokSobok/auth/ui/AuthController.java | 8 ++++++-- .../SobokSobok/auth/ui/dto/SocialLoginRequest.java | 8 +++++++- .../SobokSobok/auth/ui/dto/SocialSignupRequest.java | 8 +++++++- 6 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java diff --git a/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java b/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java index 318a810..be6c113 100644 --- a/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java +++ b/src/main/java/io/sobok/SobokSobok/auth/application/SocialService.java @@ -44,6 +44,7 @@ public SocialSignupResponse signup(SocialSignupRequest request) { .build()) .deviceToken(request.deviceToken()) .roles(Role.USER.name()) + .platform(request.platform()) .build()); Jwt jwt = jwtProvider.getUserJwt(signupUser.getSocialInfo().getSocialId()); @@ -69,6 +70,10 @@ public SocialLoginResponse login(SocialLoginRequest request) { loginUser.updateDeviceToken(request.deviceToken()); } + if (!request.platform().equals(loginUser.getPlatform())) { + loginUser.updatePlatform(request.platform()); + } + Jwt jwt = jwtProvider.getUserJwt(loginUser.getSocialInfo().getSocialId()); return SocialLoginResponse.builder() diff --git a/src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java b/src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java new file mode 100644 index 0000000..af26e23 --- /dev/null +++ b/src/main/java/io/sobok/SobokSobok/auth/domain/Platform.java @@ -0,0 +1,11 @@ +package io.sobok.SobokSobok.auth.domain; + +import lombok.Getter; + +@Getter +public enum Platform { + + iOS, + ANDROID, + ; +} diff --git a/src/main/java/io/sobok/SobokSobok/auth/domain/User.java b/src/main/java/io/sobok/SobokSobok/auth/domain/User.java index d6d91b7..0f719a9 100644 --- a/src/main/java/io/sobok/SobokSobok/auth/domain/User.java +++ b/src/main/java/io/sobok/SobokSobok/auth/domain/User.java @@ -49,12 +49,17 @@ public class User extends BaseEntity implements UserDetails { @Column private String leaveReason; + @Column + @Enumerated(EnumType.STRING) + private Platform platform; + @Builder - public User(String username, SocialInfo socialInfo, String deviceToken, String roles) { + public User(String username, SocialInfo socialInfo, String deviceToken, String roles, Platform platform) { this.username = username; this.socialInfo = socialInfo; this.deviceToken = deviceToken; this.roles = roles; + this.platform = platform; } public void updateDeviceToken(String newDeviceToken) { @@ -65,6 +70,10 @@ public void changeUsername(String username) { this.username = username; } + public void updatePlatform(Platform platform) { + this.platform = platform; + } + public void deleteUser(String leaveReason) { this.deviceToken = null; this.username = null; diff --git a/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java b/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java index 9219c88..d7c40ee 100644 --- a/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java +++ b/src/main/java/io/sobok/SobokSobok/auth/ui/AuthController.java @@ -2,6 +2,7 @@ import io.sobok.SobokSobok.auth.application.AuthService; import io.sobok.SobokSobok.auth.application.SocialService; +import io.sobok.SobokSobok.auth.domain.Platform; import io.sobok.SobokSobok.auth.domain.User; import io.sobok.SobokSobok.auth.ui.dto.*; import io.sobok.SobokSobok.common.dto.ApiResponse; @@ -9,6 +10,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -48,8 +50,9 @@ public ResponseEntity> signup( ) public ResponseEntity> login( @RequestParam final String socialId, - @RequestParam final String deviceToken - ) { + @RequestParam final String deviceToken, + @RequestParam final Platform platform + ) { return ResponseEntity .status(HttpStatus.OK) @@ -58,6 +61,7 @@ public ResponseEntity> login( socialService.login(SocialLoginRequest.builder() .socialId(socialId) .deviceToken(deviceToken) + .platform(platform) .build()) )); } diff --git a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java index ab6f111..c8640f7 100644 --- a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java +++ b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialLoginRequest.java @@ -1,6 +1,8 @@ package io.sobok.SobokSobok.auth.ui.dto; +import io.sobok.SobokSobok.auth.domain.Platform; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Builder; @Builder @@ -10,6 +12,10 @@ public record SocialLoginRequest( String socialId, @Schema(requiredMode = Schema.RequiredMode.REQUIRED) - String deviceToken + String deviceToken, + + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull + Platform platform ) { } diff --git a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java index dce7b20..e8b391a 100644 --- a/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java +++ b/src/main/java/io/sobok/SobokSobok/auth/ui/dto/SocialSignupRequest.java @@ -1,7 +1,9 @@ package io.sobok.SobokSobok.auth.ui.dto; +import io.sobok.SobokSobok.auth.domain.Platform; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; public record SocialSignupRequest( @@ -15,6 +17,10 @@ public record SocialSignupRequest( @Schema(requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank - String deviceToken + String deviceToken, + + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull + Platform platform ) { }