Skip to content

Commit 4fbd193

Browse files
yxxnghwanSeungpangkth990303asebn1prefer2
authored
chore: 0.5.0 버전을 배포한다.
chore: 0.5.0 버전을 배포한다. Co-authored-by: seungpang <[email protected]> Co-authored-by: yxxnghwan <[email protected]> Co-authored-by: kth990303 <[email protected]> Co-authored-by: asebn1 <[email protected]> Co-authored-by: prefer2 <[email protected]> Co-authored-by: soyi47 <[email protected]>
2 parents cba53c6 + bf4d412 commit 4fbd193

File tree

199 files changed

+4777
-1504
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

199 files changed

+4777
-1504
lines changed

README.md

+38-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
1-
# 2022-nae-pyeon
2-
### 내 마음을 편지로
1+
<p align="middle" >
2+
<img width="200px;" src="https://user-images.githubusercontent.com/57438644/192427863-7a67acc7-722c-4618-892a-86c6431bba04.png"/>
3+
</p>
4+
<h1 align="middle">내편</h1>
5+
<p align="middle">내 마음을 편지로, 내편</p>
36

7+
### 프로젝트 소개 💌
8+
내편은 롤링페이퍼 서비스입니다. 원하는 사람들과 모임을 만들어 롤링페이퍼를 작성할 수 있습니다.
9+
내편 서비스를 통해 `내 편`에게 마음을 전달해보아요!
410

