Skip to content

Commit

Permalink
Merge pull request #67 from kakao-tech-campus-2nd-step3/weekly/8
Browse files Browse the repository at this point in the history
merge: 8์ฃผ์ฐจ ์ž‘์—… master์— ๋ฐ˜์˜
  • Loading branch information
peeerr authored Oct 25, 2024
2 parents 1f40cfe + aae5e7e commit 97b6bd6
Show file tree
Hide file tree
Showing 25 changed files with 530 additions and 62 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/master_weekly_cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ jobs:
distribution: 'corretto'
java-version: '21'

- name: FCM ์„œ๋น„์Šค ๊ณ„์ • ํ‚ค ํŒŒ์ผ ์ƒ์„ฑ
run: |
echo '${{ secrets.FCM_SERVICE_ACCOUNT_KEY }}' > ./src/main/resources/everymoment.json
- name: AWS S3 ๊ด€๋ จ ์ •๋ณด๋ฅผ ์„ค์ • ํŒŒ์ผ์— ์ฃผ์ž…
uses: microsoft/variable-substitution@v1
with:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/pr_weekly_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ jobs:
distribution: 'corretto'
java-version: '21'

- name: FCM ์„œ๋น„์Šค ๊ณ„์ • ํ‚ค ํŒŒ์ผ ์ƒ์„ฑ
run: |
echo '${{ secrets.FCM_SERVICE_ACCOUNT_KEY }}' > ./src/main/resources/everymoment.json
- name: AWS S3 ๊ด€๋ จ ์ •๋ณด๋ฅผ ์„ค์ • ํŒŒ์ผ์— ์ฃผ์ž…
uses: microsoft/variable-substitution@v1
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ build/
!**/src/test/**/build/

application-dev.yml
everymoment.json

