Skip to content

Commit 14e1c33

Browse files
committed
Merge remote-tracking branch 'origin/chore/#7' into chore/#7
2 parents 7c42f1b + 12b59a8 commit 14e1c33

30 files changed

+971
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ out/
3535

3636
### VS Code ###
3737
.vscode/
38+
.env

build.gradle

+9-1
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,19 @@ dependencies {
3535
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'
3636

3737
compileOnly 'org.projectlombok:lombok'
38-
runtimeOnly 'com.mysql:mysql-connector-j'
3938
annotationProcessor 'org.projectlombok:lombok'
39+
runtimeOnly 'com.mysql:mysql-connector-j'
4040
testImplementation 'org.springframework.boot:spring-boot-starter-test'
4141
testImplementation 'org.springframework.security:spring-security-test'
4242
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
43+
44+
implementation 'org.springframework.boot:spring-boot-starter'
45+
implementation 'io.jsonwebtoken:jjwt:0.9.1'
46+
implementation 'org.springframework.boot:spring-boot-starter-webflux'
47+
48+
implementation 'javax.xml.bind:jaxb-api:2.3.1'
49+
implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1'
50+
4351
}
4452

4553
tasks.named('test') {

src/main/java/com/bloomgroom/BloomGroomApplication.java

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
@PropertySource(value = { "classpath:database/application-database.yml" }, factory = YamlPropertySourceFactory.class)
1515
@PropertySource(value = { "classpath:oauth2/application-oauth2.yml" }, factory = YamlPropertySourceFactory.class)
1616
@PropertySource(value = { "classpath:s3/application-s3.yml" }, factory = YamlPropertySourceFactory.class)
17+
1718
public class BloomGroomApplication {
1819

1920
public static void main(String[] args) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.bloomgroom.domain.smallgoal.application;
2+
3+
import com.bloomgroom.domain.biggoal.domain.BigGoal;
4+
import com.bloomgroom.domain.biggoal.domain.repository.BigGoalRepository;
5+
import com.bloomgroom.domain.smallgoal.domain.SmallGoal;
6+
import com.bloomgroom.domain.smallgoal.domain.repository.SmallGoalRepository;
7+
import com.bloomgroom.domain.smallgoal.dto.request.CreateSmallGoalReq;
8+
import com.bloomgroom.domain.smallgoal.dto.request.UpdateSmallGoalReq;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
12+
import java.time.LocalDateTime;
13+
import java.util.List;
14+
import java.util.stream.Collectors;
15+
16+
import com.bloomgroom.global.payload.ApiResponse;
17+
import org.springframework.http.ResponseEntity;
18+
19+
@Service
20+
@RequiredArgsConstructor
21+
public class SmallGoalService {
22+
23+
private final SmallGoalRepository smallGoalRepository;
24+
private final BigGoalRepository bigGoalRepository;
25+
26+
// 세부 목표 생성
27+
public ResponseEntity<ApiResponse> createSmallGoal(CreateSmallGoalReq request) {
28+
SmallGoal smallGoal = new SmallGoal();
29+
30+
BigGoal bigGoal = bigGoalRepository.findById(request.getBigGoalId())
31+
.orElseThrow(() -> new RuntimeException("장기 목표를 찾을 수 없습니다."));
32+
smallGoal.setBigGoal(bigGoal);
33+
smallGoal.setContent(request.getContent());
34+
smallGoal.setGoalStatus(request.getGoalStatus());
35+
smallGoal = smallGoalRepository.save(smallGoal);
36+
37+
ApiResponse response = ApiResponse.toApiResponse(smallGoal);
38+
return ResponseEntity.ok(response);
39+
}
40+
41+
// 특정 장기 목표의 세부 목표 조회
42+
public ResponseEntity<ApiResponse> getSmallGoalsByBigGoalId(Long bigGoalId) {
43+
BigGoal bigGoal = bigGoalRepository.findById(bigGoalId)
44+
.orElseThrow(() -> new RuntimeException("장기 목표를 찾을 수 없습니다."));
45+
46+
List<SmallGoal> smallGoals = smallGoalRepository.findByBigGoal(bigGoal);
47+
ApiResponse response = ApiResponse.toApiResponse(smallGoals);
48+
49+
return ResponseEntity.ok(response);
50+
}
51+
52+
// 세부 목표 수정
53+
public ResponseEntity<ApiResponse> updateSmallGoal(Long smallGoalId, UpdateSmallGoalReq request) {
54+
SmallGoal smallGoal = smallGoalRepository.findById(smallGoalId)
55+
.orElseThrow(() -> new RuntimeException("세부 목표를 찾을 수 없습니다."));
56+
57+
smallGoal.setContent(request.getContent());
58+
smallGoal.setGoalStatus(request.getGoalStatus());
59+
smallGoal = smallGoalRepository.save(smallGoal);
60+
61+
ApiResponse response = ApiResponse.toApiResponse(smallGoal);
62+
63+
return ResponseEntity.ok(response);
64+
}
65+
66+
// 세부 목표 삭제
67+
public ResponseEntity<ApiResponse> deleteSmallGoal(Long smallGoalId) {
68+
smallGoalRepository.deleteById(smallGoalId);
69+
ApiResponse response = ApiResponse.toApiResponse("세부 목표가 삭제되었습니다.");
70+
71+
return ResponseEntity.ok(response);
72+
}
73+
74+
// 날짜로 세부 목표 조회
75+
public ResponseEntity<ApiResponse> getSmallGoalsByDate(Long bigGoalId, LocalDateTime smallGoalDate) {
76+
BigGoal bigGoal = bigGoalRepository.findById(bigGoalId)
77+
.orElseThrow(() -> new RuntimeException("장기 목표를 찾을 수 없습니다."));
78+
79+
List<SmallGoal> smallGoals = smallGoalRepository.findByBigGoal(bigGoal).stream()
80+
.filter(goal -> goal.getSmallGoalDate().toLocalDate().isEqual(smallGoalDate.toLocalDate())) // 날짜 비교
81+
.collect(Collectors.toList());
82+
83+
ApiResponse response = ApiResponse.toApiResponse(smallGoals);
84+
return ResponseEntity.ok(response);
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.bloomgroom.domain.smallgoal.domain;
2+
3+
import com.bloomgroom.domain.biggoal.domain.BigGoal;
4+
import jakarta.persistence.*;
5+
import lombok.AllArgsConstructor;
6+
7+
import lombok.Data;
8+
import lombok.NoArgsConstructor;
9+
10+
import java.time.LocalDateTime;
11+
12+
@Entity
13+
@Data
14+
@AllArgsConstructor
15+
@NoArgsConstructor
16+
public class SmallGoal {
17+
18+
@Id
19+
@GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 설정
20+
private Long smallGoalId;
21+
22+
@ManyToOne
23+
@JoinColumn(name = "bigGoal_id", nullable = false)
24+
private BigGoal bigGoal;
25+
26+
private String content;
27+
28+
private Boolean goalStatus;
29+
30+
private LocalDateTime smallGoalDate;
31+
32+
@PrePersist
33+
protected void onCreate() {
34+
this.smallGoalDate = LocalDateTime.now(); // 현재 날짜와 시간으로 설정
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.bloomgroom.domain.smallgoal.domain.repository;
2+
3+
import com.bloomgroom.domain.biggoal.domain.BigGoal;
4+
import com.bloomgroom.domain.smallgoal.domain.SmallGoal;
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.stereotype.Repository;
7+
8+
import java.util.List;
9+
import java.util.Optional;
10+
11+
@Repository
12+
public interface SmallGoalRepository extends JpaRepository<SmallGoal, Long> {
13+
List<SmallGoal> findByBigGoal(BigGoal bigGoal);
14+
Optional<SmallGoal> findBySmallGoalId(Long smallGoalId);
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.bloomgroom.domain.smallgoal.dto.request;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
import java.time.LocalDateTime;
8+
9+
@Data
10+
@AllArgsConstructor
11+
@NoArgsConstructor
12+
public class CreateSmallGoalReq {
13+
private Long bigGoalId; // 장기 목표 ID
14+
private String content = ""; // 세부 목표 내용 (기본값: 빈 문자열)
15+
private Boolean goalStatus = false; // 목표 상태 (기본값: false)
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.bloomgroom.domain.smallgoal.dto.request;
2+
3+
import lombok.Data;
4+
5+
import java.time.LocalDateTime;
6+
7+
@Data
8+
public class SmallGoalDateReq {
9+
private LocalDateTime smallGoalDate;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.bloomgroom.domain.smallgoal.dto.request;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
import java.time.LocalDateTime;
8+
9+
@Data
10+
@AllArgsConstructor
11+
@NoArgsConstructor
12+
public class UpdateSmallGoalReq {
13+
private String content; // 수정할 세부 목표 내용
14+
private Boolean goalStatus; // 수정할 목표 상태
15+
private LocalDateTime smallGoalDate;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.bloomgroom.domain.smallgoal.dto.response;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
import java.time.LocalDateTime;
7+
8+
@Data
9+
@AllArgsConstructor
10+
public class SmallGoalRes {
11+
private Long smallGoalId;
12+
private Long bigGoalId;
13+
private String content;
14+
private LocalDateTime smallGoalDate;
15+
private Boolean goalStatus;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.bloomgroom.domain.smallgoal.presentation;
2+
3+
import com.bloomgroom.domain.smallgoal.application.SmallGoalService;
4+
import com.bloomgroom.domain.smallgoal.dto.request.CreateSmallGoalReq;
5+
import com.bloomgroom.domain.smallgoal.dto.request.SmallGoalDateReq;
6+
import com.bloomgroom.domain.smallgoal.dto.request.UpdateSmallGoalReq;
7+
import com.bloomgroom.global.payload.ApiResponse;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.http.ResponseEntity;
10+
import org.springframework.web.bind.annotation.*;
11+
12+
@RestController
13+
@RequestMapping("/api/v1/small-goal")
14+
@RequiredArgsConstructor
15+
public class SmallGoalController {
16+
17+
private final SmallGoalService smallGoalService;
18+
19+
// 생성
20+
@PostMapping("/{bigGoalId}")
21+
public ResponseEntity<ApiResponse> createSmallGoal(@PathVariable Long bigGoalId, @RequestBody CreateSmallGoalReq request) {
22+
request.setBigGoalId(bigGoalId); // 요청 객체에 장기 목표 ID 설정
23+
return smallGoalService.createSmallGoal(request);
24+
}
25+
26+
// 조회
27+
@GetMapping("/list/{bigGoalId}")
28+
public ResponseEntity<ApiResponse> getSmallGoalsByBigGoalId(@PathVariable Long bigGoalId) {
29+
return smallGoalService.getSmallGoalsByBigGoalId(bigGoalId);
30+
}
31+
32+
// 수정
33+
@PatchMapping("/{smallGoalId}")
34+
public ResponseEntity<ApiResponse> updateSmallGoal(@PathVariable Long smallGoalId, @RequestBody UpdateSmallGoalReq request) {
35+
return smallGoalService.updateSmallGoal(smallGoalId, request);
36+
}
37+
38+
// 삭제
39+
@DeleteMapping("/{smallGoalId}")
40+
public ResponseEntity<ApiResponse> deleteSmallGoal(@PathVariable Long smallGoalId) {
41+
return smallGoalService.deleteSmallGoal(smallGoalId);
42+
}
43+
44+
// 날짜로 조회
45+
@PostMapping("/date-list/{bigGoalId}")
46+
public ResponseEntity<ApiResponse> getSmallGoalsByDate(@PathVariable Long bigGoalId, @RequestBody SmallGoalDateReq request) {
47+
return smallGoalService.getSmallGoalsByDate(bigGoalId, request.getSmallGoalDate());
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.bloomgroom.domain.user.application;
2+
3+
import com.bloomgroom.domain.user.domain.RefreshToken;
4+
import com.bloomgroom.domain.user.domain.User;
5+
import com.bloomgroom.domain.user.domain.repository.RefreshTokenRepository;
6+
import com.bloomgroom.domain.user.domain.repository.UserRepository;
7+
import io.jsonwebtoken.Claims;
8+
import io.jsonwebtoken.Jwts;
9+
import io.jsonwebtoken.SignatureAlgorithm;
10+
import io.jsonwebtoken.SignatureException;
11+
import lombok.RequiredArgsConstructor;
12+
import org.springframework.beans.factory.annotation.Value;
13+
14+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
15+
import org.springframework.stereotype.Service;
16+
import java.util.Date;
17+
18+
@Service
19+
@RequiredArgsConstructor
20+
public class TokenService {
21+
private final RefreshTokenRepository refreshTokenRepository;
22+
private final UserRepository userRepository;
23+
24+
@Value("${jwt.secret-key}")
25+
private String secretKey;
26+
27+
// AccessToken 생성
28+
public String createAccessToken(User user) { //AccessToken을 JWT형식으로 생성함
29+
return Jwts.builder()
30+
.setSubject(user.getUserId().toString())
31+
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) //1시간
32+
.signWith(SignatureAlgorithm.HS256, secretKey)
33+
.compact();
34+
}
35+
36+
// RefreshToken 생성
37+
public String createRefreshToken(User user) {
38+
return Jwts.builder()
39+
.setSubject(user.getUserId().toString())
40+
.setExpiration(new Date(System.currentTimeMillis() + 7 * 24 * 3600000)) //1주일
41+
.signWith(SignatureAlgorithm.HS256, secretKey)
42+
.compact();
43+
}
44+
45+
// RefreshToken 저장
46+
public void saveRefreshToken(User user, String refreshToken) {
47+
48+
RefreshToken token = new RefreshToken();
49+
50+
token.setRefreshToken(refreshToken);
51+
token.setUser(user);
52+
refreshTokenRepository.save(token);
53+
}
54+
55+
//RefreshToken 이용하여 AccessToken 재발급
56+
public String renewAccessToken(String refreshToken) {
57+
58+
RefreshToken token = refreshTokenRepository.findByRefreshToken(refreshToken).orElse(null);
59+
60+
if (token == null) {
61+
return null;
62+
}
63+
User user = token.getUser();
64+
return createAccessToken(user);
65+
}
66+
67+
// RefreshToken 조회
68+
public String getRefreshToken(User user) {
69+
RefreshToken refreshToken = refreshTokenRepository.findByUser(user);
70+
71+
if (refreshToken != null) {
72+
return refreshToken.getRefreshToken();
73+
}
74+
return null;
75+
}
76+
77+
}

0 commit comments

Comments
 (0)