5-
|FRONTEND|FRONTEND|BACKEND|BACKEND|BACKEND|BACKEND
11+
12+
### 팀원 👩‍👦‍👦
13+
14+
|프론트엔드|프론트엔드|백엔드|백엔드|백엔드|백엔드|
615
|:-:|:-:|:-:|:-:|:-:|:-:|
7-
|![](https://github.com/prefer2.png?size=100)|![](https://github.com/soyi47.png?size=100)|![](https://github.com/kth990303.png?size=100)|![](https://github.com/seungpang.png?size=100)|![](https://github.com/yxxnghwan.png?size=100)|![](https://github.com/asebn1.png?size=100)
8-
|[도리](https://github.com/prefer2)|[소피아](https://github.com/soyi47)|[케이](https://github.com/kth990303)|[승팡](https://github.com/seungpang)|[알렉스](https://github.com/yxxnghwan)|[제로](https://github.com/asebn1)
16+
|![도리](https://user-images.githubusercontent.com/57438644/194012074-b174c57c-73a1-4987-ba7f-c43e9275bbe2.png?size=100)|![소피아](https://user-images.githubusercontent.com/57438644/194012003-85309c16-a8b9-4cb8-9f29-ea6c41b5dac8.png?size=100)|![케이](https://user-images.githubusercontent.com/57438644/194011499-0d1445fc-6ad8-473b-aec1-55b47ad3bf57.png?size=100)|![승팡](https://user-images.githubusercontent.com/57438644/194011899-3c2ad161-d79e-4d30-b480-b7855ebeeb2c.png?size=100)|![알렉스](https://user-images.githubusercontent.com/57438644/194011294-6a49501a-3cac-4973-8b12-22edb6c3619f.png?size=100)|![제로](https://user-images.githubusercontent.com/57438644/194011739-accc3a55-4d93-435f-aa4c-94db4933ca2f.png?size=100)|
17+
|[도리](https://github.com/prefer2)|[소피아](https://github.com/soyi47)|[케이](https://github.com/kth990303)|[승팡](https://github.com/seungpang)|[알렉스](https://github.com/yxxnghwan)|[제로](https://github.com/asebn1)|
18+
19+
20+
## 프로젝트 기술스택 🏰
21+
22+
### 백엔드 🏫
23+
24+
![백엔드기술스택](https://user-images.githubusercontent.com/57438644/194008987-08fe38f0-7ab6-423a-83d0-dc575c9aaa4f.JPG)
25+
26+
### 프론트엔드 🏡
27+
28+
29+
## 프로젝트 아키텍처 📚
30+
31+
### 백엔드 프로젝트 아키텍처 📙
32+
![백엔드_프로젝트_아키텍처](https://user-images.githubusercontent.com/57438644/194009329-48f0d8a1-66e3-4624-98be-b6ff44ae04f9.JPG)
33+
34+
### 프론트엔드 프로젝트 아키텍처 📘
35+
36+
### CI/CD
37+
![슬라이드5](https://user-images.githubusercontent.com/57438644/194009306-18b6b7be-9ed1-439f-8109-45f94eef9888.JPG)
38+
39+
40+
## 팀 문화
41+
![팀문화](https://user-images.githubusercontent.com/57438644/194008156-205b797c-8592-41d2-924c-c6472f549dde.JPG)

backend/src/docs/asciidoc/auth.adoc

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,10 @@
44
operation::auth-controller-test/kakao-login[snippets='http-request,http-response']
55

66
=== 구글 Oauth
7-
operation::auth-controller-test/google-login[snippets='http-request,http-response']
7+
operation::auth-controller-test/google-login[snippets='http-request,http-response']
8+
9+
=== Access Token 재요청
10+
operation::auth-controller-test/renewal-token[snippets='http-request,http-response']
11+
12+
=== 리프레시 토큰 무효화
13+
operation::auth-controller-test/logout[snippets='http-request,http-response']

backend/src/docs/asciidoc/errorCodes.adoc

+10
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@
4040
| 모임에게 작성하는 메시지는 비밀로 작성할 수 없습니다. rollingpaperId = {%d}
4141
| 모임에게 작성하는 메시지는 비밀로 작성할 수 없습니다.
4242
| `400 Bad Request`
43+
44+
| `2005`
45+
| 이미 좋아요를 눌렀습니다. memberId={%d} messageId={%d}
46+
| 이미 좋아요를 눌렀습니다.
47+
| `400 Bad Request`
48+
49+
| `2006`
50+
| 이미 좋아요 취소를 눌렀습니다. memberId={%d} messageId={%d}
51+
| 이미 좋아요 취소를 눌렀습니다.
52+
| `400 Bad Request`
4353
|===
4454

4555
=== 유저 에러

backend/src/docs/asciidoc/messages.adoc

+6
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ operation::message-controller-test/update-message[snippets='http-request,http-re
1111

1212
=== 메시지 삭제
1313
operation::message-controller-test/delete-message[snippets='http-request,http-response']
14+
15+
=== 메시지 좋아요
16+
operation::message-controller-test/like-message[snippets='http-request,http-response']
17+
18+
=== 메시지 좋아요 취소
19+
operation::message-controller-test/cancel-like-message[snippets='http-request,http-response']

backend/src/docs/asciidoc/rollingpapers.adoc

+13-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,21 @@ operation::rollingpaper-controller-test/create-team-rollingpaper[snippets='http-
99
=== 롤링페이퍼 단건 조회
1010
operation::rollingpaper-controller-test/find-rollingpaper-by-id[snippets='http-request,http-response']
1111

12-
=== 모임 내 롤링페이퍼 목록 조회
12+
=== 모임 내 전체 롤링페이퍼 목록 조회
1313
operation::rollingpaper-controller-test/find-rollingpapers-by-team-id[snippets='http-request,http-response']
1414

15+
=== 모임 내 팀 롤링페이퍼 목록 조회
16+
operation::rollingpaper-controller-test/find-team-rollingpapers-by-team-id[snippets='http-request,http-response']
17+
18+
=== 모임 내 멤버 롤링페이퍼 목록 조회
19+
operation::rollingpaper-controller-test/find-member-rollingpapers-by-team-id[snippets='http-request,http-response']
20+
21+
=== 모임 내 롤링페이퍼 목록 최신 순 조회
22+
operation::rollingpaper-controller-test/find-rollingpapers-by-team-id-and-latest-order[snippets='http-request,http-response']
23+
24+
=== 모임 내 롤링페이퍼 목록 오래된 순 조회
25+
operation::rollingpaper-controller-test/find-rollingpapers-by-team-id-and-oldest-order[snippets='http-request,http-response']
26+
1527
=== 모임에서 받은 내 롤링페이퍼들 조회
1628
operation::rollingpaper-controller-test/find-rollingpaper-by-id[snippets='http-request,http-response']
1729

backend/src/docs/asciidoc/teams.adoc

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ operation::team-controller-test/get-my-info-in-team[snippets='http-request,http-
3131
operation::team-controller-test/update-my-info[snippets='http-request,http-response']
3232

3333
=== 모임의 초대 코드 생성
34-
operation::team-controller-test/create-invite-token[snippets='http-request,http-response']
34+
operation::team-controller-test/create-invite-code[snippets='http-request,http-response']
3535

3636
=== 초대 코드로 어떤 팀의 초대 코드인지 조회
37-
operation::team-controller-test/get-team-id-by-invite-token[snippets='http-request,http-response']
37+
operation::team-controller-test/get-team-id-by-invite-code[snippets='http-request,http-response']
3838

3939
=== 초대 코드로 팀 가입
4040
operation::team-controller-test/invite-join[snippets='http-request,http-response']

backend/src/main/java/com/woowacourse/naepyeon/config/AuthenticationPrincipalConfig.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ public void addInterceptors(final InterceptorRegistry registry) {
2121
registry.addInterceptor(new LoginInterceptor(jwtTokenProvider))
2222
.addPathPatterns("/api/v1/**")
2323
.excludePathPatterns("/api/v1/oauth/**")
24-
.excludePathPatterns("/api/v1/members");
24+
.excludePathPatterns("/api/v1/members")
25+
.excludePathPatterns("/api/v1/renewal-token")
26+
.excludePathPatterns("/api/v1/logout");
2527
}
2628

2729
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.woowacourse.naepyeon.config.batch;
2+
3+
import com.woowacourse.naepyeon.service.AuthService;
4+
import com.woowacourse.naepyeon.service.TeamService;
5+
import java.util.concurrent.TimeUnit;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.scheduling.annotation.EnableScheduling;
9+
import org.springframework.scheduling.annotation.Scheduled;
10+
11+
@EnableScheduling
12+
@Configuration
13+
@RequiredArgsConstructor
14+
public class BatchTaskConfig {
15+
16+
private final TeamService teamService;
17+
private final AuthService authService;
18+
19+
@Scheduled(timeUnit = TimeUnit.HOURS, initialDelay = 0, fixedDelay = 12)
20+
public void scheduleDeleteExpiredInviteCode() {
21+
teamService.deleteExpiredInviteCodes();
22+
}
23+
24+
@Scheduled(timeUnit = TimeUnit.HOURS, initialDelay = 0, fixedDelay = 12)
25+
public void scheduleDeleteExpiredRefreshToken() {
26+
authService.deleteExpiredRefreshTokens();
27+
}
28+
}

backend/src/main/java/com/woowacourse/naepyeon/config/logging/LoggingInterceptor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public boolean preHandle(final HttpServletRequest request, final HttpServletResp
1919
throws Exception {
2020
final CustomCachingRequestWrapper cachingRequest;
2121
try {
22-
cachingRequest = (CustomCachingRequestWrapper) request;
22+
cachingRequest = (CustomCachingRequestWrapper) request;
2323
} catch (final ClassCastException e) {
2424
log.info("로깅 필터가 동작했는지 확인해주세요.");
2525
return true;

backend/src/main/java/com/woowacourse/naepyeon/controller/MessageController.java

+21
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.woowacourse.naepyeon.controller.dto.MessageRequest;
77
import com.woowacourse.naepyeon.controller.dto.MessageUpdateRequest;
88
import com.woowacourse.naepyeon.service.MessageService;
9+
import com.woowacourse.naepyeon.service.dto.MessageLikeResponseDto;
910
import com.woowacourse.naepyeon.service.dto.MessageResponseDto;
1011
import java.net.URI;
1112
import javax.validation.Valid;
@@ -71,4 +72,24 @@ public ResponseEntity<Void> deleteMessage(@AuthenticationPrincipal final LoginMe
7172
messageService.deleteMessage(messageId, loginMemberRequest.getId());
7273
return ResponseEntity.noContent().build();
7374
}
75+
76+
@PostMapping("/{messageId}/likes")
77+
public ResponseEntity<MessageLikeResponseDto> likeMessage(
78+
@AuthenticationPrincipal final LoginMemberRequest loginMemberRequest,
79+
@PathVariable final Long rollingpaperId,
80+
@PathVariable final Long messageId) {
81+
final MessageLikeResponseDto messageLikeResponse =
82+
messageService.likeMessage(loginMemberRequest.getId(), rollingpaperId, messageId);
83+
return ResponseEntity.ok(messageLikeResponse);
84+
}
85+
86+
@DeleteMapping("/{messageId}/likes")
87+
public ResponseEntity<MessageLikeResponseDto> cancelLikeMessage(
88+
@AuthenticationPrincipal final LoginMemberRequest loginMemberRequest,
89+
@PathVariable final Long rollingpaperId,
90+
@PathVariable final Long messageId) {
91+
final MessageLikeResponseDto messageLikeResponse =
92+
messageService.cancelLikeMessage(loginMemberRequest.getId(), messageId);
93+
return ResponseEntity.ok(messageLikeResponse);
94+
}
7495
}

backend/src/main/java/com/woowacourse/naepyeon/controller/RollingpaperController.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.web.bind.annotation.PutMapping;
2121
import org.springframework.web.bind.annotation.RequestBody;
2222
import org.springframework.web.bind.annotation.RequestMapping;
23+
import org.springframework.web.bind.annotation.RequestParam;
2324
import org.springframework.web.bind.annotation.RestController;
2425

2526
@RequiredArgsConstructor
@@ -65,9 +66,11 @@ public ResponseEntity<RollingpaperResponseDto> findRollingpaperById(
6566
@GetMapping("/rollingpapers")
6667
public ResponseEntity<RollingpapersResponseDto> findRollingpapersByTeamId(
6768
@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
69+
@RequestParam(value = "order", required = false, defaultValue = "latest") final String order,
70+
@RequestParam(value = "filter", required = false) final String filter,
6871
@PathVariable final Long teamId) {
69-
final RollingpapersResponseDto rollingpapersResponseDto = rollingpaperService.findByTeamId(teamId,
70-
loginMemberRequest.getId());
72+
final RollingpapersResponseDto rollingpapersResponseDto =
73+
rollingpaperService.findByTeamId(teamId, loginMemberRequest.getId(), order, filter);
7174
return ResponseEntity.ok(rollingpapersResponseDto);
7275
}
7376

@@ -76,7 +79,7 @@ public ResponseEntity<Void> updateRollingpaper(
7679
@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
7780
@PathVariable final Long teamId,
7881
@PathVariable final Long rollingpaperId,
79-
@RequestBody final RollingpaperUpdateRequest updateRequest) {
82+
@RequestBody @Valid final RollingpaperUpdateRequest updateRequest) {
8083
rollingpaperService.updateTitle(rollingpaperId, updateRequest.getTitle(), teamId, loginMemberRequest.getId());
8184
return ResponseEntity.noContent().build();
8285
}

backend/src/main/java/com/woowacourse/naepyeon/controller/TeamController.java

+12-13
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import com.woowacourse.naepyeon.controller.auth.AuthenticationPrincipal;
44
import com.woowacourse.naepyeon.controller.dto.CreateResponse;
5+
import com.woowacourse.naepyeon.controller.dto.InviteCodeResponse;
56
import com.woowacourse.naepyeon.controller.dto.InviteJoinRequest;
6-
import com.woowacourse.naepyeon.controller.dto.InviteTokenResponse;
77
import com.woowacourse.naepyeon.controller.dto.JoinTeamMemberRequest;
88
import com.woowacourse.naepyeon.controller.dto.LoginMemberRequest;
99
import com.woowacourse.naepyeon.controller.dto.TeamRequest;
@@ -104,7 +104,7 @@ public ResponseEntity<Void> deleteTeam(@AuthenticationPrincipal @Valid final Log
104104
@PostMapping("/{teamId}")
105105
public ResponseEntity<Void> joinMember(@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
106106
@PathVariable final Long teamId,
107-
@RequestBody final JoinTeamMemberRequest joinTeamMemberRequest) {
107+
@RequestBody @Valid final JoinTeamMemberRequest joinTeamMemberRequest) {
108108
teamService.joinMember(teamId, loginMemberRequest.getId(), joinTeamMemberRequest.getNickname());
109109
return ResponseEntity.noContent().build();
110110
}
@@ -121,37 +121,36 @@ public ResponseEntity<TeamMemberResponseDto> getMyInfoInTeam(
121121
public ResponseEntity<Void> updateMyInfo(
122122
@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
123123
@PathVariable final Long teamId,
124-
@RequestBody final UpdateTeamParticipantRequest updateTeamParticipantRequest) {
124+
@RequestBody @Valid final UpdateTeamParticipantRequest updateTeamParticipantRequest) {
125125
teamService.updateMyInfo(teamId, loginMemberRequest.getId(), updateTeamParticipantRequest.getNickname());
126126
return ResponseEntity.noContent().build();
127127
}
128128

129129
@PostMapping("/{teamId}/invite")
130-
public ResponseEntity<InviteTokenResponse> createInviteToken(
130+
public ResponseEntity<InviteCodeResponse> createInviteCode(
131131
@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
132132
@PathVariable final Long teamId) {
133133
if (!teamService.isJoinedMember(loginMemberRequest.getId(), teamId)) {
134134
throw new UncertificationTeamMemberException(teamId, loginMemberRequest.getId());
135135
}
136-
final String inviteToken = teamService.createInviteToken(teamId);
137-
return ResponseEntity.ok(new InviteTokenResponse(inviteToken));
136+
final String inviteCode = teamService.createInviteCode(teamId);
137+
return ResponseEntity.ok(new InviteCodeResponse(inviteCode));
138138
}
139139

140140
@GetMapping("/invite")
141-
public ResponseEntity<TeamResponseDto> findTeamByInviteToken(
141+
public ResponseEntity<TeamResponseDto> findTeamByInviteCode(
142142
@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
143-
@RequestParam("inviteToken") final String inviteToken) {
144-
145-
final TeamResponseDto teamResponseDto = teamService.findTeamByInviteToken(inviteToken,
146-
loginMemberRequest.getId());
143+
@RequestParam("inviteCode") final String inviteCode) {
144+
final TeamResponseDto teamResponseDto =
145+
teamService.findTeamByInviteCode(inviteCode, loginMemberRequest.getId());
147146
return ResponseEntity.ok(teamResponseDto);
148147
}
149148

150149
@PostMapping("/invite/join")
151150
public ResponseEntity<Void> inviteJoin(@AuthenticationPrincipal @Valid final LoginMemberRequest loginMemberRequest,
152-
@RequestBody final InviteJoinRequest inviteJoinRequest) {
151+
@RequestBody @Valid final InviteJoinRequest inviteJoinRequest) {
153152
teamService.inviteJoin(
154-
inviteJoinRequest.getInviteToken(),
153+
inviteJoinRequest.getInviteCode(),
155154
loginMemberRequest.getId(),
156155
inviteJoinRequest.getNickname()
157156
);

backend/src/main/java/com/woowacourse/naepyeon/controller/auth/AuthController.java

+17-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.woowacourse.naepyeon.controller.dto.TokenRequest;
44
import com.woowacourse.naepyeon.service.AuthService;
5+
import com.woowacourse.naepyeon.service.dto.AccessTokenDto;
6+
import com.woowacourse.naepyeon.service.dto.RefreshTokenDto;
57
import com.woowacourse.naepyeon.service.dto.TokenResponseDto;
68
import javax.validation.Valid;
79
import lombok.RequiredArgsConstructor;
@@ -13,22 +15,34 @@
1315

1416
@RestController
1517
@RequiredArgsConstructor
16-
@RequestMapping("/api/v1/oauth")
18+
@RequestMapping("/api/v1")
1719
public class AuthController {
1820

1921
private final AuthService authService;
2022

21-
@PostMapping("/kakao")
23+
@PostMapping("/oauth/kakao")
2224
public ResponseEntity<TokenResponseDto> kakaoLogin(@RequestBody @Valid final TokenRequest tokenRequest) {
2325
final TokenResponseDto tokenResponseDto =
2426
authService.createTokenWithKakaoOauth(tokenRequest.toServiceRequest());
2527
return ResponseEntity.ok(tokenResponseDto);
2628
}
2729

28-
@PostMapping("/google")
30+
@PostMapping("/oauth/google")
2931
public ResponseEntity<TokenResponseDto> googleLogin(@RequestBody @Valid final TokenRequest tokenRequest) {
3032
final TokenResponseDto tokenResponseDto =
3133
authService.createTokenWithGoogleOauth(tokenRequest.toServiceRequest());
3234
return ResponseEntity.ok(tokenResponseDto);
3335
}
36+
37+
@PostMapping("/renewal-token")
38+
public ResponseEntity<AccessTokenDto> renewalToken(@RequestBody @Valid final RefreshTokenDto renewalRequest) {
39+
final AccessTokenDto accessTokenDto = authService.renewalToken(renewalRequest.getRefreshToken());
40+
return ResponseEntity.ok(accessTokenDto);
41+
}
42+
43+
@PostMapping("/logout")
44+
public ResponseEntity<Void> logout(@RequestBody @Valid final RefreshTokenDto refreshTokenDto) {
45+
authService.logout(refreshTokenDto.getRefreshToken());
46+
return ResponseEntity.noContent().build();
47+
}
3448
}

backend/src/main/java/com/woowacourse/naepyeon/controller/dto/InviteTokenResponse.java renamed to backend/src/main/java/com/woowacourse/naepyeon/controller/dto/InviteCodeResponse.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
@NoArgsConstructor(access = AccessLevel.PROTECTED)
99
@AllArgsConstructor
1010
@Getter
11-
public class InviteTokenResponse {
11+
public class InviteCodeResponse {
1212

13-
private String inviteToken;
13+
private String inviteCode;
1414
}

backend/src/main/java/com/woowacourse/naepyeon/controller/dto/InviteJoinRequest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
@Getter
1212
public class InviteJoinRequest {
1313

14-
@NotBlank(message = "4015:올바르지 않은 토큰입니다.")
15-
private String inviteToken;
14+
@NotBlank(message = "4015:올바르지 않은 코드입니다.")
15+
private String inviteCode;
1616

1717
@NotBlank(message = "4009:닉네임은 공백일 수 없습니다.")
1818
private String nickname;

0 commit comments

Comments
 (0)