### STS ###
.apt_generated
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ dependencies {
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.657'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'

implementation 'com.google.firebase:firebase-admin:9.2.0'

implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/potatocake/everymoment/config/FcmConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.potatocake.everymoment.config;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.FirebaseMessaging;
import java.io.IOException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
public class FcmConfig {

@Bean
public FirebaseMessaging firebaseMessaging() throws IOException {
GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(new ClassPathResource("everymoment.json").getInputStream());

FirebaseOptions firebaseOptions = FirebaseOptions.builder()
.setCredentials(googleCredentials)
.build();

FirebaseApp app = FirebaseApp.initializeApp(firebaseOptions);

return FirebaseMessaging.getInstance(app);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.potatocake.everymoment.constant;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum NotificationType {

COMMENT("์ƒˆ๋กœ์šด ๋Œ“๊ธ€", "%s๋‹˜์ด ํšŒ์›๋‹˜์˜ ์ผ๊ธฐ์— ๋Œ“๊ธ€์„ ๋‚จ๊ฒผ์Šต๋‹ˆ๋‹ค."),
LIKE("์ƒˆ๋กœ์šด ์ข‹์•„์š”", "%s๋‹˜์ด ํšŒ์›๋‹˜์˜ ์ผ๊ธฐ๋ฅผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค."),
FRIEND_REQUEST("์ƒˆ๋กœ์šด ์นœ๊ตฌ ์š”์ฒญ", "%s๋‹˜์ด ์นœ๊ตฌ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค."),
FRIEND_ACCEPT("์นœ๊ตฌ ์š”์ฒญ ์ˆ˜๋ฝ", "%s๋‹˜์ด ์นœ๊ตฌ ์š”์ฒญ์„ ์ˆ˜๋ฝํ–ˆ์Šต๋‹ˆ๋‹ค."),
MOOD_CHECK("์ƒˆ๋กœ์šด ์žฅ์†Œ", "ํ˜„์žฌ %s์— ๋จธ๋ฌด๋ฅด๊ณ  ์žˆ์–ด์š”! ์ง€๊ธˆ ๊ธฐ๋ถ„์€ ์–ด๋– ์‹ ๊ฐ€์š”?");

private final String title;
private final String messageFormat;

public String formatMessage(String... args) {
return String.format(messageFormat, (Object[]) args);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@ public class DiaryController {
@Operation(summary = "์ž๋™ ์ผ๊ธฐ ์ž‘์„ฑ", description = "์ž๋™์œผ๋กœ ์ผ๊ธฐ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.")
@ApiResponse(responseCode = "200", description = "์ž๋™ ์ผ๊ธฐ ์ž‘์„ฑ ์„ฑ๊ณต", content = @Content(schema = @Schema(implementation = NotificationResponse.class)))
@PostMapping("/auto")
public ResponseEntity<SuccessResponse<NotificationResponse>> createDiaryAuto(
public ResponseEntity<SuccessResponse> createDiaryAuto(
@Parameter(description = "์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด", hidden = true)
@AuthenticationPrincipal MemberDetails memberDetails,
@Parameter(description = "์ž๋™ ์ผ๊ธฐ ์ž‘์„ฑ ์ •๋ณด", required = true)
@RequestBody DiaryAutoCreateRequest diaryAutoCreateRequest) {
Long memberId = memberDetails.getId();

NotificationResponse response = diaryService.createDiaryAuto(memberId, diaryAutoCreateRequest);
diaryService.createDiaryAuto(memberId, diaryAutoCreateRequest);

return ResponseEntity.ok()
.body(SuccessResponse.ok(response));
.body(SuccessResponse.ok());
}

@Operation(summary = "์ˆ˜๊ธฐ ์ผ๊ธฐ ์ž‘์„ฑ", description = "์ˆ˜๋™์œผ๋กœ ์ผ๊ธฐ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.potatocake.everymoment.controller;

import com.potatocake.everymoment.dto.SuccessResponse;
import com.potatocake.everymoment.dto.request.FcmTokenRequest;
import com.potatocake.everymoment.security.MemberDetails;
import com.potatocake.everymoment.service.FcmService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "FCM", description = "FCM ํ† ํฐ ๊ด€๋ฆฌ API")
@RestController
@RequestMapping("/api/fcm")
@RequiredArgsConstructor
public class FcmController {

private final FcmService fcmService;

@Operation(summary = "FCM ํ† ํฐ ๋“ฑ๋ก/๊ฐฑ์‹ ", description = "๋””๋ฐ”์ด์Šค์˜ FCM ํ† ํฐ์„ ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.")
@ApiResponse(responseCode = "200", description = "ํ† ํฐ ๋“ฑ๋ก/๊ฐฑ์‹  ์„ฑ๊ณต")
@PostMapping("/token")
public ResponseEntity<SuccessResponse> registerToken(
@Parameter(description = "์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด", hidden = true)
@AuthenticationPrincipal MemberDetails memberDetails,
@Parameter(description = "FCM ํ† ํฐ ์ •๋ณด", required = true)
@RequestBody @Valid FcmTokenRequest request) {

fcmService.registerToken(memberDetails.getId(), request.getDeviceId(), request.getFcmToken());

return ResponseEntity.ok()
.body(SuccessResponse.ok());
}

@Operation(summary = "FCM ํ† ํฐ ์‚ญ์ œ", description = "๋””๋ฐ”์ด์Šค์˜ FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.")
@ApiResponse(responseCode = "200", description = "ํ† ํฐ ์‚ญ์ œ ์„ฑ๊ณต")
@DeleteMapping("/token")
public ResponseEntity<SuccessResponse> removeToken(
@Parameter(description = "์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด", hidden = true)
@AuthenticationPrincipal MemberDetails memberDetails,
@Parameter(description = "๋””๋ฐ”์ด์Šค ID", required = true)
@RequestParam String deviceId) {

fcmService.removeToken(memberDetails.getId(), deviceId);

return ResponseEntity.ok()
.body(SuccessResponse.ok());
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.potatocake.everymoment.dto.request;

import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;

@Getter
public class CommentRequest {

@NotEmpty(message = "๋Œ“๊ธ€ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.")
private String content;

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
package com.potatocake.everymoment.dto.request;

import com.potatocake.everymoment.dto.LocationPoint;
import jakarta.validation.constraints.Size;
import java.util.List;
import lombok.Getter;

@Getter
public class DiaryManualCreateRequest {

private List<CategoryRequest> categories;

private LocationPoint locationPoint;

@Size(max = 50, message = "์žฅ์†Œ๋ช…์€ 50์ž๋ฅผ ์ดˆ๊ณผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค")
private String locationName;

@Size(max = 200, message = "์ฃผ์†Œ๋Š” 200์ž๋ฅผ ์ดˆ๊ณผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค")
private String address;

private boolean isBookmark;
private boolean isPublic;

@Size(max = 10, message = "์ด๋ชจ์ง€๋Š” 10์ž๋ฅผ ์ดˆ๊ณผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค")
private String emoji;

@Size(max = 5000, message = "์ผ๊ธฐ ๋‚ด์šฉ์€ 5000์ž๋ฅผ ์ดˆ๊ณผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค")
private String content;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.potatocake.everymoment.dto.request;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class FcmNotificationRequest {

private String title;
private String body;
private String type;
private Long targetId;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.potatocake.everymoment.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;

@Getter
public class FcmTokenRequest {

@NotBlank(message = "FCM ํ† ํฐ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
private String fcmToken;

@NotBlank(message = "๋””๋ฐ”์ด์Šค ID๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
private String deviceId;

}
48 changes: 48 additions & 0 deletions src/main/java/com/potatocake/everymoment/entity/DeviceToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.potatocake.everymoment.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class DeviceToken extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false)
private Member member;

@Column(nullable = false)
private String fcmToken;

@Column(nullable = false)
@Lob
private String deviceId;

@Builder
public DeviceToken(Member member, String fcmToken, String deviceId) {
this.member = member;
this.fcmToken = fcmToken;
this.deviceId = deviceId;
}

public void updateToken(String fcmToken) {
this.fcmToken = fcmToken;
}

}
3 changes: 1 addition & 2 deletions src/main/java/com/potatocake/everymoment/entity/Diary.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.potatocake.everymoment.entity;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
Expand Down Expand Up @@ -57,7 +56,7 @@ public class Diary extends BaseTimeEntity {
@Builder.Default
private boolean isPublic = false;

@OneToMany(mappedBy = "diary", cascade = CascadeType.ALL, orphanRemoval = true)
@OneToMany(mappedBy = "diary")
private Set<DiaryCategory> diaryCategories = new HashSet<>();

public void updateContent(String content) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
public enum ErrorCode {

/* Diary */
DIARY_NOT_PUBLIC("๋น„๊ณต๊ฐœ ์ผ๊ธฐ์ž…๋‹ˆ๋‹ค.", HttpStatus.FORBIDDEN),
DIARY_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ผ๊ธฐ์ž…๋‹ˆ๋‹ค.", NOT_FOUND),

/* Member */
Expand Down Expand Up @@ -60,7 +61,14 @@ public enum ErrorCode {

/* FriendRequestService */
FRIEND_REQUEST_ALREADY_EXISTS("์ด๋ฏธ ์นœ๊ตฌ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.", CONFLICT),
FRIEND_REQUEST_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์นœ๊ตฌ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.", NOT_FOUND);
FRIEND_REQUEST_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์นœ๊ตฌ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.", NOT_FOUND),

/* FCM */
FCM_TOKEN_NOT_FOUND("FCM ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", HttpStatus.NOT_FOUND),
FCM_MESSAGE_SEND_FAILED("FCM ๋ฉ”์‹œ์ง€ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.", HttpStatus.INTERNAL_SERVER_ERROR),

/* Friend */
ALREADY_FRIEND("์ด๋ฏธ ์นœ๊ตฌ ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค.", HttpStatus.CONFLICT);

private final String message;
private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.potatocake.everymoment.repository;

import com.potatocake.everymoment.entity.DeviceToken;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface DeviceTokenRepository extends JpaRepository<DeviceToken, Long> {

List<DeviceToken> findAllByMemberId(Long memberId);

Optional<DeviceToken> findByMemberIdAndDeviceId(Long memberId, String deviceId);

void deleteByMemberIdAndDeviceId(Long memberId, String deviceId);

}
Loading

0 comments on commit 97b6bd6

Please sign in to comment.