├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── appspec.yml
├── build.gradle
├── docs
└── Project Branch, Commit Convetion.md
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── scripts
└── deploy.sh
├── settings.gradle
└── src
├── main
├── java
│ └── com
│ │ └── yapp
│ │ └── ios1
│ │ ├── Ios1Application.java
│ │ ├── annotation
│ │ ├── Auth.java
│ │ └── ReAuth.java
│ │ ├── aop
│ │ ├── AuthAspect.java
│ │ └── UserContext.java
│ │ ├── config
│ │ ├── AsyncConfig.java
│ │ ├── CacheKey.java
│ │ ├── RedisCacheConfig.java
│ │ ├── RestTemplateConfig.java
│ │ ├── SecurityConfig.java
│ │ ├── SwaggerConfig.java
│ │ ├── filter
│ │ │ └── CustomServletWrappingFilter.java
│ │ └── interceptor
│ │ │ ├── InterceptorConfig.java
│ │ │ └── LoggingInterceptor.java
│ │ ├── controller
│ │ ├── AlarmController.java
│ │ ├── BucketController.java
│ │ ├── EmailController.java
│ │ ├── FriendController.java
│ │ ├── HealthController.java
│ │ ├── OauthController.java
│ │ ├── ProfileController.java
│ │ ├── S3Controller.java
│ │ ├── SearchController.java
│ │ ├── TokenController.java
│ │ ├── UserController.java
│ │ ├── UserInfoController.java
│ │ └── dto
│ │ │ ├── bucket
│ │ │ └── BucketRequestDto.java
│ │ │ ├── email
│ │ │ ├── EmailCodeDto.java
│ │ │ └── EmailDto.java
│ │ │ └── user
│ │ │ ├── ProfileUpdateDto.java
│ │ │ ├── login
│ │ │ ├── PasswordDto.java
│ │ │ ├── SignInDto.java
│ │ │ └── SignUpDto.java
│ │ │ └── social
│ │ │ ├── SocialLoginDto.java
│ │ │ └── SocialType.java
│ │ ├── dto
│ │ ├── ResponseDto.java
│ │ ├── bookmark
│ │ │ └── BookmarkListDto.java
│ │ ├── bucket
│ │ │ ├── BucketDetailDto.java
│ │ │ └── BucketHomeDto.java
│ │ ├── jwt
│ │ │ ├── JwtPayload.java
│ │ │ ├── RefreshTokenDto.java
│ │ │ └── TokenResponseDto.java
│ │ ├── notification
│ │ │ ├── FcmMessage.java
│ │ │ ├── NotificationDto.java
│ │ │ ├── NotificationForOneDto.java
│ │ │ ├── NotificationLogDto.java
│ │ │ └── NotificationTestDto.java
│ │ └── user
│ │ │ ├── UserInfoDto.java
│ │ │ └── UserStatusDto.java
│ │ ├── enums
│ │ ├── AlarmStatus.java
│ │ ├── BucketLogStatus.java
│ │ ├── BucketStatus.java
│ │ └── FriendStatus.java
│ │ ├── error
│ │ ├── ErrorResponse.java
│ │ ├── GlobalExceptionHandler.java
│ │ └── exception
│ │ │ ├── BusinessException.java
│ │ │ ├── EntityNotFoundException.java
│ │ │ ├── ErrorCode.java
│ │ │ ├── InvalidValueException.java
│ │ │ ├── alarm
│ │ │ └── AlarmNotFoundException.java
│ │ │ ├── aws
│ │ │ └── S3Exception.java
│ │ │ ├── bucket
│ │ │ ├── BucketNotFoundException.java
│ │ │ └── bucketStateIdInvalidException.java
│ │ │ ├── common
│ │ │ └── JsonWriteException.java
│ │ │ ├── email
│ │ │ ├── EmailCodeException.java
│ │ │ └── EmailSendException.java
│ │ │ ├── jwt
│ │ │ ├── JwtException.java
│ │ │ ├── JwtExpiredException.java
│ │ │ └── JwtParseException.java
│ │ │ └── user
│ │ │ ├── DeviceTokenNotFoundException.java
│ │ │ ├── EmailDuplicatedException.java
│ │ │ ├── EmailNotExistException.java
│ │ │ ├── NickNameDuplicatedException.java
│ │ │ ├── PasswordNotMatchException.java
│ │ │ ├── UserAuthenticationException.java
│ │ │ └── UserNotFoundException.java
│ │ ├── mapper
│ │ ├── AlarmMapper.java
│ │ ├── BucketMapper.java
│ │ ├── FriendMapper.java
│ │ ├── ProfileMapper.java
│ │ ├── SearchMapper.java
│ │ ├── TokenMapper.java
│ │ └── UserMapper.java
│ │ ├── message
│ │ ├── AlarmMessage.java
│ │ ├── ResponseMessage.java
│ │ └── ValidMessage.java
│ │ ├── model
│ │ ├── bookmark
│ │ │ └── Bookmark.java
│ │ ├── bucket
│ │ │ ├── Bucket.java
│ │ │ └── BucketTimeline.java
│ │ ├── image
│ │ │ └── Image.java
│ │ ├── notification
│ │ │ └── Notification.java
│ │ ├── tag
│ │ │ └── Tag.java
│ │ └── user
│ │ │ ├── Friend.java
│ │ │ ├── Profile.java
│ │ │ └── User.java
│ │ ├── properties
│ │ ├── EmailProperties.java
│ │ ├── FirebaseProperties.java
│ │ ├── JwtProperties.java
│ │ ├── S3Properties.java
│ │ └── SocialLoginProperties.java
│ │ ├── service
│ │ ├── EmailService.java
│ │ ├── FriendService.java
│ │ ├── OauthService.java
│ │ ├── S3Service.java
│ │ ├── SearchService.java
│ │ ├── alarm
│ │ │ ├── AlarmService.java
│ │ │ └── FirebaseService.java
│ │ ├── bucket
│ │ │ ├── BucketFindService.java
│ │ │ └── BucketService.java
│ │ ├── jwt
│ │ │ ├── JwtIssueService.java
│ │ │ └── JwtService.java
│ │ └── user
│ │ │ ├── ProfileService.java
│ │ │ ├── UserFindService.java
│ │ │ ├── UserInfoService.java
│ │ │ └── UserService.java
│ │ ├── utils
│ │ ├── AlarmMessageUtil.java
│ │ └── RedisUtil.java
│ │ └── validator
│ │ ├── AlarmValidator.java
│ │ ├── BucketValidator.java
│ │ └── UserValidator.java
└── resources
│ ├── logback-spring.xml
│ ├── logback.xml
│ ├── mapper
│ ├── alarmMapper.xml
│ ├── bucketMapper.xml
│ ├── friendMapper.xml
│ ├── profileMapper.xml
│ ├── searchMapper.xml
│ ├── tokenMapper.xml
│ └── userMapper.xml
│ └── templates
│ └── email.html
└── test
└── java
└── com
└── yapp
└── ios1
├── DBConnectionTest.java
├── Ios1ApplicationTests.java
├── dto
└── ResponseDtoTest.java
└── service
├── EmailServiceTest.java
├── JwtServiceTest.java
└── UserServiceTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**/build/
6 | !**/src/test/**/build/
7 |
8 | ### STS ###
9 | .apt_generated
10 | .classpath
11 | .factorypath
12 | .project
13 | .settings
14 | .springBeans
15 | .sts4-cache
16 | bin/
17 | !**/src/main/**/bin/
18 | !**/src/test/**/bin/
19 |
20 | ### IntelliJ IDEA ###
21 | .idea
22 | *.iws
23 | *.iml
24 | *.ipr
25 | out/
26 | !**/src/main/**/out/
27 | !**/src/test/**/out/
28 |
29 | application.yml
30 | application-local.yml
31 | application-dev.yml
32 | application-prod.yml
33 | firebase.json
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11-jre-slim
2 |
3 | WORKDIR /root
4 |
5 | COPY ./build/libs/*.jar .
6 |
7 | CMD java -jar -Dspring.profiles.active=${active} *.jar
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bucket buok
2 |
3 |
4 |
5 | 
6 |
7 | 버킷리스트를 작성하며 나를 기록해 보세요!
8 |
9 | 미래를 ‘완성된 집’ 현재를 ‘설계도’라고 생각해 봅시다.
10 |
11 | buok은 당신이 멋진 집을 완성할 수 있도록 도와드릴 거예요.
12 |
13 | 어떤 집을 짓고 싶은지 찾아보고, 구체적인 설계 계획을 할 수 있도록요!
14 |
15 | 생각날 때마다 미래 계획을 담을 버킷북을 만들어 보세요.
16 |
17 | 완성된 버킷북 중 나를 잘 나타내는 것을 골라 나만의 히스토리로 만들어보세요.
18 |
19 | 저희와 함께하다 보면 당신의 꿈이 이뤄져 있을 거예요.
20 |
21 |
22 |
23 | ---
24 |
25 |
26 |
27 | ## 📚 API Docs
28 |
29 | - [API Description Link](https://github.com/YAPP-18th/iOS1_Backend/wiki)
30 |
31 |
32 |
33 | ## 📐프로젝트 전체 구성도
34 |
35 | 
36 |
37 |
38 |
39 | ## 🛠 사용한 기술 스택
40 |
41 | 
42 |
43 |
44 |
45 | ## 📂 Database Modeling
46 |
47 | | ER Diagram |
48 | |:---:|
49 | | |
50 |
51 |
52 |
53 | ## 프로젝트 주요 관심사
54 |
55 | ### 공통사항
56 |
57 | - 지속적인 성능 개선
58 | - 나쁜 냄새가 나는 코드에 대한 리팩토링
59 |
60 | ### 코드 컨벤션
61 |
62 | - 프로젝트 전반적으로 `일관되게` 코드를 작성하려고 노력
63 |
64 | ### 성능 최적화
65 | - DB 서버와의 통신을 최소화(당연한 이야기지만 N+1 쿼리를 지양하려고 노력)
66 |
67 |
68 |
69 | ## 프로젝트 하면서 겪은 과정들
70 |
71 | **AccessToken, RefreshToken 과정 정리**
72 | > Spring Security 없이 JWT 연동
73 | > [스프링부트 환경에서 JWT 연동하기](https://velog.io/@ayoung0073/springboot-jwt-without-springsecurity) - [아영](https://github.com/ayoung0073)
74 | > Redis Cache 적용하기 - [아영](https://github.com/ayoung0073)
75 |
76 |
77 |
78 | **Session을 사용하지 않고 JWT를 사용한 이유는 무엇일까?**
79 |
80 | > 정균(작성)
81 |
82 |
83 |
84 | **JPA가 아니라 MyBatis를 사용한 이유**
85 |
86 | > [프로젝트에서 JPA가 아닌 MyBatis를 선택한 이유는?](https://devlog-wjdrbs96.tistory.com/350) - [정균](https://github.com/wjdrbs96)
87 |
88 |
89 |
90 | **FireBase Alarm Async 보내기**
91 |
92 | > 정균(작성)
93 |
94 |
95 |
96 | **Spring Logback으로 Slack, CloudWatch로 에러 로그 전송하기**
97 |
98 | > [Spring Error log CloudWatch로 전송하기](https://devlog-wjdrbs96.tistory.com/329) - [정균](https://github.com/wjdrbs96)
99 | > [Spring Error log Slack으로 전송하는 법](https://devlog-wjdrbs96.tistory.com/327) - [정균](https://github.com/wjdrbs96)
100 | > [Spring Filter, Interceptor로 Request logging 하기]() - [정균](https://github.com/wjdrbs96)
101 |
102 |
103 |
104 | **수 많은 에러들을 어떻게 관리하고 있을까?**
105 |
106 | > [Error 클래스 상속 관계를 통한 ControllerAdvice, ExceptionHandler 처리하기](https://devlog-wjdrbs96.tistory.com/348) - [정균](https://github.com/wjdrbs96)
107 |
108 |
109 |
110 | **이메일 인증까지의 과정**
111 |
112 | > 비밀번호 재설정을 위한 이메일 전송부터 인증까지의 과정
113 | > [Thymeleaf을 이용한 이메일 전송하기](https://velog.io/@ayoung0073/SpringBoot-%ED%83%80%EC%9E%84%EB%A6%AC%ED%94%84%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A0%84%EC%86%A1) - [아영](https://github.com/ayoung0073)
114 | > [Redis 이용한 이메일 인증하기](https://velog.io/@ayoung0073/SpringBoot-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%9D%B8%EC%A6%9D-%EA%B3%BC%EC%A0%95-Redis) - [아영](https://github.com/ayoung0073)
115 |
116 |
117 |
118 | **비밀번호 암호화**
119 |
120 | > [단방향 해시 함수와 BCrypt로 비밀번호 암호화하기](https://velog.io/@ayoung0073/Security-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EB%8B%A8%EB%B0%A9%ED%96%A5-%EC%95%94%ED%98%B8%ED%99%94) - [아영](https://github.com/ayoung0073)
121 |
122 |
123 |
124 | **AOP로 중복로직 제거하기**
125 |
126 | > 프로젝트에서 대부분 API에서 인가 체크가 필요했는데, AOP를 적용하여 중복 로직을 제거
127 | > [AOP를 사용하여 중복 로직 제거하기](https://devlog-wjdrbs96.tistory.com/344) - [정균](https://github.com/wjdrbs96)
128 | > [ThreadLocal로 사용자 정보 저장하기](https://velog.io/@ayoung0073/Java-ThreadLocal) - [아영](https://github.com/ayoung0073)
129 |
130 |
131 | **yml 파일 prod, dev, local 환경 분리하기**
132 |
133 | > [application.yml을 prod, dev, local로 분리시키기](https://devlog-wjdrbs96.tistory.com/343) - [정균](https://github.com/wjdrbs96)
134 |
135 |
136 |
137 | **이미지 리사이징**
138 |
139 | > 버킷리스트 앱의 특성상 이미지 업로드 양이 많기 때문에 AWS Lambda를 이용하여 이미지 리사이징 기능을 추가
140 | > [Lambda로 Image Resize 하기](https://devlog-wjdrbs96.tistory.com/330?category=885022) - [정균](https://github.com/wjdrbs96)
141 |
142 |
143 |
144 | **Jenkins와 CodeDeploy, Docker를 이용하여 CI/CD 구현하기**
145 |
146 | > 무중단 자동화 배포 기능을 추가
147 | > [Jenkins CI 설정](https://velog.io/@ayoung0073/jenkins-ci) - [아영](https://github.com/ayoung0073)
148 | > [CodeDeploy, Load-Balancer 설정](https://devlog-wjdrbs96.tistory.com/345) - [정균](https://github.com/wjdrbs96)
149 |
150 |
151 |
152 | ## 브랜치 관리 전략 & 커밋 컨벤션
153 |
154 | - [iOS 1팀 BackEnd Branch && Commit Convention](https://github.com/YAPP-18th/iOS1_Backend/blob/develop/docs/Project%20Branch%2C%20Commit%20Convetion.md)
155 |
156 |
157 |
158 | ## Contributors ✨
159 |
160 |
166 |
167 | [기여자 목록](https://github.com/YAPP-18th/iOS1_Backend/graphs/contributors) 을 확인하여 이 프로젝트에 대해 자세히 확인할 수 있습니다.
168 |
169 |
170 |
171 | ## 🔗 Repository Link
172 |
173 | - [iOS](https://github.com/YAPP-18th/iOS1_Client)
174 |
--------------------------------------------------------------------------------
/appspec.yml:
--------------------------------------------------------------------------------
1 | version: 0.0
2 | os: linux
3 | files:
4 | - source: /
5 | destination: /home/ec2-user/yapp
6 | overwrite: yes
7 |
8 | permissions:
9 | - object: /
10 | pattern: "**"
11 | owner: root
12 | group: root
13 |
14 | hooks:
15 | ApplicationStart:
16 | - location: scripts/deploy.sh
17 | timeout: 60
18 | runas: root
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'org.springframework.boot' version '2.4.3'
3 | id 'io.spring.dependency-management' version '1.0.11.RELEASE'
4 | id 'java'
5 | }
6 |
7 | group = 'com.yapp'
8 | version = '0.0.1-SNAPSHOT'
9 | sourceCompatibility = '11'
10 |
11 | configurations {
12 | compileOnly {
13 | extendsFrom annotationProcessor
14 | }
15 | }
16 |
17 | repositories {
18 | mavenCentral()
19 | }
20 |
21 | dependencies {
22 | implementation 'org.springframework.boot:spring-boot-starter-web'
23 | compileOnly 'org.projectlombok:lombok'
24 | annotationProcessor 'org.projectlombok:lombok'
25 |
26 | // DataBase
27 | runtimeOnly 'mysql:mysql-connector-java'
28 | implementation 'org.springframework.boot:spring-boot-starter-data-redis'
29 | implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'
30 |
31 | // JWT
32 | implementation 'javax.xml.bind:jaxb-api'
33 | implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
34 | implementation 'com.nimbusds:nimbus-jose-jwt:3.10'
35 | runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.2")
36 | runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.2")
37 |
38 | implementation 'com.google.firebase:firebase-admin:6.8.1'
39 |
40 | implementation 'org.springframework.boot:spring-boot-starter-aop'
41 |
42 | implementation 'com.googlecode.json-simple:json-simple:1.1'
43 | implementation 'com.google.code.gson:gson:2.8.6'
44 |
45 | // AWS
46 | compile 'org.springframework.cloud:spring-cloud-starter-aws:2.0.1.RELEASE'
47 |
48 | // logback
49 | compile group: 'ca.pjer', name: 'logback-awslogs-appender', version: '1.4.0'
50 | implementation 'com.github.maricn:logback-slack-appender:1.4.0'
51 |
52 | implementation group: 'org.codehaus.janino', name: 'janino', version: '3.0.7'
53 |
54 | compile "javax.xml.bind:jaxb-api"
55 |
56 | implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security'
57 |
58 | // Swagger
59 | implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
60 | implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
61 |
62 | // validation
63 | implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation', version: '2.4.5'
64 |
65 | // Test
66 | testImplementation 'org.springframework.boot:spring-boot-starter-test'
67 |
68 | // Email
69 | implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
70 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
71 |
72 |
73 | // ConfigurationProperties
74 | annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
75 | }
76 |
77 | test {
78 | useJUnitPlatform()
79 | }
80 |
--------------------------------------------------------------------------------
/docs/Project Branch, Commit Convetion.md:
--------------------------------------------------------------------------------
1 | # `우리팀의 Branch, Commit Convention을 어떻게 진행하고 있을까?`
2 |
3 | YAPP 18기에서 진행하는 `백엔드 iOS 1팀`은 협업 툴로 `JIRA`를 사용하고 있습니다. JIRA는 처음 사용해봤는데 되게 편리했습니다.
4 | 저희팀은 어떻게 사용을 했는가 하면, 현재 각자 수행하고 있는 이슈들을 등록해서 그 이슈를 기반으로 브랜치를 만들고, 커밋 컨벤션을 정의해서 작업을 진행하였습니다.
5 |
6 | 
7 |
8 | 위에서 보이시는 것처럼 백엔드 파트 뿐만 아니라 iOS 파트와 같이 사용하고 있기 때문에 다른 파트들도 어떻게 진행되고 있는지를 쉽게 파악할 수 있었습니다.
9 | 또한 누가 어떤 이슈를 남겼는지도 쉽게 알 수 있기 때문에 편리하고 생상성 높게 협업을 진행할 수 있었습니다.
10 |
11 | 그리고 위에 이슈를 만들 때마다 `YITEAM-이슈번호`로 생성이 되는데요. 저희 iOS 1팀 백엔드는 `JIRA 이슈` 번호를 기반으로 branch를 작성하였습니다. 기존에 프로젝트를 했을 때는 `feature/~~`, `bug/~~` 등등 다양하게 브랜치 역할에 맡게 브랜치를 만들었지만 이번에는 JIRA 이슈 기반으로 브챈치 컨벤션을 정해서 해보았습니다.
12 |
13 |
14 |
15 | 
16 |
17 | 실제로도 커밋을 할 때 위와 같이 `커밋 컨벤션`을 유지하면서 프로젝트를 진행하였기에, 커밋과 JIRA 이슈를 보면서 현재 어떤 이슈를 진행 중인지 좀 더 명확하게 알 수 있었습니다.
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAPP-18th/iOS1_Backend/30c3be758e76f43eb86e4ad19a1c2aacfe2ae784/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/scripts/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | CONTAINER_ID=$(docker container ls -f "name=yapp" -q)
4 |
5 | echo "> 컨테이너 ID는 무엇?? ${CONTAINER_ID}"
6 |
7 | if [ -z ${CONTAINER_ID} ]
8 | then
9 | echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ec2-user/yapp/deploy.log
10 | else
11 | echo "> docker stop ${CONTAINER_ID}"
12 | sudo docker stop ${CONTAINER_ID}
13 | echo "> docker rm ${CONTAINER_ID}"
14 | sudo docker rm ${CONTAINER_ID}
15 | #sudo docker rmi yapp
16 | sleep 5
17 | fi
18 | # && docker build -t yapp .
19 | cd /home/ec2-user/yapp
20 | docker run --name yapp -d -e active=prod -p 8080:8080 -v $(pwd)/build/libs:/root yapp
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'ios1'
2 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/Ios1Application.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.scheduling.annotation.EnableAsync;
7 | import org.springframework.scheduling.annotation.EnableScheduling;
8 |
9 | @EnableScheduling
10 | @EnableAsync
11 | @EnableCaching
12 | @SpringBootApplication
13 | public class Ios1Application {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(Ios1Application.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/annotation/Auth.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * created by jg 2021/04/11
10 | */
11 | @Target({ElementType.METHOD})
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface Auth {
14 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/annotation/ReAuth.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * created by jg 2021/06/04
10 | */
11 | @Target({ElementType.METHOD})
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface ReAuth {
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/aop/AuthAspect.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.aop;
2 |
3 | import com.yapp.ios1.dto.jwt.JwtPayload;
4 | import com.yapp.ios1.model.user.User;
5 | import com.yapp.ios1.error.exception.jwt.JwtException;
6 | import com.yapp.ios1.error.exception.jwt.JwtExpiredException;
7 | import com.yapp.ios1.service.jwt.JwtIssueService;
8 | import com.yapp.ios1.service.jwt.JwtService;
9 | import com.yapp.ios1.service.user.UserFindService;
10 | import io.jsonwebtoken.ExpiredJwtException;
11 | import io.jsonwebtoken.MalformedJwtException;
12 | import io.jsonwebtoken.UnsupportedJwtException;
13 | import io.jsonwebtoken.security.SignatureException;
14 | import lombok.RequiredArgsConstructor;
15 | import org.aspectj.lang.ProceedingJoinPoint;
16 | import org.aspectj.lang.annotation.Around;
17 | import org.aspectj.lang.annotation.Aspect;
18 | import org.springframework.stereotype.Component;
19 |
20 | import javax.servlet.http.HttpServletRequest;
21 |
22 | /**
23 | * created by jg 2021/04/11
24 | */
25 | @RequiredArgsConstructor
26 | @Aspect
27 | @Component
28 | public class AuthAspect {
29 |
30 | private static final String AUTHORIZATION = "accessToken";
31 | private static final String REAUTHORIZATION = "refreshToken";
32 |
33 | private final JwtService jwtService;
34 | private final JwtIssueService jwtIssueService;
35 | private final UserFindService userFindService;
36 | private final HttpServletRequest httpServletRequest;
37 |
38 | @Around("@annotation(com.yapp.ios1.annotation.Auth)")
39 | public Object accessToken(final ProceedingJoinPoint pjp) throws Throwable {
40 | try {
41 | String accessToken = httpServletRequest.getHeader(AUTHORIZATION);
42 | JwtPayload payload = jwtService.getPayload(accessToken);
43 | User user = userFindService.getUser(payload.getId());
44 | UserContext.USER_CONTEXT.set(new JwtPayload(user.getId()));
45 | return pjp.proceed();
46 | } catch (SignatureException | ExpiredJwtException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException e) {
47 | throw new JwtException();
48 | }
49 | }
50 |
51 | @Around("@annotation(com.yapp.ios1.annotation.ReAuth)")
52 | public Object refreshToken(final ProceedingJoinPoint pjp) throws Throwable {
53 | try {
54 | String refreshToken = httpServletRequest.getHeader(REAUTHORIZATION);
55 | JwtPayload payload = jwtService.getPayload(refreshToken);
56 | User user = userFindService.getUser(payload.getId());
57 |
58 | String dbRefreshToken = jwtIssueService.getRefreshTokenByUserId(user.getId());
59 | checkRefreshTokenExpired(dbRefreshToken, refreshToken);
60 | UserContext.USER_CONTEXT.set(new JwtPayload(user.getId()));
61 | return pjp.proceed();
62 | } catch (SignatureException | ExpiredJwtException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException e) {
63 | throw new JwtException();
64 | }
65 | }
66 |
67 | private void checkRefreshTokenExpired(String dbRefreshToken, String refreshToken) {
68 | if (!dbRefreshToken.equals(refreshToken)) {
69 | throw new JwtExpiredException();
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/aop/UserContext.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.aop;
2 |
3 | import com.yapp.ios1.dto.jwt.JwtPayload;
4 | import com.yapp.ios1.error.exception.jwt.JwtException;
5 |
6 | /**
7 | * created by ayoung 2021/05/01
8 | */
9 | public class UserContext {
10 |
11 | public static final ThreadLocal USER_CONTEXT = new ThreadLocal<>();
12 |
13 | public static Long getCurrentUserId() {
14 | if (UserContext.USER_CONTEXT.get() != null) {
15 | return UserContext.USER_CONTEXT.get().getId();
16 | }
17 |
18 | throw new JwtException();
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/AsyncConfig.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
6 |
7 | import java.util.concurrent.Executor;
8 | import java.util.concurrent.ThreadPoolExecutor;
9 |
10 | /**
11 | * created by jg 2021/05/21
12 | */
13 | @Configuration
14 | public class AsyncConfig {
15 |
16 | @Bean("asyncTask")
17 | public Executor threadPoolExecutor() {
18 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
19 | executor.setThreadNamePrefix("asyncTask-"); // thread 이름 설정
20 | executor.setCorePoolSize(5); // 동시에 실행시킬 쓰래드의 개수를 의미
21 | executor.setMaxPoolSize(100); // 쓰레드 풀의 최대 사이즈
22 | executor.setQueueCapacity(0); // 쓰레드 풀 큐의 사이즈. corePoolSize 개수를 넘어서는 task가 들어왔을 때
23 | executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
24 | return executor;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/CacheKey.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config;
2 |
3 | /**
4 | * created by ayoung 2021/06/03
5 | */
6 | public class CacheKey {
7 |
8 | public static final String TOKEN = "token";
9 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/RedisCacheConfig.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.redis.cache.CacheKeyPrefix;
7 | import org.springframework.data.redis.cache.RedisCacheConfiguration;
8 | import org.springframework.data.redis.cache.RedisCacheManager;
9 | import org.springframework.data.redis.connection.RedisConnectionFactory;
10 | import org.springframework.data.redis.serializer.RedisSerializationContext;
11 | import org.springframework.data.redis.serializer.StringRedisSerializer;
12 |
13 | import java.time.Duration;
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | /**
18 | * created by ayoung 2021/06/03
19 | */
20 | @Configuration
21 | public class RedisCacheConfig {
22 |
23 | @Value("${jwt.refreshToken.validTime}")
24 | private Long REFRESH_VALID_TIME;
25 |
26 | @Bean(name = "cacheManager")
27 | public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
28 |
29 | RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
30 | .disableCachingNullValues()
31 | .computePrefixWith(CacheKeyPrefix.simple())
32 | .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
33 |
34 | Map cacheConfigurations = new HashMap<>();
35 | cacheConfigurations.put(CacheKey.TOKEN, RedisCacheConfiguration.defaultCacheConfig()
36 | .entryTtl(Duration.ofMillis(REFRESH_VALID_TIME)));
37 |
38 | return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(configuration)
39 | .withInitialCacheConfigurations(cacheConfigurations).build();
40 | }
41 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/RestTemplateConfig.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config;
2 |
3 | import org.springframework.boot.web.client.RestTemplateBuilder;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.http.client.BufferingClientHttpRequestFactory;
7 | import org.springframework.http.client.SimpleClientHttpRequestFactory;
8 | import org.springframework.http.converter.StringHttpMessageConverter;
9 | import org.springframework.web.client.RestTemplate;
10 |
11 | import java.nio.charset.Charset;
12 | import java.nio.charset.StandardCharsets;
13 | import java.time.Duration;
14 |
15 | /**
16 | * created by ayoung 2021/05/06
17 | */
18 | @Configuration
19 | public class RestTemplateConfig {
20 |
21 | @Bean
22 | public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
23 | return restTemplateBuilder
24 | .requestFactory(() -> new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()))
25 | .setConnectTimeout(Duration.ofMillis(5000)) // connection-timeout
26 | .setReadTimeout(Duration.ofMillis(5000)) // read-timeout
27 | .additionalMessageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8))
28 | .build();
29 | }
30 | }
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 |
11 | /**
12 | * created by ayoung 2021/04/15
13 | */
14 | @EnableWebSecurity
15 | @Configuration
16 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
17 |
18 | @Bean
19 | public PasswordEncoder getPasswordEncoder() {
20 | return new BCryptPasswordEncoder();
21 | }
22 |
23 | @Override
24 | protected void configure(HttpSecurity http) throws Exception {
25 | http.authorizeRequests()
26 | .antMatchers("/api/v2/**", "/health", "/swagger-ui.html", "/swagger/**",
27 | "/swagger-resources/**", "/webjars/**", "/v2/api-docs").permitAll()
28 | .anyRequest().authenticated()
29 | .and()
30 | .csrf().disable()
31 | .formLogin();
32 | }
33 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config;
2 |
3 | import com.google.common.collect.Lists;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import springfox.documentation.builders.ApiInfoBuilder;
7 | import springfox.documentation.builders.PathSelectors;
8 | import springfox.documentation.builders.RequestHandlerSelectors;
9 | import springfox.documentation.service.ApiInfo;
10 | import springfox.documentation.service.ApiKey;
11 | import springfox.documentation.service.AuthorizationScope;
12 | import springfox.documentation.service.SecurityReference;
13 | import springfox.documentation.spi.DocumentationType;
14 | import springfox.documentation.spi.service.contexts.SecurityContext;
15 | import springfox.documentation.spring.web.plugins.Docket;
16 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
17 |
18 | import java.util.List;
19 |
20 | /**
21 | * created by ayoung 2021/05/03
22 | */
23 | @Configuration
24 | @EnableSwagger2
25 | public class SwaggerConfig {
26 |
27 | @Bean
28 | public Docket api() {
29 | return new Docket(DocumentationType.SWAGGER_2)
30 | .apiInfo(apiInfo())
31 | .select()
32 | .apis(RequestHandlerSelectors.any())
33 | .paths(PathSelectors.ant("/api/v2/**"))
34 | .build()
35 | .securityContexts(Lists.newArrayList(securityContext())) // JWT 인증 기능 추가
36 | .securitySchemes(Lists.newArrayList(apiKey()));
37 | }
38 |
39 | private ApiInfo apiInfo() {
40 | String applicationName = "Buok API Documents";
41 | return new ApiInfoBuilder()
42 | .title(applicationName)
43 | .build();
44 | }
45 |
46 | private ApiKey apiKey() {
47 | return new ApiKey("JWT", "accessToken", "header");
48 | }
49 |
50 | private SecurityContext securityContext() {
51 | return SecurityContext.builder().securityReferences(defaultAuth()).build();
52 | }
53 |
54 | List defaultAuth() {
55 | AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
56 | AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
57 | authorizationScopes[0] = authorizationScope;
58 | return Lists.newArrayList(new SecurityReference("JWT", authorizationScopes));
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/filter/CustomServletWrappingFilter.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config.filter;
2 |
3 | import org.springframework.stereotype.Component;
4 | import org.springframework.web.filter.OncePerRequestFilter;
5 | import org.springframework.web.util.ContentCachingRequestWrapper;
6 | import org.springframework.web.util.ContentCachingResponseWrapper;
7 |
8 | import javax.servlet.FilterChain;
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 |
14 | /**
15 | * created by jg 2021/06/27
16 | */
17 | @Component
18 | public class CustomServletWrappingFilter extends OncePerRequestFilter {
19 |
20 | @Override
21 | protected void doFilterInternal(HttpServletRequest request,
22 | HttpServletResponse response,
23 | FilterChain chain) throws ServletException, IOException {
24 | ContentCachingRequestWrapper wrappingRequest = new ContentCachingRequestWrapper(request);
25 | ContentCachingResponseWrapper wrappingResponse = new ContentCachingResponseWrapper(response);
26 |
27 | chain.doFilter(wrappingRequest, wrappingResponse);
28 |
29 | wrappingResponse.copyBodyToResponse();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/interceptor/InterceptorConfig.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config.interceptor;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7 |
8 | /**
9 | * created by jg 2021/06/27
10 | */
11 | @RequiredArgsConstructor
12 | @Configuration
13 | public class InterceptorConfig implements WebMvcConfigurer {
14 |
15 | private final LoggingInterceptor loggingInterceptor;
16 |
17 | @Override
18 | public void addInterceptors(InterceptorRegistry registry) {
19 | registry.addInterceptor(loggingInterceptor);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/config/interceptor/LoggingInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.config.interceptor;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import lombok.RequiredArgsConstructor;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.stereotype.Component;
7 | import org.springframework.web.servlet.HandlerInterceptor;
8 | import org.springframework.web.util.ContentCachingRequestWrapper;
9 | import org.springframework.web.util.ContentCachingResponseWrapper;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 |
14 | /**
15 | * created by jg 2021/06/27
16 | */
17 | @RequiredArgsConstructor
18 | @Slf4j
19 | @Component
20 | public class LoggingInterceptor implements HandlerInterceptor {
21 |
22 | private final ObjectMapper objectMapper;
23 |
24 | @Override
25 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
26 | String[] requestURI = request.getRequestURI().split("/");
27 | if (requestURI[1].equals("api") && requestURI[2].equals("v2")) {
28 | final String requestMethod = request.getMethod();
29 |
30 | log.error("==============");
31 | log.error("Request URL : " + request.getRequestURL() + "\n" +
32 | "Query String : " + request.getQueryString() + " || Request Method : " + requestMethod);
33 |
34 | if (requestMethod.equals("POST")) {
35 | final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request;
36 | final ContentCachingResponseWrapper cachingResponse = (ContentCachingResponseWrapper) response;
37 |
38 | log.error(String.format("Request Body : %s", objectMapper.readTree(cachingRequest.getContentAsByteArray())));
39 | log.error(String.format("Response Body : %s", objectMapper.readTree(cachingResponse.getContentAsByteArray())));
40 | }
41 | log.error("==============");
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/AlarmController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.dto.notification.NotificationForOneDto;
5 | import com.yapp.ios1.dto.notification.NotificationTestDto;
6 | import com.yapp.ios1.service.alarm.AlarmService;
7 | import com.yapp.ios1.annotation.Auth;
8 | import com.yapp.ios1.aop.UserContext;
9 | import com.yapp.ios1.service.alarm.FirebaseService;
10 | import io.swagger.annotations.Api;
11 | import io.swagger.annotations.ApiOperation;
12 | import lombok.RequiredArgsConstructor;
13 | import org.springframework.http.HttpStatus;
14 | import org.springframework.http.ResponseEntity;
15 | import org.springframework.web.bind.annotation.*;
16 |
17 | import static com.yapp.ios1.message.ResponseMessage.DELETE_ALARM_LOG;
18 | import static com.yapp.ios1.message.ResponseMessage.GET_ALARM_LOG;
19 |
20 | /**
21 | * created by jg 2021/05/24
22 | */
23 | @Api(tags = "Alarm")
24 | @RequiredArgsConstructor
25 | @RestController
26 | @RequestMapping("/api/v2/alarm")
27 | public class AlarmController {
28 |
29 | private final AlarmService alarmService;
30 | private final FirebaseService firebaseService;
31 |
32 | @ApiOperation("알람 로그 조회")
33 | @Auth
34 | @GetMapping("")
35 | public ResponseEntity alarmLog() {
36 | Long userId = UserContext.getCurrentUserId();
37 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_ALARM_LOG, alarmService.getAlarmLog(userId)));
38 | }
39 |
40 | @ApiOperation("알람 로그 삭제 (alarmStatus: 1(전체 알람), 2(친구 알람))")
41 | @Auth
42 | @DeleteMapping("/{alarmId}")
43 | public ResponseEntity deleteAlarm(@PathVariable Long alarmId, @RequestParam("alarm_status") int alarmStatus) {
44 | Long userId = UserContext.getCurrentUserId();
45 | alarmService.deleteAlarm(alarmId, userId, alarmStatus);
46 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, DELETE_ALARM_LOG));
47 | }
48 |
49 | // @ApiOperation("푸시 알림 테스트")
50 | // @PostMapping("/test")
51 | // public ResponseEntity alarmTest(@RequestBody NotificationTestDto requestDto) {
52 | // NotificationForOneDto notificationForOne = NotificationForOneDto.builder()
53 | // .title(requestDto.getTitle())
54 | // .message(requestDto.getMessage())
55 | // .deviceToken(requestDto.getDeviceToken())
56 | // .build();
57 | // firebaseService.sendByTokenForOne(notificationForOne);
58 | // return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, "푸시 알림 보냄"));
59 | // }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/BucketController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.controller.dto.bucket.BucketRequestDto;
5 | import com.yapp.ios1.service.bucket.BucketFindService;
6 | import com.yapp.ios1.service.bucket.BucketService;
7 | import com.yapp.ios1.annotation.Auth;
8 | import com.yapp.ios1.aop.UserContext;
9 | import io.swagger.annotations.Api;
10 | import io.swagger.annotations.ApiOperation;
11 | import lombok.RequiredArgsConstructor;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.http.ResponseEntity;
14 | import org.springframework.web.bind.annotation.*;
15 |
16 | import javax.validation.Valid;
17 |
18 | import static com.yapp.ios1.message.ResponseMessage.*;
19 |
20 | /**
21 | * created by jg 2021/05/05
22 | */
23 | @Api(tags = "Bucket")
24 | @RequiredArgsConstructor
25 | @RestController
26 | @RequestMapping("/api/v2/buckets")
27 | public class BucketController {
28 |
29 | private final BucketService bucketService;
30 | private final BucketFindService bucketFindService;
31 |
32 | /**
33 | * @INFO state 1(전체), 2(예정), 3(진행 중), 4(완료), 5(실패)
34 | * @INFO category 1(전체), 2(여행), 3(취미), 4(소유), 5(재정), 6(건강)
35 | 7(목표), 8(조직), 9(봉사), 10(기타)
36 | * @INFO sortI= 1(작성 순), sortId = 2(가나다 순)
37 | */
38 | @ApiOperation("홈 화면 버킷 조회")
39 | @Auth
40 | @GetMapping("")
41 | public ResponseEntity homeBucket(@RequestParam("state") int bucketState,
42 | @RequestParam("category") int category,
43 | @RequestParam("sort") int sort) {
44 | Long userId = UserContext.getCurrentUserId();
45 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_BUCKET_LIST,
46 | bucketFindService.getHomeBucketList(bucketState, category, userId, sort)));
47 | }
48 |
49 | @ApiOperation("버킷 상세 조회")
50 | @GetMapping("/{bucketId}")
51 | public ResponseEntity myBucket(@PathVariable Long bucketId) {
52 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_BUCKET_DETAIL, bucketFindService.getBucketDetail(bucketId)));
53 | }
54 |
55 | // bucketStateId 2(예정), 3(진행 중), 4(완료), 5(실패)
56 | @ApiOperation("버킷 상태 변경")
57 | @Auth
58 | @PutMapping("/{bucketId}/state/{bucketStateId}")
59 | public ResponseEntity updateBucketState(@PathVariable Long bucketId,
60 | @PathVariable int bucketStateId) {
61 | Long userId = UserContext.getCurrentUserId();
62 | bucketService.updateBucketState(userId, bucketId, bucketStateId);
63 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, UPDATE_BUCKET_STATE));
64 | }
65 |
66 | @ApiOperation("버킷 핀 설정 or 해제")
67 | @Auth
68 | @PutMapping("/{bucketId}/fin")
69 | public ResponseEntity registerBucketFin(@PathVariable Long bucketId, @RequestParam("state") boolean isFin) {
70 | Long userId = UserContext.getCurrentUserId();
71 | bucketService.setBucketFin(bucketId, userId, isFin);
72 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, REGISTER_BUCKET_FIN_SUCCESS));
73 | }
74 |
75 | @ApiOperation("버킷 등록")
76 | @Auth
77 | @PostMapping("")
78 | public ResponseEntity registerBucket(@RequestBody @Valid BucketRequestDto bucket) {
79 | bucket.setUserId(UserContext.getCurrentUserId());
80 | bucketService.saveBucket(bucket);
81 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.CREATED, REGISTER_BUCKET_SUCCESS));
82 | }
83 |
84 | @ApiOperation("버킷 수정")
85 | @Auth
86 | @PutMapping("/{bucketId}")
87 | public ResponseEntity updateBucket(@PathVariable Long bucketId, @RequestBody @Valid BucketRequestDto requestDto) {
88 | bucketService.updateBucket(bucketId, requestDto, UserContext.getCurrentUserId());
89 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, UPDATE_BUCKET_SUCCESS));
90 | }
91 |
92 | @ApiOperation("북마크 설정 or 해제")
93 | @Auth
94 | @PutMapping("/{bucketId}/bookmark")
95 | public ResponseEntity setBookmark(@PathVariable("bucketId") Long bucketId, @RequestParam("state") boolean isBookmark) {
96 | Long userId = UserContext.getCurrentUserId();
97 | bucketService.saveBookmark(bucketId, userId, isBookmark);
98 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, UPDATE_BUCKET_SUCCESS));
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/EmailController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.controller.dto.email.EmailCodeDto;
4 | import com.yapp.ios1.controller.dto.email.EmailDto;
5 | import com.yapp.ios1.dto.ResponseDto;
6 | import com.yapp.ios1.dto.jwt.JwtPayload;
7 | import com.yapp.ios1.service.EmailService;
8 | import com.yapp.ios1.service.jwt.JwtIssueService;
9 | import io.swagger.annotations.Api;
10 | import io.swagger.annotations.ApiOperation;
11 | import lombok.RequiredArgsConstructor;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.http.ResponseEntity;
14 | import org.springframework.web.bind.annotation.PostMapping;
15 | import org.springframework.web.bind.annotation.RequestBody;
16 | import org.springframework.web.bind.annotation.RequestMapping;
17 | import org.springframework.web.bind.annotation.RestController;
18 |
19 | import javax.validation.Valid;
20 |
21 | import static com.yapp.ios1.message.ResponseMessage.EMAIL_AUTH_SUCCESS;
22 | import static com.yapp.ios1.message.ResponseMessage.EMAIL_SEND_SUCCESS;
23 |
24 | /**
25 | * created by ayoung 2021/05/30
26 | */
27 | @Api(tags = "Email")
28 | @RequiredArgsConstructor
29 | @RestController
30 | @RequestMapping("/api/v2/email")
31 | public class EmailController {
32 |
33 | private final EmailService emailService;
34 | private final JwtIssueService jwtIssueService;
35 |
36 | @ApiOperation("이메일 인증 코드 전송")
37 | @PostMapping("/send")
38 | public ResponseEntity sendEmail(@RequestBody @Valid EmailDto email) {
39 | emailService.sendEmailMessage(email.getEmail());
40 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, EMAIL_SEND_SUCCESS));
41 | }
42 |
43 | @ApiOperation("인증 코드 검증")
44 | @PostMapping("/verify")
45 | public ResponseEntity verifyCode(@RequestBody @Valid EmailCodeDto code) {
46 | Long userId = emailService.getUserIdByCode(code.getCode());
47 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, EMAIL_AUTH_SUCCESS, jwtIssueService.createAccessToken(new JwtPayload(userId))));
48 | }
49 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/FriendController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.annotation.Auth;
4 | import com.yapp.ios1.aop.UserContext;
5 | import com.yapp.ios1.dto.ResponseDto;
6 | import com.yapp.ios1.model.user.Friend;
7 | import com.yapp.ios1.service.FriendService;
8 | import io.swagger.annotations.Api;
9 | import io.swagger.annotations.ApiOperation;
10 | import lombok.RequiredArgsConstructor;
11 | import org.springframework.http.HttpStatus;
12 | import org.springframework.http.ResponseEntity;
13 | import org.springframework.web.bind.annotation.*;
14 | import springfox.documentation.annotations.ApiIgnore;
15 |
16 | import java.util.List;
17 |
18 | import static com.yapp.ios1.message.ResponseMessage.*;
19 |
20 | /**
21 | * created by jg 2021/05/21
22 | */
23 | @Api(tags = "Friend")
24 | @RequiredArgsConstructor
25 | @RestController
26 | @RequestMapping("/api/v2")
27 | public class FriendController {
28 |
29 | private final FriendService friendService;
30 |
31 | @ApiOperation("친구 요청")
32 | @Auth
33 | @PostMapping("/friend/{friendId}/request")
34 | public ResponseEntity followRequest(@PathVariable Long friendId) {
35 | Long myUserId = UserContext.getCurrentUserId();
36 | friendService.requestFollow(myUserId, friendId);
37 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.CREATED, FRIEND_REQUEST));
38 | }
39 |
40 | @ApiOperation("친구 요청 수락, 거절")
41 | @Auth
42 | @PostMapping("/friend/{friendId}/{alarmId}")
43 | public ResponseEntity followAccept(@PathVariable Long friendId,
44 | @PathVariable Long alarmId,
45 | @RequestParam("accept") boolean isAccept) {
46 | Long myUserId = UserContext.getCurrentUserId();
47 | friendService.checkFollowAccept(isAccept, myUserId, friendId, alarmId);
48 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.CREATED, FRIEND_MESSAGE, isAccept));
49 | }
50 |
51 | @ApiOperation("친구 리스트")
52 | @GetMapping("/users/{userId}/friends")
53 | public ResponseEntity getFriendList(@PathVariable Long userId) {
54 | List friendList = friendService.getFriendList(userId);
55 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_FRIEND_LIST, friendList));
56 | }
57 |
58 | @Auth
59 | @ApiOperation("친구 끊기")
60 | @DeleteMapping("/friend/{friendId}")
61 | public ResponseEntity deleteFriend(@PathVariable Long friendId) {
62 | Long myUserId = UserContext.getCurrentUserId();
63 | friendService.deleteFriend(myUserId, friendId);
64 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, FRIEND_DELETE));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/HealthController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 | import springfox.documentation.annotations.ApiIgnore;
6 |
7 | /**
8 | * created by jg 2021/06/02
9 | */
10 | @RestController
11 | public class HealthController {
12 |
13 | // 로드 밸런서 용
14 | @ApiIgnore
15 | @GetMapping("/health")
16 | public String loadBalancer() {
17 | return "health";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/OauthController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.dto.user.UserStatusDto;
5 | import com.yapp.ios1.controller.dto.user.social.SocialLoginDto;
6 | import com.yapp.ios1.controller.dto.user.social.SocialType;
7 | import com.yapp.ios1.service.OauthService;
8 | import io.swagger.annotations.Api;
9 | import lombok.RequiredArgsConstructor;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.*;
13 |
14 | import javax.validation.Valid;
15 |
16 | import static com.yapp.ios1.message.ResponseMessage.LOGIN_SUCCESS;
17 |
18 | /**
19 | * created by ayoung 2021/05/04
20 | */
21 | @RequiredArgsConstructor
22 | @Slf4j
23 | @RestController
24 | @RequestMapping("/api/v2/social")
25 | @Api(tags = "Social Login")
26 | public class OauthController {
27 |
28 | private final OauthService oauthService;
29 |
30 | @PostMapping("/{social_type}")
31 | public ResponseEntity socialLogin(@PathVariable("social_type") SocialType socialType,
32 | @RequestBody @Valid SocialLoginDto socialDto) {
33 | UserStatusDto statusDto = oauthService.getSocialUser(socialType.name(), socialDto);
34 | return ResponseEntity.ok(ResponseDto.of(statusDto.getStatus(), LOGIN_SUCCESS, statusDto.getTokenDto()));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/ProfileController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.annotation.Auth;
4 | import com.yapp.ios1.aop.UserContext;
5 | import com.yapp.ios1.controller.dto.user.ProfileUpdateDto;
6 | import com.yapp.ios1.dto.ResponseDto;
7 | import com.yapp.ios1.service.user.ProfileService;
8 | import io.swagger.annotations.Api;
9 | import io.swagger.annotations.ApiOperation;
10 | import lombok.RequiredArgsConstructor;
11 | import org.springframework.http.HttpStatus;
12 | import org.springframework.http.ResponseEntity;
13 | import org.springframework.web.bind.annotation.*;
14 |
15 | import static com.yapp.ios1.message.ResponseMessage.GET_PROFILE_SUCCESS;
16 | import static com.yapp.ios1.message.ResponseMessage.UPDATE_PROFILE_SUCCESS;
17 |
18 | /**
19 | * created by jg 2021/06/11
20 | */
21 | @Api(tags = "Profile")
22 | @RequiredArgsConstructor
23 | @RestController
24 | @RequestMapping("/api/v2/profile") // TODO 뭐가 좋을지 생각
25 | public class ProfileController {
26 |
27 | private final ProfileService profileService;
28 |
29 | @ApiOperation("프로필 가져오기")
30 | @Auth
31 | @GetMapping("")
32 | public ResponseEntity getProfile() {
33 | Long userId = UserContext.getCurrentUserId();
34 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_PROFILE_SUCCESS, profileService.getProfile(userId)));
35 | }
36 |
37 | @ApiOperation("프로필 수정")
38 | @Auth
39 | @PutMapping("")
40 | public ResponseEntity updateProfile(@RequestBody ProfileUpdateDto profile) {
41 | Long userId = UserContext.getCurrentUserId();
42 | profileService.updateProfile(profile, userId);
43 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, UPDATE_PROFILE_SUCCESS));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/S3Controller.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.service.S3Service;
5 | import com.yapp.ios1.annotation.Auth;
6 | import com.yapp.ios1.aop.UserContext;
7 | import io.swagger.annotations.Api;
8 | import io.swagger.annotations.ApiOperation;
9 | import lombok.RequiredArgsConstructor;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.*;
13 | import org.springframework.web.multipart.MultipartFile;
14 |
15 | import static com.yapp.ios1.message.ResponseMessage.NOT_EXIST_IMAGE;
16 | import static com.yapp.ios1.message.ResponseMessage.UPLOAD_IMAGE_SUCCESS;
17 |
18 | /**
19 | * created by ayoung 2021/03/29
20 | */
21 | @Api(tags = "Image Upload")
22 | @RequiredArgsConstructor
23 | @RestController
24 | @RequestMapping("/api/v2")
25 | public class S3Controller {
26 |
27 | private final S3Service s3Service;
28 |
29 | @ApiOperation("이미지 url 배열 리턴")
30 | @Auth
31 | @PostMapping("/images")
32 | public ResponseEntity registerBucketImageList(@RequestParam(value = "image") MultipartFile[] imageList) {
33 | if (imageList == null) {
34 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.BAD_REQUEST, NOT_EXIST_IMAGE));
35 | }
36 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, UPLOAD_IMAGE_SUCCESS, s3Service.upload(imageList, UserContext.getCurrentUserId())));
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/SearchController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.service.SearchService;
5 | import com.yapp.ios1.annotation.Auth;
6 | import com.yapp.ios1.aop.UserContext;
7 | import io.swagger.annotations.Api;
8 | import io.swagger.annotations.ApiOperation;
9 | import lombok.RequiredArgsConstructor;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 | import org.springframework.web.bind.annotation.RequestParam;
15 | import org.springframework.web.bind.annotation.RestController;
16 |
17 | import static com.yapp.ios1.message.ResponseMessage.NOT_FOUND_SEARCH_TYPE;
18 | import static com.yapp.ios1.message.ResponseMessage.SUCCESS_SEARCH;
19 |
20 | /**
21 | * created by jg 2021/05/17
22 | */
23 | @Api(tags = "Search")
24 | @RequiredArgsConstructor
25 | @RestController
26 | @RequestMapping("/api/v2")
27 | public class SearchController {
28 |
29 | private final SearchService searchService;
30 |
31 | @ApiOperation("검색, type = my(마이북), user(유저), mark(북마크) 검색, keyword = 검색키워드")
32 | @Auth
33 | @GetMapping("/search")
34 | public ResponseEntity search(@RequestParam("type") String type,
35 | @RequestParam("keyword") String keyword) {
36 | ResponseDto responseDto = ResponseDto.of(HttpStatus.OK, SUCCESS_SEARCH);
37 | Long userId = UserContext.getCurrentUserId();
38 |
39 | switch (type) {
40 | case "my":
41 | responseDto.setData(searchService.searchMyBook(keyword, userId));
42 | break;
43 | case "user":
44 | responseDto.setData(searchService.searchUser(keyword, userId));
45 | break;
46 | case "mark":
47 | responseDto.setData(searchService.searchBookMark(keyword, userId));
48 | break;
49 | default:
50 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.BAD_REQUEST, NOT_FOUND_SEARCH_TYPE));
51 | }
52 |
53 | return ResponseEntity.ok(responseDto);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/TokenController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.dto.jwt.JwtPayload;
5 | import com.yapp.ios1.service.jwt.JwtService;
6 | import com.yapp.ios1.service.jwt.JwtIssueService;
7 | import com.yapp.ios1.annotation.ReAuth;
8 | import com.yapp.ios1.aop.UserContext;
9 | import io.swagger.annotations.Api;
10 | import io.swagger.annotations.ApiOperation;
11 | import lombok.RequiredArgsConstructor;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.http.ResponseEntity;
14 | import org.springframework.web.bind.annotation.*;
15 |
16 | import static com.yapp.ios1.message.ResponseMessage.REISSUE_TOKEN_SUCCESS;
17 |
18 | /**
19 | * created by jg 2021/05/05
20 | */
21 | @Api(tags = "Token")
22 | @RequiredArgsConstructor
23 | @RestController
24 | @RequestMapping("/api/v2")
25 | public class TokenController {
26 |
27 | private final JwtService jwtService;
28 | private final JwtIssueService jwtIssueService;
29 |
30 | @ApiOperation("서버 토큰 발급 용")
31 | @GetMapping("/token")
32 | public String getToken() {
33 | return jwtIssueService.createAccessToken(new JwtPayload(157L));
34 | }
35 |
36 | @ApiOperation("토큰 재발급")
37 | @ReAuth
38 | @PostMapping("/token/refresh")
39 | public ResponseEntity reissueToken() {
40 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, REISSUE_TOKEN_SUCCESS, jwtService.createTokenResponse(UserContext.getCurrentUserId())));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.dto.ResponseDto;
4 | import com.yapp.ios1.model.user.User;
5 | import com.yapp.ios1.controller.dto.user.login.PasswordDto;
6 | import com.yapp.ios1.controller.dto.user.login.SignInDto;
7 | import com.yapp.ios1.controller.dto.user.login.SignUpDto;
8 | import com.yapp.ios1.service.jwt.JwtService;
9 | import com.yapp.ios1.service.user.UserService;
10 | import com.yapp.ios1.annotation.Auth;
11 | import com.yapp.ios1.aop.UserContext;
12 | import com.yapp.ios1.validator.UserValidator;
13 | import io.swagger.annotations.Api;
14 | import io.swagger.annotations.ApiOperation;
15 | import lombok.RequiredArgsConstructor;
16 | import lombok.extern.slf4j.Slf4j;
17 | import org.springframework.http.HttpStatus;
18 | import org.springframework.http.ResponseEntity;
19 | import org.springframework.web.bind.annotation.*;
20 |
21 | import javax.validation.Valid;
22 |
23 | import static com.yapp.ios1.message.ResponseMessage.*;
24 |
25 | /**
26 | * created by jg 2021/03/28
27 | */
28 | @Api(tags = "User")
29 | @RequiredArgsConstructor
30 | @Slf4j
31 | @RestController
32 | @RequestMapping("/api/v2/users")
33 | public class UserController {
34 |
35 | private final UserService userService;
36 | private final UserValidator userValidator;
37 | private final JwtService jwtService;
38 |
39 | @ApiOperation("이메일 존재 여부")
40 | @GetMapping("/email-check")
41 | public ResponseEntity emailCheck(@RequestParam String email) {
42 | userValidator.checkEmailDuplicate(email);
43 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, POSSIBLE_EMAIL));
44 | }
45 |
46 | @ApiOperation("닉네임 존재 여부")
47 | @GetMapping("/nickname-check")
48 | public ResponseEntity nicknameCheck(@RequestParam String nickname) {
49 | userValidator.checkNickName(nickname);
50 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, POSSIBLE_NICKNAME));
51 | }
52 |
53 | @ApiOperation("회원가입")
54 | @PostMapping("/signup")
55 | public ResponseEntity signUp(@RequestBody @Valid SignUpDto signUpDto) {
56 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.CREATED, SIGN_UP_SUCCESS, userService.signUp(User.of(signUpDto))));
57 | }
58 |
59 | @ApiOperation("로그인")
60 | @PostMapping("/signin")
61 | public ResponseEntity signIn(@RequestBody @Valid SignInDto signInDto) {
62 | User user = userValidator.checkPassword(signInDto);
63 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, LOGIN_SUCCESS, jwtService.createTokenResponse(user.getId())));
64 | }
65 |
66 | @ApiOperation("비밀번호 재설정")
67 | @Auth
68 | @PutMapping("/password")
69 | public ResponseEntity changePassword(@RequestBody @Valid PasswordDto passwordDto) {
70 | Long userId = UserContext.getCurrentUserId();
71 | userService.changePassword(userId, passwordDto.getPassword());
72 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, CHANGE_PASSWORD_SUCCESS));
73 | }
74 |
75 | @ApiOperation("회원 탈퇴")
76 | @Auth
77 | @DeleteMapping("")
78 | public ResponseEntity deleteUser() {
79 | userService.deleteUser(UserContext.getCurrentUserId());
80 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, DELETE_USER_SUCCESS));
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/UserInfoController.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller;
2 |
3 | import com.yapp.ios1.annotation.Auth;
4 | import com.yapp.ios1.aop.UserContext;
5 | import com.yapp.ios1.dto.ResponseDto;
6 | import com.yapp.ios1.service.user.UserInfoService;
7 | import io.swagger.annotations.Api;
8 | import io.swagger.annotations.ApiOperation;
9 | import lombok.RequiredArgsConstructor;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.PathVariable;
14 | import org.springframework.web.bind.annotation.RequestMapping;
15 | import org.springframework.web.bind.annotation.RestController;
16 |
17 | import static com.yapp.ios1.message.ResponseMessage.GET_MY_INFO;
18 | import static com.yapp.ios1.message.ResponseMessage.GET_USER_INFO;
19 |
20 | /**
21 | * created by ayoung 2021/06/12
22 | */
23 | @Api(tags = "User Info")
24 | @RequiredArgsConstructor
25 | @RestController
26 | @RequestMapping("/api/v2/users")
27 | public class UserInfoController {
28 |
29 | private final UserInfoService userInfoService;
30 |
31 | @ApiOperation("마이 페이지")
32 | @Auth
33 | @GetMapping("/me")
34 | public ResponseEntity getMyInfo() {
35 | Long userId = UserContext.getCurrentUserId();
36 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_MY_INFO, userInfoService.getUserInfo(userId)));
37 | }
38 |
39 | @ApiOperation("사용자 페이지")
40 | @Auth
41 | @GetMapping("/{userId}")
42 | public ResponseEntity getUserInfo(@PathVariable Long userId) {
43 | Long currentUserId = UserContext.getCurrentUserId();
44 | return ResponseEntity.ok(ResponseDto.of(HttpStatus.OK, GET_USER_INFO, userInfoService.getOtherUserInfo(currentUserId, userId)));
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/bucket/BucketRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.bucket;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 |
7 | import javax.validation.constraints.Max;
8 | import javax.validation.constraints.Min;
9 | import javax.validation.constraints.NotBlank;
10 | import javax.validation.constraints.NotNull;
11 | import java.time.LocalDate;
12 | import java.util.List;
13 |
14 | import static com.yapp.ios1.message.ValidMessage.*;
15 |
16 | /**
17 | * created by ayoung 2021/05/08
18 | */
19 | @Getter
20 | @Builder
21 | public class BucketRequestDto {
22 |
23 | @JsonIgnore
24 | private Long id;
25 | @JsonIgnore
26 | private Long userId;
27 | @NotBlank(message = NOT_VALID_BUCKET_NAME)
28 | private String bucketName;
29 | @Min(value = 2, message = NOT_VALID_STATE)
30 | @Max(value = 5, message = NOT_VALID_STATE)
31 | private int bucketState;
32 | @Min(value = 2, message = NOT_VALID_CATEGORY_ID)
33 | @Max(value = 10, message = NOT_VALID_CATEGORY_ID)
34 | private int categoryId;
35 | @NotNull
36 | private LocalDate endDate;
37 | @NotNull
38 | private String content;
39 | @NotNull
40 | private List imageList;
41 | @NotNull
42 | private List tagList;
43 |
44 | public void setUserId(Long userId) {
45 | this.userId = userId;
46 | }
47 |
48 | public void setId(Long id) { this.id = id; }
49 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/email/EmailCodeDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.email;
2 |
3 | import lombok.Getter;
4 |
5 | import javax.validation.constraints.NotBlank;
6 |
7 | /**
8 | * created by ayoung 2021/05/30
9 | */
10 | @Getter
11 | public class EmailCodeDto {
12 | @NotBlank
13 | private String code;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/email/EmailDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.email;
2 |
3 | import lombok.Getter;
4 |
5 | import javax.validation.constraints.Email;
6 | import javax.validation.constraints.NotBlank;
7 |
8 | import static com.yapp.ios1.message.ValidMessage.NOT_VALID_EMAIL;
9 |
10 | /**
11 | * created by ayoung 2021/04/20
12 | */
13 | @Getter
14 | public class EmailDto {
15 | @NotBlank
16 | @Email(message = NOT_VALID_EMAIL)
17 | private String email;
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/user/ProfileUpdateDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.user;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Getter;
6 |
7 | import javax.validation.constraints.NotBlank;
8 | import javax.validation.constraints.NotNull;
9 |
10 | /**
11 | * created by ayoung 2021/05/18
12 | */
13 | @AllArgsConstructor
14 | @Getter
15 | public class ProfileUpdateDto {
16 | @JsonIgnore
17 | private Long userId;
18 | @NotBlank
19 | private String nickname;
20 | @NotNull
21 | private String intro;
22 | @NotNull
23 | private String profileUrl;
24 |
25 | public void setUserId(Long userId) {
26 | this.userId = userId;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/user/login/PasswordDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.user.login;
2 |
3 | import lombok.Getter;
4 |
5 | import javax.validation.constraints.NotBlank;
6 |
7 | /**
8 | * created by ayoung 2021/05/30
9 | */
10 | @Getter
11 | public class PasswordDto {
12 | @NotBlank
13 | private String password;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/user/login/SignInDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.user.login;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 |
6 | import javax.validation.constraints.Email;
7 | import javax.validation.constraints.NotBlank;
8 |
9 | import static com.yapp.ios1.message.ValidMessage.NOT_VALID_EMAIL;
10 |
11 | /**
12 | * created by ayoung 2021/04/15
13 | */
14 | @AllArgsConstructor
15 | @Getter
16 | public class SignInDto {
17 | @NotBlank
18 | @Email(message = NOT_VALID_EMAIL)
19 | private String email;
20 | @NotBlank
21 | private String password;
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/user/login/SignUpDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.user.login;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Getter;
7 |
8 | import javax.validation.constraints.Email;
9 | import javax.validation.constraints.NotBlank;
10 | import javax.validation.constraints.NotNull;
11 |
12 | import static com.yapp.ios1.message.ValidMessage.NOT_VALID_EMAIL;
13 |
14 | /**
15 | * created by ayoung 2021/04/14
16 | */
17 | @AllArgsConstructor
18 | @Builder
19 | @Getter
20 | public class SignUpDto {
21 | @NotBlank
22 | @Email(message = NOT_VALID_EMAIL)
23 | private String email;
24 | @JsonIgnore
25 | private String socialType;
26 | @NotBlank
27 | private String password;
28 | @NotBlank
29 | private String nickname;
30 | @NotNull
31 | private String intro;
32 | @JsonIgnore
33 | private String socialId;
34 | @NotBlank
35 | private String deviceToken;
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/user/social/SocialLoginDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.user.social;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | import javax.validation.constraints.Email;
7 | import javax.validation.constraints.NotBlank;
8 | import javax.validation.constraints.NotNull;
9 |
10 | /**
11 | * created by ayoung 2021/05/25
12 | */
13 | @Getter
14 | public class SocialLoginDto {
15 | @NotNull
16 | @Email
17 | private String email;
18 | @NotBlank
19 | private String socialId;
20 | @NotBlank
21 | private String deviceToken;
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/controller/dto/user/social/SocialType.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.controller.dto.user.social;
2 |
3 | /**
4 | * created by ayoung 2021/05/06
5 | */
6 | public enum SocialType {
7 | apple, google, kakao
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/ResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 | import org.springframework.http.HttpStatus;
7 |
8 | import java.util.Optional;
9 |
10 | /**
11 | * created by ayoung 2021/04/10
12 | */
13 | @Getter
14 | @Setter
15 | @AllArgsConstructor
16 | public class ResponseDto {
17 |
18 | private int status;
19 | private String message;
20 | private Object data;
21 |
22 | public ResponseDto(int status, String message) {
23 | this.status = status;
24 | this.message = message;
25 | }
26 |
27 | public static ResponseDto of(HttpStatus httpStatus, String message) {
28 | int status = Optional.ofNullable(httpStatus)
29 | .orElse(HttpStatus.OK)
30 | .value();
31 | return new ResponseDto(status, message);
32 | }
33 |
34 | public static ResponseDto of(HttpStatus httpStatus, String message, Object data) {
35 | int status = Optional.ofNullable(httpStatus)
36 | .orElse(HttpStatus.OK)
37 | .value();
38 | return new ResponseDto(status, message, data);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/bookmark/BookmarkListDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.bookmark;
2 |
3 | import com.yapp.ios1.model.bookmark.Bookmark;
4 | import lombok.Getter;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * created by ayoung 2021/05/11
10 | * 북마크 Dto
11 | */
12 | @Getter
13 | public class BookmarkListDto {
14 | private List bookmarkList;
15 | private int bookMarkCount;
16 |
17 | public BookmarkListDto(List bookmarkList, int bookMarkCount) {
18 | this.bookmarkList = bookmarkList;
19 | this.bookMarkCount = bookMarkCount;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/bucket/BucketDetailDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.bucket;
2 |
3 | import com.yapp.ios1.model.bucket.Bucket;
4 | import com.yapp.ios1.model.bucket.BucketTimeline;
5 | import com.yapp.ios1.model.image.Image;
6 | import com.yapp.ios1.model.tag.Tag;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Getter;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * created by jg 2021/06/06
14 | * 버킷 하나 조회 Dto
15 | */
16 | @AllArgsConstructor
17 | @Getter
18 | public class BucketDetailDto {
19 | private Bucket bucket;
20 | private List images;
21 | private List tags;
22 | private List bucketTimelines;
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/bucket/BucketHomeDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.bucket;
2 |
3 | import com.yapp.ios1.model.bucket.Bucket;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * created by jg 2021/05/09
11 | * 홈 화면 Dto
12 | */
13 | @Builder
14 | @Getter
15 | public class BucketHomeDto {
16 | private List buckets;
17 | private int bucketCount;
18 | private boolean isAlarmCheck;
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/jwt/JwtPayload.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.jwt;
2 |
3 | import lombok.Getter;
4 | import lombok.NoArgsConstructor;
5 |
6 | /**
7 | * created by jg 2021/04/11
8 | */
9 | @Getter
10 | @NoArgsConstructor
11 | public class JwtPayload {
12 | private long id;
13 |
14 | public JwtPayload(long id) {
15 | this.id = id;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/jwt/RefreshTokenDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.jwt;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by ayoung 2021/06/03
7 | */
8 | @Getter
9 | public class RefreshTokenDto {
10 | private Long userId;
11 | private String refreshToken;
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/jwt/TokenResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.jwt;
2 |
3 | import com.fasterxml.jackson.annotation.JsonFormat;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Getter;
7 |
8 | import java.util.Date;
9 |
10 | /**
11 | * created by ayoung 2021/05/23
12 | */
13 | @AllArgsConstructor
14 | @Getter
15 | @Builder
16 | public class TokenResponseDto {
17 | private String accessToken;
18 | private String refreshToken;
19 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
20 | private Date accessExpiredAt;
21 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
22 | private Date refreshExpiredAt;
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/notification/FcmMessage.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.notification;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 |
7 | @Builder
8 | @AllArgsConstructor
9 | @Getter
10 | public class FcmMessage {
11 | private Message message;
12 |
13 | @Builder
14 | @AllArgsConstructor
15 | @Getter
16 | public static class Message {
17 | private Notification notification;
18 | private String token;
19 | }
20 |
21 | @Builder
22 | @AllArgsConstructor
23 | @Getter
24 | public static class Notification {
25 | private String title;
26 | private String body;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/notification/NotificationDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.notification;
2 |
3 | import lombok.Getter;
4 |
5 | import java.time.LocalDateTime;
6 |
7 | /**
8 | * created by jg 2021/05/17
9 | */
10 | @Getter
11 | public class NotificationDto {
12 | private String title;
13 | private String message;
14 | private LocalDateTime localDateTime;
15 |
16 | public NotificationDto(String title, String message, LocalDateTime localDateTime) {
17 | this.title = title;
18 | this.message = message;
19 | this.localDateTime = localDateTime;
20 | }
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/notification/NotificationForOneDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.notification;
2 |
3 | import lombok.Builder;
4 | import lombok.Getter;
5 |
6 | import java.time.LocalDateTime;
7 |
8 | /**
9 | * created by jg 2021/05/21
10 | */
11 | @Getter
12 | public class NotificationForOneDto extends NotificationDto {
13 | private Long alarmId;
14 | private String deviceToken;
15 |
16 | @Builder
17 | public NotificationForOneDto(String title, String message, LocalDateTime localDateTime, String deviceToken) {
18 | super(title, message, localDateTime);
19 | this.deviceToken = deviceToken;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/notification/NotificationLogDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.notification;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by jg 2021/05/26
7 | */
8 | @Getter
9 | public class NotificationLogDto {
10 | private Long alarmId;
11 | private String title;
12 | private String message;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/notification/NotificationTestDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.notification;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by ayoung 2021/07/02
7 | */
8 | @Getter
9 | public class NotificationTestDto {
10 | private String title;
11 | private String message;
12 | private String deviceToken;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/user/UserInfoDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.user;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.yapp.ios1.dto.bookmark.BookmarkListDto;
5 | import com.yapp.ios1.model.bucket.Bucket;
6 | import com.yapp.ios1.model.user.Profile;
7 | import lombok.Builder;
8 | import lombok.Getter;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * created by ayoung 2021/05/11
14 | * 마이페이지 Dto
15 | */
16 | @Getter
17 | @Builder
18 | public class UserInfoDto {
19 | private Profile user;
20 | private int friendCount;
21 | private int bucketCount;
22 | private BookmarkListDto bookmark;
23 | @JsonInclude(JsonInclude.Include.NON_NULL)
24 | private int isFriend;
25 | @JsonInclude(JsonInclude.Include.NON_NULL)
26 | private List bucket;
27 |
28 | public void setBucket(List bucket) {
29 | this.bucket = bucket;
30 | }
31 |
32 | public void setFriend(int friend) {
33 | this.isFriend = friend;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/dto/user/UserStatusDto.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto.user;
2 |
3 | import com.yapp.ios1.dto.jwt.TokenResponseDto;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Getter;
6 | import org.springframework.http.HttpStatus;
7 |
8 | /**
9 | * created by ayoung 2021/05/05
10 | * 소셜 로그인 로그인, 회원가입 구분하는 Dto
11 | */
12 | @AllArgsConstructor
13 | @Getter
14 | public class UserStatusDto {
15 | private HttpStatus status;
16 | private TokenResponseDto tokenDto;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/enums/AlarmStatus.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.enums;
2 |
3 | /**
4 | * created by jg 2021/06/07
5 | */
6 | public enum AlarmStatus {
7 | WHOLE_ALARM(1), // 전체 알람
8 | FOLLOW_ALARM(2) // 친구 알람
9 | ;
10 | private final int alarmStatus;
11 |
12 | AlarmStatus(int alarmStatus) {
13 | this.alarmStatus = alarmStatus;
14 | }
15 |
16 | public int get() {
17 | return alarmStatus;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/enums/BucketLogStatus.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.enums;
2 |
3 | /**
4 | * created by ayoung 2021/06/28
5 | */
6 | public enum BucketLogStatus {
7 | BUCKET_NAME_LOG(1), // 버킷 이름 로그
8 | BUCKET_END_DATE_LOG(2) // 버킷 완료 날짜 로그
9 | ;
10 | private final int bucketLogStatus;
11 |
12 | BucketLogStatus(int bucketLogStatus) {
13 | this.bucketLogStatus = bucketLogStatus;
14 | }
15 |
16 | public int get() {
17 | return bucketLogStatus;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/enums/BucketStatus.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.enums;
2 |
3 | /**
4 | * created by jg 2021/06/10
5 | */
6 | public enum BucketStatus {
7 | BUCKET_WHOLE(1), // 전체 버킷
8 | BUCKET_EXPECTED(2), // 예정 버킷
9 | BUCKET_ONGOING(3), // 진행 중 버킷
10 | BUCKET_COMPLETE(4), // 완료 버킷
11 | BUCKET_FAIL(5) // 실패 버킷
12 | ;
13 | private final int bucketStatus;
14 |
15 | BucketStatus(int bucketStatus) {
16 | this.bucketStatus = bucketStatus;
17 | }
18 |
19 | public int get() {
20 | return bucketStatus;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/enums/FriendStatus.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.enums;
2 |
3 | /**
4 | * created by jg 2021/05/21
5 | */
6 | public enum FriendStatus {
7 | FRIEND(1), // 친구
8 | REQUEST(2) // 요청 중
9 | ;
10 | private final int friendStatus;
11 |
12 | FriendStatus(int friendStatus) {
13 | this.friendStatus = friendStatus;
14 | }
15 |
16 | public int get() {
17 | return friendStatus;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/ErrorResponse.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import lombok.AccessLevel;
5 | import lombok.Getter;
6 | import lombok.NoArgsConstructor;
7 | import org.springframework.validation.BindingResult;
8 | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 | import java.util.stream.Collectors;
13 |
14 | /**
15 | * created by jg 2021/06/03
16 | */
17 |
18 | @Getter
19 | @NoArgsConstructor(access = AccessLevel.PROTECTED)
20 | public class ErrorResponse {
21 |
22 | private String message;
23 | private int status;
24 | private List errors;
25 | private String code;
26 |
27 | private ErrorResponse(final ErrorCode code, final List errors) {
28 | this.message = code.getMessage();
29 | this.status = code.getStatus();
30 | this.errors = errors;
31 | this.code = code.getCode();
32 | }
33 |
34 | private ErrorResponse(final ErrorCode code) {
35 | this.message = code.getMessage();
36 | this.status = code.getStatus();
37 | this.code = code.getCode();
38 | this.errors = new ArrayList<>();
39 | }
40 |
41 | public static ErrorResponse of(final ErrorCode code, final BindingResult bindingResult) {
42 | return new ErrorResponse(code, FieldError.of(bindingResult));
43 | }
44 |
45 | public static ErrorResponse of(final ErrorCode code) {
46 | return new ErrorResponse(code);
47 | }
48 |
49 | public static ErrorResponse of(final ErrorCode code, final List errors) {
50 | return new ErrorResponse(code, errors);
51 | }
52 |
53 | public static ErrorResponse of(MethodArgumentTypeMismatchException e) {
54 | final String value = e.getValue() == null ? "" : e.getValue().toString();
55 | final List errors = ErrorResponse.FieldError.of(e.getName(), value, e.getErrorCode());
56 | return new ErrorResponse(ErrorCode.INVALID_TYPE_VALUE, errors);
57 | }
58 |
59 | @Getter
60 | @NoArgsConstructor(access = AccessLevel.PROTECTED)
61 | public static class FieldError {
62 | private String field;
63 | private String value;
64 | private String reason;
65 |
66 | private FieldError(final String field, final String value, final String reason) {
67 | this.field = field;
68 | this.value = value;
69 | this.reason = reason;
70 | }
71 |
72 | public static List of(final String field, final String value, final String reason) {
73 | List fieldErrors = new ArrayList<>();
74 | fieldErrors.add(new FieldError(field, value, reason));
75 | return fieldErrors;
76 | }
77 |
78 | private static List of(final BindingResult bindingResult) {
79 | final List fieldErrors = bindingResult.getFieldErrors();
80 | return fieldErrors.stream()
81 | .map(error -> new FieldError(
82 | error.getField(),
83 | error.getRejectedValue() == null ? "" : error.getRejectedValue().toString(),
84 | error.getDefaultMessage()))
85 | .collect(Collectors.toList());
86 | }
87 | }
88 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/GlobalExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error;
2 |
3 | import com.yapp.ios1.error.exception.BusinessException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.http.HttpStatus;
7 | import org.springframework.http.ResponseEntity;
8 | import org.springframework.http.converter.HttpMessageNotReadableException;
9 | import org.springframework.web.HttpRequestMethodNotSupportedException;
10 | import org.springframework.web.bind.MethodArgumentNotValidException;
11 | import org.springframework.web.bind.annotation.ControllerAdvice;
12 | import org.springframework.web.bind.annotation.ExceptionHandler;
13 | import org.springframework.web.client.HttpClientErrorException;
14 | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
15 |
16 | /**
17 | * created by jg 2021/06/03
18 | */
19 | @ControllerAdvice
20 | @Slf4j
21 | public class GlobalExceptionHandler {
22 |
23 | /**
24 | * Bucket 등록할 때 LocalDate 형식 오류
25 | */
26 | @ExceptionHandler(HttpMessageNotReadableException.class)
27 | protected ResponseEntity httpMessageNotReadableException() {
28 | log.error("HttpMessageNotReadableException");
29 | final ErrorResponse response = ErrorResponse.of(ErrorCode.INVALID_TYPE_VALUE);
30 | return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
31 | }
32 |
33 | /**
34 | * javax.validation.Valid or @Validated 으로 binding error 발생시 발생한다.
35 | * HttpMessageConverter 에서 등록한 HttpMessageConverter binding 못할경우 발생
36 | * 주로 @RequestBody, @RequestPart 어노테이션에서 발생
37 | */
38 | @ExceptionHandler(MethodArgumentNotValidException.class)
39 | protected ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
40 | log.error("MethodArgumentNotValidException : " + e.getMessage());
41 | final ErrorResponse response = ErrorResponse.of(ErrorCode.INVALID_INPUT_VALUE, e.getBindingResult());
42 | return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
43 | }
44 |
45 | /**
46 | * enum type 일치하지 않아 binding 못할 경우 발생
47 | * 주로 @RequestParam enum으로 binding 못했을 경우 발생
48 | */
49 | @ExceptionHandler(MethodArgumentTypeMismatchException.class)
50 | protected ResponseEntity handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
51 | log.error("MethodArgumentTypeMismatchException : " + e.getMessage());
52 | final ErrorResponse response = ErrorResponse.of(e);
53 | return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
54 | }
55 |
56 | /**
57 | * 지원하지 않은 HTTP method 호출 할 경우 발생
58 | */
59 | @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
60 | protected ResponseEntity handleHttpRequestMethodNotSupportedException() {
61 | log.error("HttpRequestMethodNotSupportedException");
62 | final ErrorResponse response = ErrorResponse.of(ErrorCode.METHOD_NOT_ALLOWED);
63 | return new ResponseEntity<>(response, HttpStatus.METHOD_NOT_ALLOWED);
64 | }
65 |
66 | /**
67 | * RuntimeException 하위 클래스
68 | */
69 | @ExceptionHandler(BusinessException.class)
70 | protected ResponseEntity handleBusinessException(final BusinessException e) {
71 | log.error("BusinessException : " + e.getMessage());
72 | final ErrorCode errorCode = e.getErrorCode();
73 | final ErrorResponse response = ErrorResponse.of(errorCode);
74 | return new ResponseEntity<>(response, HttpStatus.valueOf(errorCode.getStatus()));
75 | }
76 |
77 | /**
78 | * 예상치 못한 에러 처리
79 | */
80 | @ExceptionHandler(Exception.class)
81 | protected ResponseEntity handleException(final Exception e) {
82 | log.error("Exception : " + e.getMessage());
83 | final ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR);
84 | return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
85 | }
86 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/BusinessException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception;
2 |
3 | /**
4 | * created by jg 2021/06/03
5 | */
6 | public class BusinessException extends RuntimeException {
7 |
8 | private ErrorCode errorCode;
9 |
10 | public BusinessException(String message) {
11 | super(message);
12 | }
13 |
14 | public BusinessException(ErrorCode errorCode) {
15 | super(errorCode.getMessage());
16 | this.errorCode = errorCode;
17 | }
18 |
19 | public ErrorCode getErrorCode() {
20 | return errorCode;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/EntityNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception;
2 |
3 | /**
4 | * created by jg 2021/06/03
5 | */
6 | public class EntityNotFoundException extends BusinessException {
7 |
8 | public EntityNotFoundException(ErrorCode errorCode) {
9 | super(errorCode);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/ErrorCode.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception;
2 |
3 | import com.fasterxml.jackson.annotation.JsonFormat;
4 |
5 | /**
6 | * created by jg 2021/06/03
7 | */
8 | @JsonFormat(shape = JsonFormat.Shape.OBJECT)
9 | public enum ErrorCode {
10 |
11 | // Common
12 | INVALID_INPUT_VALUE(400, "C001", " Invalid Input Value"),
13 | METHOD_NOT_ALLOWED(405, "C002", " Invalid Input Value"),
14 | ENTITY_NOT_FOUND(400, "C003", " Entity Not Found"),
15 | INTERNAL_SERVER_ERROR(500, "C004", "Server Error"),
16 | INVALID_TYPE_VALUE(400, "C005", " Invalid Type Value"),
17 | HANDLE_ACCESS_DENIED(403, "C006", "Access is Denied"),
18 | JSON_WRITE_ERROR(401, "C007", "JSON content that are not pure I/O problems"),
19 |
20 | // JWT
21 | JWT_ERROR(401, "J001", "JWT가 없거나 잘못된 값 입니다"),
22 | JWT_PARSE_ERROR(401, "J002", "JWT Parse Error"),
23 | JWT_EXPIRED_ERROR(401, "J003", "JWT Expired Error"),
24 |
25 | // User
26 | EMAIL_NOT_FOUND(400, "M000", "Email is not Exist"),
27 | EMAIL_DUPLICATION(400, "M001", "Email is Duplication"),
28 | USER_NOT_FOUND(400, "M003", "User is not Exist"),
29 | NICKNAME_EMAIL_DUPLICATION(400, "M004", "NickName is Duplication"),
30 | USER_NOT_AUTHENTICATION(401, "M005", "User is not Authentication"),
31 | PASSWORD_MISMATCH_ERROR(400, "M008", "Password MisMatch Error"),
32 | DEVICE_TOKEN_NOT_FOUND_ERROR(400, "M008", "DeviceToken is not Exist"),
33 |
34 | // Alarm
35 | ALARM_NOT_FOUND_ERROR(400, "N001", "Alarm is not Exist"),
36 |
37 | // Email
38 | EMAIL_SEND_ERROR(500, "P001", "Email Send Error"),
39 |
40 | // AWS
41 | AWS_S3_ERROR(500, "A001", "AWS S3 Error");
42 |
43 |
44 | private final String code;
45 | private final String message;
46 | private int status;
47 |
48 | ErrorCode(final int status, final String code, final String message) {
49 | this.status = status;
50 | this.message = message;
51 | this.code = code;
52 | }
53 |
54 | public String getMessage() {
55 | return this.message;
56 | }
57 |
58 | public String getCode() {
59 | return code;
60 | }
61 |
62 | public int getStatus() {
63 | return status;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/InvalidValueException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception;
2 |
3 | /**
4 | * created by jg 2021/06/03
5 | */
6 | public class InvalidValueException extends BusinessException {
7 |
8 | public InvalidValueException(ErrorCode errorCode) {
9 | super(errorCode);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/alarm/AlarmNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.alarm;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by jg 2021/06/07
8 | */
9 | public class AlarmNotFoundException extends InvalidValueException {
10 | public AlarmNotFoundException() {
11 | super(ErrorCode.ALARM_NOT_FOUND_ERROR);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/aws/S3Exception.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.aws;
2 |
3 | import com.yapp.ios1.error.exception.BusinessException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 |
6 | /**
7 | * created by jg 2021/06/04
8 | */
9 | public class S3Exception extends BusinessException {
10 | public S3Exception() {
11 | super(ErrorCode.AWS_S3_ERROR);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/bucket/BucketNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.bucket;
2 |
3 | import com.yapp.ios1.error.exception.EntityNotFoundException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 |
6 | /**
7 | * created by ayoung 2021/05/21
8 | */
9 | public class BucketNotFoundException extends EntityNotFoundException {
10 | public BucketNotFoundException() {
11 | super(ErrorCode.ENTITY_NOT_FOUND);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/bucket/bucketStateIdInvalidException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.bucket;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by jg 2021/06/07
8 | */
9 | public class bucketStateIdInvalidException extends InvalidValueException {
10 | public bucketStateIdInvalidException() {
11 | super(ErrorCode.INVALID_INPUT_VALUE);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/common/JsonWriteException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.common;
2 |
3 | import com.yapp.ios1.error.exception.BusinessException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 |
6 | /**
7 | * created by jg 2021/06/03
8 | */
9 | public class JsonWriteException extends BusinessException {
10 | public JsonWriteException() {
11 | super(ErrorCode.JSON_WRITE_ERROR);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/email/EmailCodeException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.email;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by ayoung 2021/06/15
8 | */
9 | public class EmailCodeException extends InvalidValueException {
10 | public EmailCodeException() {
11 | super(ErrorCode.INVALID_INPUT_VALUE);
12 | }
13 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/email/EmailSendException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.email;
2 |
3 | import com.yapp.ios1.error.exception.BusinessException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 |
6 | /**
7 | * created by jg 2021/06/03
8 | */
9 | public class EmailSendException extends BusinessException {
10 | public EmailSendException() {
11 | super(ErrorCode.EMAIL_SEND_ERROR);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/jwt/JwtException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.jwt;
2 |
3 | import com.yapp.ios1.error.exception.BusinessException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 |
6 | /**
7 | * created by jg 2021/06/03
8 | */
9 | public class JwtException extends BusinessException {
10 | public JwtException() {
11 | super(ErrorCode.JWT_ERROR);
12 | }
13 |
14 | public JwtException(ErrorCode errorCode) {
15 | super(errorCode);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/jwt/JwtExpiredException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.jwt;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 |
5 | /**
6 | * created by ayoung 2021/06/04
7 | */
8 | public class JwtExpiredException extends JwtException {
9 | public JwtExpiredException() {
10 | super(ErrorCode.JWT_EXPIRED_ERROR);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/jwt/JwtParseException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.jwt;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 |
5 | /**
6 | * created by jg 2021/06/03
7 | */
8 | public class JwtParseException extends JwtException {
9 | public JwtParseException() {
10 | super(ErrorCode.JWT_PARSE_ERROR);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/DeviceTokenNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by jg 2021/06/06
8 | */
9 | public class DeviceTokenNotFoundException extends InvalidValueException {
10 | public DeviceTokenNotFoundException() {
11 | super(ErrorCode.DEVICE_TOKEN_NOT_FOUND_ERROR);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/EmailDuplicatedException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 | import lombok.Getter;
6 |
7 | /**
8 | * created by ayoung 2021/04/14
9 | */
10 | @Getter
11 | public class EmailDuplicatedException extends InvalidValueException {
12 |
13 | public EmailDuplicatedException() {
14 | super(ErrorCode.EMAIL_DUPLICATION);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/EmailNotExistException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 | import lombok.Getter;
6 |
7 | /**
8 | * created by ayoung 2021/05/25
9 | */
10 | @Getter
11 | public class EmailNotExistException extends InvalidValueException {
12 |
13 | public EmailNotExistException() {
14 | super(ErrorCode.EMAIL_NOT_FOUND);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/NickNameDuplicatedException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by jg 2021/06/03
8 | */
9 | public class NickNameDuplicatedException extends InvalidValueException {
10 |
11 | public NickNameDuplicatedException() {
12 | super(ErrorCode.NICKNAME_EMAIL_DUPLICATION);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/PasswordNotMatchException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by ayoung 2021/04/15
8 | */
9 | public class PasswordNotMatchException extends InvalidValueException {
10 |
11 | public PasswordNotMatchException() {
12 | super(ErrorCode.PASSWORD_MISMATCH_ERROR);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/UserAuthenticationException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.ErrorCode;
4 | import com.yapp.ios1.error.exception.InvalidValueException;
5 |
6 | /**
7 | * created by jg 2021/06/03
8 | */
9 | public class UserAuthenticationException extends InvalidValueException {
10 |
11 | public UserAuthenticationException() {
12 | super(ErrorCode.USER_NOT_AUTHENTICATION);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/error/exception/user/UserNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.error.exception.user;
2 |
3 | import com.yapp.ios1.error.exception.EntityNotFoundException;
4 | import com.yapp.ios1.error.exception.ErrorCode;
5 |
6 | /**
7 | * created by jg 2021/04/11
8 | */
9 | public class UserNotFoundException extends EntityNotFoundException {
10 | public UserNotFoundException() {
11 | super(ErrorCode.USER_NOT_FOUND);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/AlarmMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import com.yapp.ios1.dto.notification.NotificationDto;
4 | import com.yapp.ios1.dto.notification.NotificationForOneDto;
5 | import com.yapp.ios1.model.notification.Notification;
6 | import org.apache.ibatis.annotations.Mapper;
7 | import org.apache.ibatis.annotations.Param;
8 |
9 | import java.time.LocalDateTime;
10 | import java.util.List;
11 | import java.util.Optional;
12 |
13 | /**
14 | * created by jg 2021/05/21
15 | */
16 | @Mapper
17 | public interface AlarmMapper {
18 |
19 | void insertFollowAlarmLog(@Param("notification") NotificationForOneDto notification,
20 | @Param("fromUserId") Long fromUserId,
21 | @Param("alarmStatus") int alarmStatus,
22 | @Param("time") LocalDateTime localDateTime,
23 | @Param("friendId") Long friendId);
24 |
25 | void updateFollowAlarmLog(@Param("notification") NotificationForOneDto notification,
26 | @Param("alarmId") Long alarmId);
27 |
28 | void insertWholeAlarmLog(@Param("alarm") NotificationDto notificationDto,
29 | @Param("alarmStatus") int alarmStatus);
30 |
31 | List getCommonAlarmLog(Long userId);
32 | List getFollowAlarmLog(Long userId);
33 |
34 | void deleteFollowAlarmLog(Long alarmId);
35 | void deleteWholeAlarmLog(Long alarmId, Long userId);
36 |
37 | Optional findWholeAlarmByAlarmId(Long alarmId);
38 | Optional findFollowAlarmByAlarmId(Long alarmId);
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/BucketMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import com.yapp.ios1.controller.dto.bucket.BucketRequestDto;
4 | import com.yapp.ios1.model.bookmark.Bookmark;
5 | import com.yapp.ios1.model.bucket.Bucket;
6 | import com.yapp.ios1.model.bucket.BucketTimeline;
7 | import com.yapp.ios1.model.image.Image;
8 | import com.yapp.ios1.model.tag.Tag;
9 | import org.apache.ibatis.annotations.Mapper;
10 | import org.apache.ibatis.annotations.Param;
11 |
12 | import java.util.List;
13 | import java.util.Optional;
14 |
15 | /**
16 | * created by jg 2021/05/05
17 | */
18 | @Mapper
19 | public interface BucketMapper {
20 |
21 | Optional findByBucketIdAndUserId(Long bucketId, Long userId);
22 |
23 | Optional findByBucketId(Long bucketId);
24 |
25 | void registerBucket(BucketRequestDto registerDto);
26 |
27 | void updateBucket(BucketRequestDto updateDto);
28 |
29 | void saveBucketImageUrlList(@Param("bucketId") Long bucketId, List imageUrlList);
30 |
31 | void saveBucketIdAndTagId(@Param("bucketId") Long bucketId, List tagList);
32 |
33 | void saveTagList(List tagList);
34 |
35 | List findByBucketStateAndCategory(@Param("bucketState") int bucketState,
36 | @Param("category") int category,
37 | @Param("userId") Long userId,
38 | @Param("sort") int sort);
39 |
40 | List findByUserId(Long userId);
41 |
42 | List findBookmarkListByUserId(@Param("userId") Long userId);
43 |
44 | int getBucketCountByUserId(@Param("userId") Long userId);
45 |
46 | void deleteTagListByBucketId(Long bucketId);
47 |
48 | void deleteImageListByBucketId(Long bucketId);
49 |
50 | void saveBucketLog(Long bucketId, String content, int updateType);
51 |
52 | void setBookmark(Long bucketId, boolean isBookmark);
53 |
54 | List findByBucketTagByBucketId(Long bucketId);
55 |
56 | List findByBucketImageByBucketId(Long bucketId);
57 |
58 | List findByBucketTimelineByBucketId(Long bucketId);
59 |
60 | void setBucketFin(Long bucketId, boolean isFin);
61 |
62 | void updateBucketState(Long bucketId, Long userId, int bucketStateId);
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/FriendMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import com.yapp.ios1.model.user.Friend;
4 | import org.apache.ibatis.annotations.Mapper;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * created by ayoung 2021/05/11
11 | */
12 | @Mapper
13 | public interface FriendMapper {
14 |
15 | int getFollowCountByUserId(Long userId);
16 |
17 | List getFollowListByUserId(Long userId);
18 |
19 | int checkFriendStatus(Long myUserId, Long otherUserId);
20 |
21 | void insertFollow(@Param("myUserId") Long myUserId,
22 | @Param("friendId") Long friendId,
23 | @Param("followRequest") int followRequest,
24 | @Param("alarmId") Long alarmId);
25 |
26 | void deleteFriend(Long myUserId, Long friendId);
27 |
28 | Long findByFollowAlarmId(Long myUserId, Long friendId);
29 |
30 | void updateFriendStatus(@Param("myUserId") Long myUserId,
31 | @Param("friendId") Long friendId,
32 | @Param("friendStatus") int friendStatus);
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/ProfileMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import com.yapp.ios1.controller.dto.user.ProfileUpdateDto;
4 | import com.yapp.ios1.model.user.Profile;
5 | import org.apache.ibatis.annotations.Mapper;
6 | import org.apache.ibatis.annotations.Param;
7 |
8 | import java.util.Optional;
9 |
10 | /**
11 | * created by jg 2021/06/11
12 | */
13 | @Mapper
14 | public interface ProfileMapper {
15 |
16 | Optional findProfileByUserId(@Param("userId") Long userId);
17 | int updateProfile(ProfileUpdateDto profile, Long userId);
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/SearchMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import com.yapp.ios1.model.bucket.Bucket;
4 | import com.yapp.ios1.model.user.Friend;
5 | import org.apache.ibatis.annotations.Mapper;
6 | import org.apache.ibatis.annotations.Param;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * created by jg 2021/05/17
12 | */
13 | @Mapper
14 | public interface SearchMapper {
15 |
16 | List searchUser(@Param("keyword") String keyword, @Param("userId") Long userId);
17 | List searchMyBook(@Param("keyword") String keyword, @Param("userId") Long userId);
18 | List searchBookMark(@Param("keyword") String keyword, @Param("userId") Long userId);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/TokenMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import org.apache.ibatis.annotations.Mapper;
4 |
5 | /**
6 | * created by ayoung 2021/06/03
7 | */
8 | @Mapper
9 | public interface TokenMapper {
10 | void updateToken(String refreshToken, Long userId);
11 |
12 | String getTokenByUserId(Long userId);
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.mapper;
2 |
3 | import com.yapp.ios1.model.user.User;
4 | import org.apache.ibatis.annotations.Mapper;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 | import java.util.Optional;
9 |
10 | /**
11 | * created by jg 2021/03/28
12 | */
13 | @Mapper
14 | public interface UserMapper {
15 |
16 | Optional findByUserId(@Param("userId") Long userId);
17 |
18 | // TODO id 없으면 왜 에러인지 알아보기
19 | Optional findByEmail(@Param("email") String email);
20 |
21 | Optional findByNickname(@Param("nickname") String nickname);
22 |
23 | Optional findBySocialIdAndSocialType(String socialId, String socialType);
24 |
25 | void changePassword(Long userId, String password);
26 |
27 | void signUp(User user);
28 |
29 | Optional findDeviceTokenByUserId(Long userId);
30 |
31 | List findAllUserDeviceToken();
32 |
33 | void deleteUser(Long userId);
34 |
35 | void updateAlarmStatus(Long userId, boolean alarmReadStatus);
36 |
37 | boolean alarmCheckStatus(Long userId);
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/message/AlarmMessage.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.message;
2 |
3 | /**
4 | * created by jg 2021/06/06
5 | */
6 | public class AlarmMessage {
7 | private AlarmMessage() {}
8 |
9 | public static final String FOLLOW_REQUEST_TITLE = "친구 요청이 왔어요";
10 | public static final String FOLLOW_REQUEST_MESSAGE = "님이 회원님과 친구가 되고 싶어 합니다.";
11 | public static final String FOLLOW_ACCEPT_TITLE = "친구 요청을 수락했습니다.";
12 | public static final String FOLLOW_ACCEPT_MESSAGE = "님이 회원님과 친구가 되었습니다";
13 |
14 | public static final String WHOLE_ALARM_TITLE = "전체 알람 메시지 제목";
15 | public static final String WHOLE_ALARM_MESSAGE = "전체 알람 메세지 내용";
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/message/ResponseMessage.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.message;
2 |
3 | /**
4 | * created by jg 2021/05/05
5 | */
6 | public class ResponseMessage {
7 | private ResponseMessage() {}
8 |
9 | // Bucket
10 | public static final String GET_BUCKET_LIST = "버킷 리스트 조회 성공입니다.";
11 | public static final String UPLOAD_IMAGE_SUCCESS = "이미지 업로드 성공입니다.";
12 | public static final String NOT_EXIST_IMAGE = "업로드할 이미지 존재하지 않습니다.";
13 | public static final String REGISTER_BUCKET_SUCCESS = "버킷 등록 성공입니다.";
14 | public static final String UPDATE_BUCKET_SUCCESS = "버킷 수정 성공입니다.";
15 | public static final String GET_BUCKET_DETAIL = "버킷 상세 조회 성공입니다";
16 | public static final String REGISTER_BUCKET_FIN_SUCCESS = "버킷 핀 등록 성공입니다";
17 | public static final String UPDATE_BUCKET_STATE = "버킷 상태 변경 성공입니다";
18 |
19 | // Login
20 | public static final String LOGIN_SUCCESS = "로그인 성공입니다.";
21 | public static final String SIGN_UP_SUCCESS = "회원가입 성공입니다.";
22 | public static final String CHANGE_PASSWORD_SUCCESS = "비밀번호 재설정 성공입니다.";
23 | public static final String POSSIBLE_NICKNAME = "사용가능한 닉네임입니다.";
24 | public static final String POSSIBLE_EMAIL = "사용가능한 이메일입니다.";
25 | public static final String REISSUE_TOKEN_SUCCESS = "토큰 재발급 성공입니다.";
26 |
27 | // User
28 | public static final String GET_PROFILE_SUCCESS = "프로필 가져오기 성공입니다.";
29 | public static final String UPDATE_PROFILE_SUCCESS = "프로필 수정 성공입니다.";
30 | public static final String GET_MY_INFO = "마이페이지 정보입니다.";
31 | public static final String GET_USER_INFO = "사용자페이지 정보입니다.";
32 | public static final String GET_FRIEND_LIST = "친구 목록입니다.";
33 | public static final String DELETE_USER_SUCCESS = "탈퇴 성공입니다.";
34 |
35 | // Notification
36 | public static final String GET_ALARM_LOG = "알람 로그 조회 성공입니다";
37 | public static final String DELETE_ALARM_LOG = "알람 로그 삭제되었습니다";
38 |
39 | // Search
40 | public static final String NOT_FOUND_SEARCH_TYPE = "존재하지 않는 검색 조건입니다.";
41 | public static final String SUCCESS_SEARCH = "검색 성공입니다.";
42 |
43 | // Follow
44 | public static final String FRIEND_REQUEST = "팔로우 요청 성공입니다.";
45 | public static final String FRIEND_MESSAGE = "팔로우 응답 성공입니다.";
46 | public static final String FRIEND_DELETE = "친구 끊기 성공입니다";
47 |
48 | // Email
49 | public static final String EMAIL_SEND_SUCCESS = "이메일 전송 성공입니다.";
50 | public static final String EMAIL_AUTH_SUCCESS = "이메일 인증 성공입니다.";
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/message/ValidMessage.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.message;
2 |
3 | /**
4 | * created by jg 2021/06/07
5 | */
6 | public class ValidMessage {
7 | private ValidMessage() {}
8 |
9 | // Valid
10 | public static final String NOT_VALID_BUCKET_NAME = "버킷 제목 작성 필수입니다.";
11 | public static final String NOT_VALID_CATEGORY_ID = "유효한 카테고리 ID가 아닙니다.";
12 | public static final String NOT_VALID_STATE = "유효한 버킷 state가 아닙니다.";
13 | public static final String NOT_VALID_EMAIL = "이메일 형식 제대로 입력해주세요.";
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/bookmark/Bookmark.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.bookmark;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by ayoung 2021/05/11
7 | */
8 | @Getter
9 | public class Bookmark {
10 | private Long id;
11 | private String bucketName;
12 | private String endDate;
13 | private int categoryId;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/bucket/Bucket.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.bucket;
2 |
3 | import lombok.Getter;
4 |
5 | import java.time.LocalDate;
6 | import java.time.LocalDateTime;
7 |
8 | /**
9 | * created by jg 2021/05/05
10 | * 버킷 홈, 나의버킷-북마크 검색 모델
11 | */
12 | @Getter
13 | public class Bucket {
14 | private Long id;
15 | private Long userId;
16 | private String bucketName;
17 | private String content;
18 | private String createdDate;
19 | private String endDate;
20 | private int bucketState;
21 | private Integer categoryId;
22 | private boolean isBookmark;
23 | private boolean isFin;
24 | private String userProfileUrl;
25 | private boolean isAlarmCheck;
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/bucket/BucketTimeline.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.bucket;
2 |
3 | import lombok.Getter;
4 |
5 | import java.time.LocalDate;
6 |
7 | /**
8 | * created by jg 2021/06/07
9 | */
10 | @Getter
11 | public class BucketTimeline {
12 | private String content;
13 | private LocalDate modifiedDate;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/image/Image.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.image;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by jg 2021/06/06
7 | */
8 | @Getter
9 | public class Image {
10 | private String imageUrl;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/notification/Notification.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.notification;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by jg 2021/05/26
7 | * 알림 로그 모델
8 | */
9 | @Getter
10 | public class Notification {
11 | private Long alarmId;
12 | private Long friendId;
13 | private String title;
14 | private String message;
15 | private String nickName;
16 | private String profileUrl;
17 | private int friendStatus;
18 | private int alarmStatus;
19 | private String createdAt;
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/tag/Tag.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.tag;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import lombok.Getter;
5 | import lombok.NoArgsConstructor;
6 |
7 | /**
8 | * created by ayoung 2021/05/08
9 | */
10 | @JsonInclude(JsonInclude.Include.NON_NULL)
11 | @NoArgsConstructor
12 | @Getter
13 | public class Tag {
14 | private Long id;
15 | private String tagName;
16 |
17 | public void setId(Long id) {
18 | this.id = id;
19 | }
20 |
21 | public Tag(String tagName) {
22 | this.tagName = tagName;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/user/Friend.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.user;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by ayoung 2021/05/12
7 | * 친구 목록 조회, 유저 검색 모델
8 | */
9 | @Getter
10 | public class Friend {
11 | private Long userId;
12 | private String email;
13 | private String nickname;
14 | private String intro;
15 | private String profileUrl;
16 | private int friendStatus;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/user/Profile.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.user;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * created by ayoung 2021/05/18
7 | * 디바이스 토큰, 패스워드 제외한 프로필 모델
8 | */
9 | @Getter
10 | public class Profile {
11 | private Long id;
12 | private String email;
13 | private String nickname;
14 | private String createdDate;
15 | private String intro;
16 | private String profileUrl;
17 | private String socialType;
18 | private String socialId;
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/model/user/User.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.model.user;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import com.yapp.ios1.controller.dto.user.login.SignUpDto;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Getter;
8 | import lombok.NoArgsConstructor;
9 |
10 | /**
11 | * created by jg 2021/03/28
12 | */
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Getter
16 | @Builder
17 | public class User {
18 | private Long id;
19 | private String email;
20 | @JsonIgnore
21 | private String socialType;
22 | private String nickname;
23 | @JsonIgnore
24 | private String password;
25 | private String intro;
26 | private String createdDate;
27 | @JsonIgnore
28 | private String socialId;
29 | @JsonIgnore
30 | private String deviceToken;
31 | private String profileUrl;
32 | private boolean isAlarmCheck;
33 |
34 | public static User of(SignUpDto signUpDto) {
35 | return User.builder()
36 | .email(signUpDto.getEmail())
37 | .nickname(signUpDto.getNickname())
38 | .password(signUpDto.getPassword())
39 | .intro(signUpDto.getIntro())
40 | .socialType(signUpDto.getSocialType())
41 | .socialId(signUpDto.getSocialId())
42 | .deviceToken(signUpDto.getDeviceToken())
43 | .build();
44 | }
45 |
46 | public void encodePassword(String password) {
47 | this.password = password;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/properties/EmailProperties.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | /**
9 | * created by ayoung 2021/05/30
10 | */
11 | @Getter
12 | @Setter
13 | @ConfigurationProperties(prefix = "buok.email")
14 | @Configuration
15 | public class EmailProperties {
16 | private String name;
17 | private String link;
18 | private Long validTime;
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/properties/FirebaseProperties.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | /**
9 | * created by jg 2021/06/07
10 | */
11 | @Getter
12 | @Setter
13 | @ConfigurationProperties(prefix = "fcm.account")
14 | @Configuration
15 | public class FirebaseProperties {
16 | private String path;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/properties/JwtProperties.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | /**
9 | * created by jg 2021/06/04
10 | */
11 | @Getter
12 | @Setter
13 | @ConfigurationProperties(prefix = "jwt")
14 | @Configuration
15 | public class JwtProperties {
16 | // TODO AccessToken, RefreshToken SecretKey 분리하기
17 | private String secretKey;
18 | private AccessToken accessToken;
19 | private RefreshToken refreshToken;
20 |
21 | @Getter @Setter
22 | public static class AccessToken {
23 | private Long validTime;
24 | }
25 |
26 | @Getter @Setter
27 | public static class RefreshToken {
28 | private Long validTime;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/properties/S3Properties.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | /**
9 | * created by jg 2021/06/04
10 | */
11 | @Getter
12 | @Setter
13 | @ConfigurationProperties(prefix = "cloud.aws.s3")
14 | @Configuration
15 | public class S3Properties {
16 | private String bucket;
17 | private String dir;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/properties/SocialLoginProperties.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.properties;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | /**
9 | * created by jg 2021/06/04
10 | */
11 | @Getter
12 | @Setter
13 | @ConfigurationProperties(prefix = "social")
14 | @Configuration
15 | public class SocialLoginProperties {
16 | private String key;
17 | private Host host;
18 |
19 | @Getter @Setter
20 | public static class Host {
21 | private String google;
22 | private String kakao;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/EmailService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.yapp.ios1.error.exception.email.EmailCodeException;
4 | import com.yapp.ios1.model.user.User;
5 | import com.yapp.ios1.error.exception.email.EmailSendException;
6 | import com.yapp.ios1.properties.EmailProperties;
7 | import com.yapp.ios1.utils.RedisUtil;
8 | import com.yapp.ios1.validator.UserValidator;
9 | import lombok.RequiredArgsConstructor;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.mail.javamail.JavaMailSender;
12 | import org.springframework.stereotype.Service;
13 | import org.thymeleaf.context.Context;
14 | import org.thymeleaf.spring5.SpringTemplateEngine;
15 |
16 | import javax.mail.internet.InternetAddress;
17 | import javax.mail.internet.MimeMessage;
18 | import java.util.Random;
19 |
20 | /**
21 | * created by ayoung 2021/05/30
22 | */
23 | @Slf4j
24 | @RequiredArgsConstructor
25 | @Service
26 | public class EmailService {
27 |
28 | private final JavaMailSender emailSender;
29 | private final RedisUtil redisUtil;
30 | private final EmailProperties emailProperties;
31 | private final UserValidator userValidator;
32 | private final SpringTemplateEngine templateEngine;
33 |
34 | public void sendEmailMessage(String email) {
35 | userValidator.checkEmailPresent(email);
36 | try {
37 | String code = createCode();
38 | redisUtil.setDataExpire(code, email, emailProperties.getValidTime());
39 | MimeMessage message = createMessage(email, code);
40 | emailSender.send(message);
41 | } catch (Exception e) {
42 | throw new EmailSendException();
43 | }
44 | }
45 |
46 | private MimeMessage createMessage(String email, String code) throws Exception {
47 | MimeMessage message = emailSender.createMimeMessage();
48 | message.addRecipients(MimeMessage.RecipientType.TO, email);
49 | message.setSubject("[buok] 비밀번호를 잊으셨나요? " + code);
50 | message.setText(setContext(code), "utf-8", "html");
51 | message.setFrom(new InternetAddress(emailProperties.getLink(), emailProperties.getName()));
52 | return message;
53 | }
54 |
55 | private String setContext(String code) {
56 | Context context = new Context();
57 | context.setVariable("code", code);
58 | return templateEngine.process("email", context);
59 | }
60 |
61 | private String createCode() {
62 | StringBuilder code = new StringBuilder();
63 | Random rnd = new Random();
64 | for (int i = 0; i < 7; i++) {
65 | int rIndex = rnd.nextInt(3);
66 | switch (rIndex) {
67 | case 0:
68 | code.append((char) (rnd.nextInt(26) + 97));
69 | break;
70 | case 1:
71 | code.append((char) (rnd.nextInt(26) + 65));
72 | break;
73 | case 2:
74 | code.append((rnd.nextInt(10)));
75 | break;
76 | }
77 | }
78 | return code.toString();
79 | }
80 |
81 | public Long getUserIdByCode(String code) {
82 | String email = redisUtil.getData(code);
83 | if (email == null) {
84 | throw new EmailCodeException();
85 | }
86 |
87 | User user = userValidator.checkEmailPresent(email);
88 | return user.getId();
89 | }
90 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/FriendService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.yapp.ios1.dto.notification.NotificationForOneDto;
4 | import com.yapp.ios1.mapper.AlarmMapper;
5 | import com.yapp.ios1.mapper.FriendMapper;
6 | import com.yapp.ios1.model.user.Friend;
7 | import com.yapp.ios1.service.alarm.FirebaseService;
8 | import com.yapp.ios1.service.user.UserService;
9 | import com.yapp.ios1.utils.AlarmMessageUtil;
10 | import lombok.RequiredArgsConstructor;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.springframework.stereotype.Service;
13 | import org.springframework.transaction.annotation.Transactional;
14 |
15 | import java.time.LocalDateTime;
16 | import java.util.List;
17 |
18 | import static com.yapp.ios1.enums.AlarmStatus.FOLLOW_ALARM;
19 | import static com.yapp.ios1.enums.FriendStatus.FRIEND;
20 | import static com.yapp.ios1.enums.FriendStatus.REQUEST;
21 | import static com.yapp.ios1.message.AlarmMessage.*;
22 |
23 | /**
24 | * created by jg 2021/05/21
25 | */
26 | @Slf4j
27 | @RequiredArgsConstructor
28 | @Service
29 | public class FriendService { // TODO 친구 관련 API 들이 N+1 쿼리가 너무 많음 => 리팩터링 필수
30 |
31 | private final FirebaseService firebaseService;
32 | private final FriendMapper followMapper;
33 | private final AlarmMapper alarmMapper;
34 | private final UserService userService;
35 | private final AlarmMessageUtil alarmMessage;
36 |
37 | // TODO 어떻게 리팩터링 할까
38 | @Transactional
39 | public void requestFollow(Long myUserId, Long friendId) {
40 | NotificationForOneDto notificationForOne = alarmMessage.createFollowAlarmMessage(FOLLOW_REQUEST_TITLE, FOLLOW_REQUEST_MESSAGE, friendId);
41 | // alarm_status = 1(전체알람), 2 (친구 알람)
42 | alarmMapper.insertFollowAlarmLog(notificationForOne, myUserId, FOLLOW_ALARM.get(), LocalDateTime.now(), friendId);
43 | followMapper.insertFollow(myUserId, friendId, REQUEST.get(), notificationForOne.getAlarmId());
44 | userService.updateUserAlarmReadStatus(friendId, false);
45 | firebaseService.sendByTokenForOne(notificationForOne, myUserId);
46 | }
47 |
48 | public List getFriendList(Long userId) {
49 | return followMapper.getFollowListByUserId(userId);
50 | }
51 |
52 | // friendStatus = 1(친구), 2(요청 중)
53 | @Transactional
54 | public void checkFollowAccept(boolean isAccept, Long myUserId, Long friendId, Long alarmId) {
55 | if (isAccept) {
56 | acceptFollow(myUserId, friendId, alarmId);
57 | return;
58 | }
59 | noAcceptFollow(alarmId, myUserId, friendId);
60 | }
61 |
62 | // TODO 어떻게 리팩터링 할까
63 | private void acceptFollow(Long myUserId, Long friendId, Long alarmId) {
64 | NotificationForOneDto notificationForOne = alarmMessage.createFollowAlarmMessage(FOLLOW_ACCEPT_TITLE, FOLLOW_ACCEPT_MESSAGE, friendId);
65 | alarmMapper.updateFollowAlarmLog(notificationForOne, alarmId);
66 | alarmMapper.insertFollowAlarmLog(notificationForOne, myUserId, FOLLOW_ALARM.get(), LocalDateTime.now(), friendId);
67 | followMapper.insertFollow(myUserId, friendId, FRIEND.get(), notificationForOne.getAlarmId());
68 | followMapper.updateFriendStatus(myUserId, friendId, FRIEND.get());
69 | userService.updateUserAlarmReadStatus(friendId, false);
70 | firebaseService.sendByTokenForOne(notificationForOne, myUserId);
71 | }
72 |
73 | // TODO 리팩터링
74 | private void noAcceptFollow(Long alarmId, Long myUserId, Long friendId) {
75 | followMapper.deleteFriend(myUserId, friendId);
76 | followMapper.deleteFriend(friendId, myUserId);
77 | alarmMapper.deleteFollowAlarmLog(alarmId);
78 | }
79 |
80 | // TODO: 망가진 API (어떻게 리팩터링 할까) => Mybatis에서 Multi Query 지원 하는 듯
81 | @Transactional
82 | public void deleteFriend(Long myUserId, Long friendId) {
83 | Long followRequestAlarmId = getFollowAlarmId(myUserId, friendId);
84 | Long followAcceptAlarmId = getFollowAlarmId(friendId, myUserId);
85 | alarmMapper.deleteFollowAlarmLog(followRequestAlarmId);
86 | alarmMapper.deleteFollowAlarmLog(followAcceptAlarmId);
87 | followMapper.deleteFriend(myUserId, friendId);
88 | followMapper.deleteFriend(friendId, myUserId);
89 | }
90 |
91 | private Long getFollowAlarmId(Long myUserId, Long friendId) {
92 | return followMapper.findByFollowAlarmId(myUserId, friendId);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/OauthService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.yapp.ios1.model.user.User;
4 | import com.yapp.ios1.dto.user.UserStatusDto;
5 | import com.yapp.ios1.controller.dto.user.login.SignUpDto;
6 | import com.yapp.ios1.controller.dto.user.social.SocialLoginDto;
7 | import com.yapp.ios1.properties.SocialLoginProperties;
8 | import com.yapp.ios1.service.jwt.JwtService;
9 | import com.yapp.ios1.service.user.UserFindService;
10 | import com.yapp.ios1.service.user.UserService;
11 | import com.yapp.ios1.validator.UserValidator;
12 | import lombok.RequiredArgsConstructor;
13 | import org.springframework.http.*;
14 | import org.springframework.stereotype.Service;
15 | import org.springframework.transaction.annotation.Transactional;
16 |
17 | import java.util.Optional;
18 |
19 | /**
20 | * created by ayoung 2021/05/04
21 | */
22 | @RequiredArgsConstructor
23 | @Service
24 | public class OauthService {
25 |
26 | private final UserService userService;
27 | private final UserFindService userFindService;
28 | private final UserValidator userValidator;
29 | private final JwtService jwtService;
30 | private final SocialLoginProperties socialLoginProperties;
31 |
32 | @Transactional
33 | public UserStatusDto getSocialUser(String socialType, SocialLoginDto socialDto) {
34 | String socialId = socialDto.getSocialId();
35 | String email = socialDto.getEmail();
36 |
37 | Optional optionalUser = userFindService.findBySocialIdAndSocialType(socialId, socialType);
38 |
39 | if (optionalUser.isEmpty()) {
40 | if (!email.equals("")) {
41 | userValidator.checkEmailDuplicate(email);
42 | }
43 | return socialSignUp(socialType, socialDto);
44 | }
45 | return new UserStatusDto(HttpStatus.OK, jwtService.createTokenResponse(optionalUser.get().getId()));
46 | }
47 |
48 | private UserStatusDto socialSignUp(String socialType, SocialLoginDto socialDto) {
49 | SignUpDto signUpDto = SignUpDto.builder()
50 | .socialType(socialType)
51 | .email(socialDto.getEmail())
52 | .password(socialLoginProperties.getKey())
53 | .socialId(socialDto.getSocialId())
54 | .deviceToken(socialDto.getDeviceToken())
55 | .build();
56 | return new UserStatusDto(HttpStatus.CREATED, userService.signUp(User.of(signUpDto)));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/S3Service.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.amazonaws.services.s3.AmazonS3Client;
4 | import com.amazonaws.services.s3.model.CannedAccessControlList;
5 | import com.amazonaws.services.s3.model.ObjectMetadata;
6 | import com.amazonaws.services.s3.model.PutObjectRequest;
7 | import com.amazonaws.util.IOUtils;
8 | import com.yapp.ios1.error.exception.aws.S3Exception;
9 | import com.yapp.ios1.properties.S3Properties;
10 | import lombok.RequiredArgsConstructor;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.springframework.stereotype.Service;
13 | import org.springframework.web.multipart.MultipartFile;
14 |
15 | import java.io.ByteArrayInputStream;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import java.util.UUID;
19 |
20 | /**
21 | * created by ayoung 2021/03/29
22 | */
23 | @Slf4j
24 | @RequiredArgsConstructor
25 | @Service
26 | public class S3Service {
27 |
28 | private final AmazonS3Client s3Client;
29 | private final S3Properties s3Properties;
30 |
31 | public List upload(MultipartFile[] multipartFileList, Long userId) {
32 | List imageUrlList = new ArrayList<>();
33 | for (MultipartFile multipartFile : multipartFileList) {
34 | imageUrlList.add(upload(multipartFile, userId));
35 | }
36 | return imageUrlList;
37 | }
38 |
39 | public String upload(MultipartFile file, Long userId) {
40 | try {
41 | String fileName = userId + "-" + UUID.randomUUID() + "-" + file.getOriginalFilename();
42 | ObjectMetadata objMeta = new ObjectMetadata();
43 |
44 | byte[] bytes = IOUtils.toByteArray(file.getInputStream());
45 | objMeta.setContentLength(bytes.length);
46 |
47 | ByteArrayInputStream byteArrayIs = new ByteArrayInputStream(bytes);
48 |
49 | s3Client.putObject(new PutObjectRequest(s3Properties.getBucket(), s3Properties.getDir() + fileName, byteArrayIs, objMeta)
50 | .withCannedAcl(CannedAccessControlList.PublicRead));
51 |
52 | return s3Client.getUrl(s3Properties.getBucket(), s3Properties.getDir() + fileName).toString();
53 | } catch (Exception e) {
54 | throw new S3Exception();
55 | }
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/SearchService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.yapp.ios1.mapper.SearchMapper;
4 | import com.yapp.ios1.model.bucket.Bucket;
5 | import com.yapp.ios1.model.user.Friend;
6 | import lombok.RequiredArgsConstructor;
7 | import org.springframework.stereotype.Service;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * created by jg 2021/05/17
13 | */
14 | @RequiredArgsConstructor
15 | @Service
16 | public class SearchService {
17 |
18 | private final SearchMapper searchMapper;
19 |
20 | public List searchMyBook(String keyword, Long userId) {
21 | return searchMapper.searchMyBook(keyword, userId);
22 | }
23 |
24 | public List searchUser(String keyword, Long userId) {
25 | return searchMapper.searchUser(keyword, userId);
26 | }
27 |
28 | public List searchBookMark(String keyword, Long userId) {
29 | return searchMapper.searchBookMark(keyword, userId);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/alarm/AlarmService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.alarm;
2 |
3 | import com.yapp.ios1.mapper.AlarmMapper;
4 | import com.yapp.ios1.mapper.UserMapper;
5 | import com.yapp.ios1.model.notification.Notification;
6 | import com.yapp.ios1.validator.AlarmValidator;
7 | import lombok.RequiredArgsConstructor;
8 | import org.springframework.scheduling.annotation.Scheduled;
9 | import org.springframework.stereotype.Service;
10 |
11 | import java.util.Comparator;
12 | import java.util.List;
13 | import java.util.stream.Collectors;
14 | import java.util.stream.Stream;
15 |
16 | import static com.yapp.ios1.enums.AlarmStatus.WHOLE_ALARM;
17 |
18 | /**
19 | * created by jg 2021/06/10
20 | */
21 | @RequiredArgsConstructor
22 | @Service
23 | public class AlarmService {
24 |
25 | private final FirebaseService firebaseService;
26 | private final AlarmValidator alarmValidator;
27 | private final AlarmMapper alarmMapper;
28 | private final UserMapper userMapper;
29 |
30 | public List getAlarmLog(Long userId) {
31 | List followAlarmLog = alarmMapper.getFollowAlarmLog(userId);
32 | List commonAlarmLog = alarmMapper.getCommonAlarmLog(userId);
33 | // 알림 로그 읽었다는 뜻
34 | userMapper.updateAlarmStatus(userId, true);
35 |
36 | return Stream.concat(followAlarmLog.stream(), commonAlarmLog.stream())
37 | .sorted(Comparator.comparing(Notification::getCreatedAt))
38 | .collect(Collectors.toList());
39 | }
40 |
41 | public void deleteAlarm(Long alarmId, Long userId, int alarmStatus) {
42 | if (alarmStatus == WHOLE_ALARM.get()) {
43 | alarmValidator.checkValidWholeAlarm(alarmId);
44 | alarmMapper.deleteWholeAlarmLog(alarmId, userId);
45 | return;
46 | }
47 |
48 | alarmValidator.checkValidFollowAlarm(alarmId);
49 | alarmMapper.deleteFollowAlarmLog(alarmId);
50 | }
51 |
52 | // // 초, 분, 시간, 일, 월, 요일 (매월, 1일, 20시 53분 30초에 알림을 보내도록 임시로 설정)
53 | // @Scheduled(cron = "10 12 14 * * ?", zone = "Asia/Seoul")
54 | // public void notificationSchedule() {
55 | // alarmMapper.insertWholeAlarmLog(firebaseService.getWholeAlarmMessage(), WHOLE_ALARM.get()); // alarm_status = 1 (전체 알람)
56 | // firebaseService.sendByTokenForMulti();
57 | // }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/alarm/FirebaseService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.alarm;
2 |
3 | import com.google.auth.oauth2.GoogleCredentials;
4 | import com.google.firebase.messaging.*;
5 | import com.yapp.ios1.dto.notification.FcmMessage;
6 | import com.yapp.ios1.dto.notification.NotificationDto;
7 | import com.yapp.ios1.dto.notification.NotificationForOneDto;
8 | import com.yapp.ios1.model.user.User;
9 | import com.yapp.ios1.properties.FirebaseProperties;
10 | import com.yapp.ios1.service.user.UserFindService;
11 | import lombok.RequiredArgsConstructor;
12 | import lombok.extern.slf4j.Slf4j;
13 | import org.springframework.core.io.ClassPathResource;
14 | import org.springframework.http.*;
15 | import org.springframework.stereotype.Service;
16 | import org.springframework.web.client.RestTemplate;
17 |
18 | import javax.annotation.PostConstruct;
19 | import java.io.IOException;
20 | import java.time.LocalDateTime;
21 | import java.util.List;
22 | import java.util.stream.Collectors;
23 |
24 | import static com.yapp.ios1.message.AlarmMessage.WHOLE_ALARM_MESSAGE;
25 | import static com.yapp.ios1.message.AlarmMessage.WHOLE_ALARM_TITLE;
26 |
27 | /**
28 | * created by jg 2021/05/02
29 | */
30 | @RequiredArgsConstructor
31 | @Slf4j
32 | @Service
33 | public class FirebaseService {
34 |
35 | private final UserFindService userFindService;
36 | private final FirebaseProperties firebaseProperties;
37 | private final RestTemplate restTemplate;
38 | private String fcmAccessToken;
39 |
40 | @PostConstruct
41 | public void init() {
42 | try {
43 | GoogleCredentials googleCredentials =
44 | GoogleCredentials.fromStream(new ClassPathResource(firebaseProperties.getPath()).getInputStream())
45 | .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform"));
46 | googleCredentials.refreshIfExpired();
47 | fcmAccessToken = googleCredentials.getAccessToken().getTokenValue();
48 | } catch (IOException e) {
49 | log.error("cannot initial firebase " + e.getMessage());
50 | }
51 | }
52 |
53 | public void sendByTokenForMulti() {
54 | List deviceTokens = userFindService.getAllDeviceToken();
55 | NotificationDto pushNotificationRequest = getWholeAlarmMessage();
56 |
57 | List messages = deviceTokens.stream().map(token -> Message.builder()
58 | .putData("title", pushNotificationRequest.getTitle())
59 | .putData("message", pushNotificationRequest.getMessage())
60 | .setToken(token)
61 | .build()).collect(Collectors.toList());
62 |
63 | BatchResponse response;
64 | try {
65 | response = FirebaseMessaging.getInstance().sendAll(messages);
66 | log.info("send message: " + response);
67 | } catch (FirebaseMessagingException e) {
68 | log.error("cannot send to member push message. error info : {}", e.getMessage());
69 | }
70 | }
71 |
72 | public void sendByTokenForOne(NotificationForOneDto messageInfo, Long userId) {
73 | HttpHeaders headers = new HttpHeaders();
74 | headers.setBearerAuth(fcmAccessToken);
75 | headers.setContentType(MediaType.APPLICATION_JSON);
76 |
77 | FcmMessage message = makeMessage(messageInfo, userId);
78 |
79 | HttpEntity request = new HttpEntity<>(message, headers);
80 | try {
81 | ResponseEntity response = restTemplate.exchange(
82 | "https://fcm.googleapis.com/v1/projects/buok-ios/messages:send",
83 | HttpMethod.POST,
84 | request,
85 | String.class
86 | );
87 | log.info("send message: " + response);
88 | } catch (Exception e) {
89 | log.error("cannot send message by token. error info : {}", e.getMessage());
90 | }
91 | }
92 |
93 | private FcmMessage makeMessage(NotificationForOneDto messageInfo, Long userId) {
94 | User user = userFindService.getUser(userId);
95 | return FcmMessage.builder()
96 | .message(FcmMessage.Message.builder()
97 | .token(messageInfo.getDeviceToken())
98 | .notification(FcmMessage.Notification.builder()
99 | .title(messageInfo.getTitle())
100 | .body(user.getNickname() + messageInfo.getMessage())
101 | .build())
102 | .build()
103 | )
104 | .build();
105 | }
106 |
107 | public NotificationDto getWholeAlarmMessage() {
108 | return new NotificationDto(WHOLE_ALARM_TITLE, WHOLE_ALARM_MESSAGE, LocalDateTime.now());
109 | }
110 | }
111 |
112 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/bucket/BucketFindService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.bucket;
2 |
3 | import com.yapp.ios1.dto.bucket.BucketDetailDto;
4 | import com.yapp.ios1.dto.bucket.BucketHomeDto;
5 | import com.yapp.ios1.error.exception.bucket.BucketNotFoundException;
6 | import com.yapp.ios1.mapper.BucketMapper;
7 | import com.yapp.ios1.mapper.UserMapper;
8 | import com.yapp.ios1.model.bookmark.Bookmark;
9 | import com.yapp.ios1.model.bucket.Bucket;
10 | import com.yapp.ios1.model.bucket.BucketTimeline;
11 | import com.yapp.ios1.model.image.Image;
12 | import com.yapp.ios1.model.tag.Tag;
13 | import lombok.RequiredArgsConstructor;
14 | import org.springframework.stereotype.Service;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * created by jg 2021/06/15
20 | */
21 | @RequiredArgsConstructor
22 | @Service
23 | public class BucketFindService {
24 |
25 | private final BucketMapper bucketMapper;
26 | private final UserMapper userMapper;
27 |
28 | public BucketHomeDto getHomeBucketList(int bucketState, int category, Long userId, int sort) {
29 | List buckets = bucketMapper.findByBucketStateAndCategory(bucketState, category, userId, sort);
30 | return BucketHomeDto.builder()
31 | .buckets(buckets)
32 | .bucketCount(buckets.size())
33 | .isAlarmCheck(userMapper.alarmCheckStatus(userId))
34 | .build();
35 | }
36 |
37 | public BucketDetailDto getBucketDetail(Long bucketId) {
38 | return new BucketDetailDto(
39 | getBucket(bucketId),
40 | getBucketImage(bucketId),
41 | getBucketTag(bucketId),
42 | getBucketTimeline(bucketId)
43 | );
44 | }
45 |
46 | public Bucket getBucket(Long bucketId) {
47 | return bucketMapper.findByBucketId(bucketId)
48 | .orElseThrow(BucketNotFoundException::new);
49 | }
50 |
51 | public Bucket getBucket(Long bucketId, Long userId) {
52 | return bucketMapper.findByBucketIdAndUserId(bucketId, userId)
53 | .orElseThrow(BucketNotFoundException::new);
54 | }
55 |
56 | private List getBucketTag(Long bucketId) {
57 | return bucketMapper.findByBucketTagByBucketId(bucketId);
58 | }
59 |
60 | private List getBucketImage(Long bucketId) {
61 | return bucketMapper.findByBucketImageByBucketId(bucketId);
62 | }
63 |
64 | private List getBucketTimeline(Long bucketId) {
65 | return bucketMapper.findByBucketTimelineByBucketId(bucketId);
66 | }
67 |
68 | public List getUserBucketList(Long userId) {
69 | return bucketMapper.findByUserId(userId);
70 | }
71 |
72 | public List getBookmarkList(Long userId) {
73 | return bucketMapper.findBookmarkListByUserId(userId);
74 | }
75 |
76 | public int getBucketCountByUserId(Long userId) {
77 | return bucketMapper.getBucketCountByUserId(userId);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/bucket/BucketService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.bucket;
2 |
3 | import com.yapp.ios1.controller.dto.bucket.BucketRequestDto;
4 | import com.yapp.ios1.mapper.BucketMapper;
5 | import com.yapp.ios1.model.bucket.Bucket;
6 | import com.yapp.ios1.validator.BucketValidator;
7 | import lombok.RequiredArgsConstructor;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.stereotype.Service;
10 | import org.springframework.transaction.annotation.Transactional;
11 |
12 | import java.util.List;
13 |
14 | import static com.yapp.ios1.enums.BucketLogStatus.*;
15 |
16 | /**
17 | * created by jg 2021/05/05
18 | */
19 | @Slf4j
20 | @RequiredArgsConstructor
21 | @Service
22 | public class BucketService {
23 |
24 | private final BucketFindService bucketFindService;
25 | private final BucketValidator bucketValidator;
26 | private final BucketMapper bucketMapper;
27 |
28 | @Transactional
29 | public void saveBucket(BucketRequestDto registerDto) {
30 | bucketMapper.registerBucket(registerDto);
31 |
32 | Long bucketId = registerDto.getId();
33 | saveTagList(bucketId, registerDto.getTagList());
34 | saveImageUrlList(bucketId, registerDto.getImageList());
35 | }
36 |
37 | @Transactional
38 | public void updateBucket(Long bucketId, BucketRequestDto updateDto, Long userId) {
39 | Bucket bucketDto = bucketFindService.getBucket(bucketId, userId);
40 |
41 | String updateBucketName = updateDto.getBucketName();
42 | String updateEndDate = updateDto.getEndDate().toString();
43 |
44 | updateDto.setId(bucketId);
45 | bucketMapper.updateBucket(updateDto);
46 |
47 | updateTag(bucketId, updateDto.getTagList());
48 | updateImageUrlList(bucketId, updateDto.getImageList());
49 |
50 | if (!updateBucketName.equals(bucketDto.getBucketName())) {
51 | bucketMapper.saveBucketLog(bucketId, updateBucketName, BUCKET_NAME_LOG.get());
52 | }
53 |
54 | if (!updateEndDate.equals(bucketDto.getEndDate())) {
55 | bucketMapper.saveBucketLog(bucketId, updateEndDate.replaceAll("-", ". "), BUCKET_END_DATE_LOG.get());
56 | }
57 | }
58 |
59 | private void saveTagList(Long bucketId, List tagList) {
60 | if (!tagList.isEmpty()) {
61 | bucketMapper.saveTagList(tagList);
62 | bucketMapper.saveBucketIdAndTagId(bucketId, tagList);
63 | }
64 | }
65 |
66 | private void updateTag(Long bucketId, List tagList) {
67 | bucketMapper.deleteTagListByBucketId(bucketId);
68 | saveTagList(bucketId, tagList);
69 | }
70 |
71 | private void saveImageUrlList(Long bucketId, List imageUrlList) {
72 | if (!imageUrlList.isEmpty()) {
73 | bucketMapper.saveBucketImageUrlList(bucketId, imageUrlList);
74 | }
75 | }
76 |
77 | private void updateImageUrlList(Long bucketId, List imageUrlList) {
78 | bucketMapper.deleteImageListByBucketId(bucketId);
79 | saveImageUrlList(bucketId, imageUrlList);
80 | }
81 |
82 | // TODO 모든 버킷마다 검증하는 메소드가 들어가는데 이거를 AOP 로 빼던가 해보아도 좋을 거 같음 (얘기 해보기)
83 | public void saveBookmark(Long bucketId, Long userId, boolean isBookmark) {
84 | bucketValidator.checkValidBucket(bucketId, userId);
85 | bucketMapper.setBookmark(bucketId, isBookmark);
86 | }
87 |
88 | public void setBucketFin(Long bucketId, Long userId, boolean isFin) {
89 | bucketValidator.checkValidBucket(bucketId, userId);
90 | bucketMapper.setBucketFin(bucketId, isFin);
91 | }
92 |
93 | @Transactional
94 | public void updateBucketState(Long userId, Long bucketId, int bucketStateId) {
95 | bucketValidator.checkValidBucketStateId(bucketStateId);
96 | bucketValidator.checkValidBucket(bucketId, userId);
97 | bucketMapper.updateBucketState(bucketId, userId, bucketStateId);
98 | }
99 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/jwt/JwtIssueService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.jwt;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.yapp.ios1.config.CacheKey;
6 | import com.yapp.ios1.dto.jwt.JwtPayload;
7 | import com.yapp.ios1.error.exception.common.JsonWriteException;
8 | import com.yapp.ios1.mapper.TokenMapper;
9 | import com.yapp.ios1.properties.JwtProperties;
10 | import io.jsonwebtoken.Jwts;
11 | import io.jsonwebtoken.SignatureAlgorithm;
12 | import lombok.RequiredArgsConstructor;
13 | import org.springframework.cache.annotation.CachePut;
14 | import org.springframework.cache.annotation.Cacheable;
15 | import org.springframework.stereotype.Service;
16 | import org.springframework.transaction.annotation.Transactional;
17 |
18 | import javax.crypto.spec.SecretKeySpec;
19 | import javax.xml.bind.DatatypeConverter;
20 | import java.security.Key;
21 | import java.util.Date;
22 |
23 | /**
24 | * created by ayoung 2021/06/03
25 | */
26 | @RequiredArgsConstructor
27 | @Service
28 | public class JwtIssueService {
29 |
30 | private final JwtProperties jwtProperties;
31 | private final ObjectMapper objectMapper;
32 | private final TokenMapper tokenMapper;
33 |
34 | private String createToken(JwtPayload payload, Long expireTime) {
35 | SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
36 | byte[] secretKeyBytes = DatatypeConverter.parseBase64Binary(jwtProperties.getSecretKey());
37 | Key signingKey = new SecretKeySpec(secretKeyBytes, signatureAlgorithm.getJcaName());
38 | return Jwts.builder()
39 | .setSubject(writeJsonAsString(payload))
40 | .signWith(signingKey, signatureAlgorithm)
41 | .setExpiration(new Date(System.currentTimeMillis() + expireTime))
42 | .compact();
43 | }
44 |
45 | private String writeJsonAsString(JwtPayload payload) {
46 | try {
47 | return objectMapper.writeValueAsString(payload.getId());
48 | } catch (JsonProcessingException e) {
49 | throw new JsonWriteException();
50 | }
51 | }
52 |
53 | public String createAccessToken(JwtPayload payload) {
54 | return createToken(payload, jwtProperties.getAccessToken().getValidTime());
55 | }
56 |
57 | @Transactional
58 | @CachePut(value = CacheKey.TOKEN, key = "#payload.id")
59 | public String createRefreshToken(JwtPayload payload) {
60 | String refreshToken = createToken(payload, jwtProperties.getRefreshToken().getValidTime());
61 | tokenMapper.updateToken(refreshToken, payload.getId());
62 | return refreshToken;
63 | }
64 |
65 | @Cacheable(value = CacheKey.TOKEN, key = "#userId")
66 | public String getRefreshTokenByUserId(Long userId) {
67 | return tokenMapper.getTokenByUserId(userId);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/jwt/JwtService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.jwt;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.yapp.ios1.dto.jwt.JwtPayload;
6 | import com.yapp.ios1.dto.jwt.TokenResponseDto;
7 | import com.yapp.ios1.properties.JwtProperties;
8 | import io.jsonwebtoken.Claims;
9 | import io.jsonwebtoken.Jwts;
10 | import lombok.RequiredArgsConstructor;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.springframework.stereotype.Service;
13 |
14 | import javax.xml.bind.DatatypeConverter;
15 | import java.util.Date;
16 | import java.util.function.Function;
17 |
18 | /**
19 | * created by jg 2021/04/11
20 | */
21 | @Slf4j
22 | @RequiredArgsConstructor
23 | @Service
24 | public class JwtService {
25 |
26 | private final JwtIssueService jwtIssueService;
27 | private final JwtProperties jwtProperties;
28 | private final ObjectMapper objectMapper;
29 |
30 | public JwtPayload getPayload(String token) throws JsonProcessingException {
31 | Claims claims = getAllClaimsFromToken(token);
32 | return objectMapper.readValue(claims.getSubject(), JwtPayload.class);
33 | }
34 |
35 | public Date getExpirationDateFromToken(String token) {
36 | return getClaimFromToken(token, Claims::getExpiration);
37 | }
38 |
39 | public T getClaimFromToken(String token, Function claimsResolver) {
40 | final Claims claims = getAllClaimsFromToken(token);
41 | return claimsResolver.apply(claims);
42 | }
43 |
44 | private Claims getAllClaimsFromToken(String token) {
45 | return Jwts.parserBuilder()
46 | .setSigningKey(DatatypeConverter.parseBase64Binary(jwtProperties.getSecretKey()))
47 | .build()
48 | .parseClaimsJws(token)
49 | .getBody();
50 | }
51 |
52 | public TokenResponseDto createTokenResponse(Long userId) {
53 | JwtPayload jwtPayload = new JwtPayload(userId);
54 | String accessToken = jwtIssueService.createAccessToken(jwtPayload);
55 | String refreshToken = jwtIssueService.createRefreshToken(jwtPayload);
56 |
57 | return TokenResponseDto.builder()
58 | .accessToken(accessToken)
59 | .refreshToken(refreshToken)
60 | .accessExpiredAt(getExpirationDateFromToken(accessToken))
61 | .refreshExpiredAt(getExpirationDateFromToken(refreshToken))
62 | .build();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/user/ProfileService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.user;
2 |
3 | import com.yapp.ios1.controller.dto.user.ProfileUpdateDto;
4 | import com.yapp.ios1.error.exception.user.NickNameDuplicatedException;
5 | import com.yapp.ios1.error.exception.user.UserNotFoundException;
6 | import com.yapp.ios1.mapper.ProfileMapper;
7 | import com.yapp.ios1.model.user.Profile;
8 | import lombok.RequiredArgsConstructor;
9 | import org.springframework.stereotype.Service;
10 | import org.springframework.transaction.annotation.Transactional;
11 |
12 | /**
13 | * created by jg 2021/06/11
14 | */
15 | @RequiredArgsConstructor
16 | @Service
17 | public class ProfileService {
18 |
19 | private final ProfileMapper profileMapper;
20 |
21 | public Profile getProfile(Long userId) {
22 | return profileMapper.findProfileByUserId(userId)
23 | .orElseThrow(UserNotFoundException::new);
24 | }
25 |
26 | @Transactional
27 | public void updateProfile(ProfileUpdateDto profileUpdateDto, Long userId) {
28 | int change = profileMapper.updateProfile(profileUpdateDto, userId);
29 | if (change == 0) {
30 | throw new NickNameDuplicatedException();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/user/UserFindService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.user;
2 |
3 | import com.yapp.ios1.error.exception.user.DeviceTokenNotFoundException;
4 | import com.yapp.ios1.error.exception.user.UserNotFoundException;
5 | import com.yapp.ios1.mapper.UserMapper;
6 | import com.yapp.ios1.model.user.User;
7 | import lombok.RequiredArgsConstructor;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.util.List;
11 | import java.util.Optional;
12 |
13 | /**
14 | * created by jg 2021/06/15
15 | */
16 | @RequiredArgsConstructor
17 | @Service
18 | public class UserFindService {
19 |
20 | private final UserMapper userMapper;
21 |
22 | public String getDeviceToken(Long userId) {
23 | return userMapper.findDeviceTokenByUserId(userId)
24 | .orElseThrow(DeviceTokenNotFoundException::new);
25 | }
26 |
27 | public List getAllDeviceToken() {
28 | return userMapper.findAllUserDeviceToken();
29 | }
30 |
31 | public User getUser(Long userId) {
32 | return userMapper.findByUserId(userId)
33 | .orElseThrow(UserNotFoundException::new);
34 | }
35 |
36 | public Optional findBySocialIdAndSocialType(String socialId, String socialType) {
37 | return userMapper.findBySocialIdAndSocialType(socialId, socialType);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/user/UserInfoService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.user;
2 |
3 | import com.yapp.ios1.dto.bookmark.BookmarkListDto;
4 | import com.yapp.ios1.dto.user.UserInfoDto;
5 | import com.yapp.ios1.mapper.FriendMapper;
6 | import com.yapp.ios1.model.bookmark.Bookmark;
7 | import com.yapp.ios1.model.user.Profile;
8 | import com.yapp.ios1.service.bucket.BucketFindService;
9 | import lombok.RequiredArgsConstructor;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.stereotype.Service;
12 | import org.springframework.transaction.annotation.Transactional;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * created by ayoung 2021/06/12
18 | */
19 | @RequiredArgsConstructor
20 | @Service
21 | public class UserInfoService {
22 |
23 | private final ProfileService profileService;
24 | private final BucketFindService bucketFindService;
25 | private final FriendMapper friendMapper;
26 |
27 | @Transactional(readOnly = true)
28 | public UserInfoDto getOtherUserInfo(Long myUserId, Long otherUserId) {
29 | UserInfoDto userInfo = getUserInfo(otherUserId);
30 |
31 | int friendStatus = friendMapper.checkFriendStatus(myUserId, otherUserId);
32 | userInfo.setFriend(friendStatus);
33 | // 친구 일 때
34 | if (friendStatus == 1) {
35 | userInfo.setBucket(bucketFindService.getUserBucketList(otherUserId));
36 | }
37 |
38 | return userInfo;
39 | }
40 |
41 | @Transactional(readOnly = true)
42 | public UserInfoDto getUserInfo(Long userId) {
43 | Profile profile = profileService.getProfile(userId);
44 |
45 | int friendCount = friendMapper.getFollowCountByUserId(userId);
46 | int bucketCount = bucketFindService.getBucketCountByUserId(userId);
47 |
48 | List bookmarkList = bucketFindService.getBookmarkList(userId);
49 |
50 | return UserInfoDto.builder()
51 | .user(profile)
52 | .friendCount(friendCount)
53 | .bucketCount(bucketCount)
54 | .bookmark(new BookmarkListDto(bookmarkList, bookmarkList.size()))
55 | .build();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/service/user/UserService.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service.user;
2 |
3 | import com.yapp.ios1.dto.jwt.TokenResponseDto;
4 | import com.yapp.ios1.mapper.UserMapper;
5 | import com.yapp.ios1.model.user.User;
6 | import com.yapp.ios1.service.jwt.JwtService;
7 | import lombok.RequiredArgsConstructor;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.stereotype.Service;
11 |
12 | /**
13 | * created by jg 2021/03/28
14 | */
15 | @Slf4j
16 | @RequiredArgsConstructor
17 | @Service
18 | public class UserService {
19 |
20 | private final PasswordEncoder passwordEncoder;
21 | private final JwtService jwtService;
22 | private final UserMapper userMapper;
23 |
24 | // 최신 알림 로그 확인한 상태(true), 확인하지 않은 알림 로그가 존재하는 상태(false)
25 | public void updateUserAlarmReadStatus(Long userId, boolean alarmReadStatus) {
26 | userMapper.updateAlarmStatus(userId, alarmReadStatus);
27 | }
28 |
29 | public TokenResponseDto signUp(User user) {
30 | user.encodePassword(passwordEncoder.encode(user.getPassword()));
31 | userMapper.signUp(user);
32 | return jwtService.createTokenResponse(user.getId());
33 | }
34 |
35 | public void changePassword(Long userId, String password) {
36 | String encodePassword = passwordEncoder.encode(password);
37 | userMapper.changePassword(userId, encodePassword);
38 | }
39 |
40 | public void deleteUser(Long userId) {
41 | userMapper.deleteUser(userId);
42 | }
43 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/utils/AlarmMessageUtil.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.utils;
2 |
3 | import com.yapp.ios1.dto.notification.NotificationForOneDto;
4 | import com.yapp.ios1.service.user.UserFindService;
5 | import lombok.RequiredArgsConstructor;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * created by jg 2021/06/12
10 | */
11 | @RequiredArgsConstructor
12 | @Component
13 | public class AlarmMessageUtil {
14 |
15 | private final UserFindService userFindService;
16 |
17 | public NotificationForOneDto createFollowAlarmMessage(String title, String message, Long sendUserId) {
18 | String deviceToken = userFindService.getDeviceToken(sendUserId);
19 | return NotificationForOneDto.builder()
20 | .title(title)
21 | .message(message)
22 | .deviceToken(deviceToken)
23 | .build();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/utils/RedisUtil.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.utils;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import org.springframework.data.redis.core.StringRedisTemplate;
5 | import org.springframework.data.redis.core.ValueOperations;
6 | import org.springframework.stereotype.Component;
7 | import org.springframework.stereotype.Service;
8 |
9 | import java.time.Duration;
10 |
11 | /**
12 | * created by ayoung 2021/05/23
13 | */
14 | @RequiredArgsConstructor
15 | @Component
16 | public class RedisUtil {
17 |
18 | private final StringRedisTemplate redisTemplate;
19 |
20 | public String getData(String key) {
21 | ValueOperations valueOperations = redisTemplate.opsForValue();
22 | return valueOperations.get(key);
23 | }
24 |
25 | public void setDataExpire(String key, String value, long duration) {
26 | ValueOperations valueOperations = redisTemplate.opsForValue();
27 | Duration expireDuration = Duration.ofMillis(duration);
28 | valueOperations.set(key, value, expireDuration);
29 | }
30 |
31 | public void deleteData(String key) {
32 | redisTemplate.delete(key);
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/validator/AlarmValidator.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.validator;
2 |
3 | import com.yapp.ios1.error.exception.alarm.AlarmNotFoundException;
4 | import com.yapp.ios1.mapper.AlarmMapper;
5 | import lombok.RequiredArgsConstructor;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * created by jg 2021/06/10
10 | */
11 | @RequiredArgsConstructor
12 | @Component
13 | public class AlarmValidator {
14 |
15 | private final AlarmMapper alarmMapper;
16 |
17 | public void checkValidWholeAlarm(Long alarmId) {
18 | alarmMapper.findWholeAlarmByAlarmId(alarmId)
19 | .orElseThrow(AlarmNotFoundException::new);
20 | }
21 |
22 | public void checkValidFollowAlarm(Long alarmId) {
23 | alarmMapper.findFollowAlarmByAlarmId(alarmId)
24 | .orElseThrow(AlarmNotFoundException::new);
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/validator/BucketValidator.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.validator;
2 |
3 | import com.yapp.ios1.error.exception.bucket.BucketNotFoundException;
4 | import com.yapp.ios1.error.exception.bucket.bucketStateIdInvalidException;
5 | import com.yapp.ios1.mapper.BucketMapper;
6 | import lombok.RequiredArgsConstructor;
7 | import org.springframework.stereotype.Component;
8 |
9 | import static com.yapp.ios1.enums.BucketStatus.BUCKET_FAIL;
10 | import static com.yapp.ios1.enums.BucketStatus.BUCKET_WHOLE;
11 |
12 | /**
13 | * created by jg 2021/06/10
14 | */
15 | @RequiredArgsConstructor
16 | @Component
17 | public class BucketValidator {
18 |
19 | private final BucketMapper bucketMapper;
20 |
21 | // TODO findByBucketIdAndUserId 과 checkValidBucket 이름의 관계를 다시 생각해보기..
22 | public void checkValidBucket(Long bucketId, Long userId) {
23 | bucketMapper.findByBucketIdAndUserId(bucketId, userId)
24 | .orElseThrow(BucketNotFoundException::new);
25 | }
26 |
27 | // TODO Validate 책임
28 | public void checkValidBucketStateId(int bucketStateId) {
29 | if (bucketStateId <= BUCKET_WHOLE.get() || bucketStateId > BUCKET_FAIL.get()) {
30 | throw new bucketStateIdInvalidException();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/yapp/ios1/validator/UserValidator.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.validator;
2 |
3 | import com.yapp.ios1.controller.dto.user.login.SignInDto;
4 | import com.yapp.ios1.error.exception.user.*;
5 | import com.yapp.ios1.mapper.UserMapper;
6 | import com.yapp.ios1.model.user.User;
7 | import lombok.RequiredArgsConstructor;
8 | import org.springframework.security.crypto.password.PasswordEncoder;
9 | import org.springframework.stereotype.Component;
10 |
11 | import java.util.Optional;
12 |
13 | /**
14 | * created by jg 2021/06/10
15 | */
16 | @RequiredArgsConstructor
17 | @Component
18 | public class UserValidator {
19 |
20 | private final UserMapper userMapper;
21 | private final PasswordEncoder passwordEncoder;
22 |
23 | public void checkEmailDuplicate(String email) {
24 | Optional user = userMapper.findByEmail(email);
25 | if (user.isPresent()) {
26 | throw new EmailDuplicatedException();
27 | }
28 | }
29 |
30 | public User checkEmailPresent(String email) {
31 | return userMapper.findByEmail(email)
32 | .orElseThrow(EmailNotExistException::new);
33 | }
34 |
35 | public void checkNickName(String nickname) {
36 | Optional user = userMapper.findByNickname(nickname);
37 | if (user.isPresent()) {
38 | throw new NickNameDuplicatedException();
39 | }
40 | }
41 |
42 | public User checkPassword(SignInDto signInDto) {
43 | User user = userMapper.findByEmail(signInDto.getEmail())
44 | .orElseThrow(UserNotFoundException::new);
45 |
46 | if (!passwordEncoder.matches(signInDto.getPassword(), user.getPassword())) {
47 | throw new PasswordNotMatchException();
48 | }
49 |
50 | return user;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ${SLACK_WEBHOOK_URI}
6 |
7 | %d{yyyy-MM-dd HH:mm:ss.SSS} %msg %n
8 |
9 | Buok-Server-log
10 | :stuck_out_tongue_winking_eye:
11 | true
12 |
13 |
14 |
15 |
16 |
17 | %d %-5level %logger{35} - %msg%n
18 |
19 |
20 |
21 |
22 |
23 |
24 | ERROR
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ERROR
12 |
13 |
14 |
15 |
16 | [%date] %highlight([%level]) [%logger{10} %file:%line] %msg%n
17 |
18 |
19 |
20 | YAPP-log
21 |
22 |
23 | YAPP/
24 |
25 |
26 | ap-northeast-2
27 |
28 |
29 |
30 | 50
31 |
32 |
33 |
34 | 30000
35 |
36 |
37 |
38 |
39 | 5000
40 |
41 |
42 |
43 |
44 |
45 | 0
46 |
47 |
48 |
49 |
50 |
51 | [%date] %highlight([%level]) [%logger{10} %file:%line] %msg%n
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/alarmMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
8 | INSERT INTO follow_alarm_log (title, message, from_user_id, alarm_status, created_at, user_id)
9 | VALUES (#{notification.title}, #{notification.message}, #{fromUserId}, #{alarmStatus}, #{time}, #{friendId})
10 |
11 |
12 |
13 | UPDATE follow_alarm_log
14 | SET title = #{notification.title},
15 | message = #{notification.message}
16 | WHERE id = #{alarmId}
17 |
18 |
19 |
20 | INSERT INTO whole_alarm_log (title, message, alarm_status, created_at)
21 | VALUES (#{alarm.title}, #{alarm.message}, #{alarmStatus}, #{alarm.localDateTime})
22 |
23 |
24 |
25 | SELECT id as alarmId,
26 | title,
27 | message,
28 | alarm_status as alarmStatus,
29 | created_at as createdAt
30 | FROM whole_alarm_log
31 | where id NOT IN (SELECT alarm_id FROM whole_alarm_delete WHERE user_id = #{userId})
32 | ORDER BY created_at ASC
33 |
34 |
35 |
36 | SELECT al.id as alarmId,
37 | al.from_user_id as friendId,
38 | message,
39 | u.nickname as nickName,
40 | u.profile_url as profileUrl,
41 | f.friend_status as friendStatus,
42 | alarm_status as alarmStatus,
43 | created_at as createdAt
44 | FROM follow_alarm_log al
45 | JOIN follow f
46 | ON f.alarm_id = al.id
47 | JOIN user u
48 | ON u.id = al.from_user_id
49 | WHERE al.user_id = #{userId}
50 | ORDER BY al.created_at ASC
51 |
52 |
53 |
54 | SELECT id as alarmId
55 | FROM whole_alarm_log
56 | WHERE id = #{alarmId}
57 |
58 |
59 |
60 | SELECT id
61 | FROM follow_alarm_log
62 | WHERE id = #{alarmId}
63 |
64 |
65 |
66 | DELETE FROM follow_alarm_log
67 | WHERE id = #{alarmId}
68 |
69 |
70 |
71 | INSERT INTO whole_alarm_delete (alarm_id, user_id)
72 | VALUES (#{alarmId}, #{userId})
73 |
74 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/bucketMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 | SELECT id,
9 | bucket_name as bucketName,
10 | bucket_content as content,
11 | created_date as createdDate,
12 | end_date as endDate,
13 | bucket_state as bucketState,
14 | category_id as categoryId,
15 | bookmark as isBookmark,
16 | fin as isFin
17 | FROM bucket
18 | WHERE id = #{bucketId} AND user_id = #{userId}
19 |
20 |
21 |
22 | SELECT id,
23 | bucket_name as bucketName,
24 | bucket_content as content,
25 | created_date as createdDate,
26 | end_date as endDate,
27 | bucket_state as bucketState,
28 | category_id as categoryId,
29 | bookmark as isBookmark,
30 | fin as isFin
31 | FROM bucket
32 | WHERE id = #{bucketId}
33 |
34 |
35 |
36 | SELECT id,
37 | bucket_name as bucketName,
38 | created_date as createdDate,
39 | end_date as endDate,
40 | bucket_state as bucketState,
41 | category_id as categoryId,
42 | bookmark as isBookmark,
43 | fin as isFin
44 | FROM bucket
45 | WHERE user_id = #{userId}
46 |
47 |
48 | AND bucket_state = #{bucketState}
49 |
50 |
51 |
52 |
53 | AND category_id = #{category}
54 |
55 |
56 |
57 |
58 | ORDER BY fin DESC, id ASC
59 |
60 |
61 | ORDER BY fin DESC, bucket_name ASC
62 |
63 |
64 |
65 |
66 |
67 | SELECT b.id, b.bucket_name as bucketName,
68 | b.created_date as createdDate,
69 | b.end_date as endDate,
70 | b.bucket_state as bucketState,
71 | c.category_name as categoryName
72 | FROM bucket b
73 | JOIN category c
74 | ON b.category_id = c.id
75 | WHERE b.user_id = #{userId}
76 |
77 |
78 |
79 | SELECT count(id) FROM category WHERE id = #{category};
80 |
81 |
82 |
83 | INSERT INTO bucket (bucket_name, bucket_content, end_date, bucket_state, user_id, category_id)
84 | VALUES(#{bucketName}, #{content}, #{endDate}, #{bucketState}, #{userId}, #{categoryId});
85 |
86 |
87 |
88 | UPDATE bucket
89 | SET bucket_name = #{bucketName},
90 | bucket_content = #{content},
91 | end_date = #{endDate},
92 | bucket_state = #{bucketState},
93 | category_id = #{categoryId}
94 | WHERE id = #{id};
95 |
96 |
97 |
98 | UPDATE bucket
99 | SET bucket_state = #{bucketStateId}
100 | WHERE id = #{bucketId} AND user_id = #{userId}
101 |
102 |
103 |
104 |
105 | INSERT INTO image (bucket_id, image_url)
106 | VALUES
107 |
108 | (#{bucketId}, #{item})
109 |
110 |
111 |
112 |
113 |
114 | SELECT id,
115 | tag_name as tagName
116 | FROM tag
117 | WHERE tag_name = #{tagName};
118 |
119 |
120 |
121 | INSERT INTO bucket_tag (bucket_id, tag_id)
122 |
123 | SELECT #{bucketId}, (SELECT id tag_id
124 | FROM tag
125 | WHERE tag_name = #{item})
126 |
127 |
128 |
129 |
130 | INSERT INTO tag (tag_name)
131 | VALUES
132 |
133 | (#{item})
134 |
135 | ON DUPLICATE KEY
136 | UPDATE
137 | tag_name = VALUES (tag_name)
138 |
139 |
140 |
141 | SELECT id,
142 | bucket_name as bucketName,
143 | category_id as categoryId,
144 | end_date as endDate
145 | FROM bucket
146 | WHERE user_id = #{userId} AND bookmark = true
147 | ORDER BY end_date DESC;
148 |
149 |
150 |
151 | SELECT count(id)
152 | FROM bucket
153 | WHERE user_id = #{userId};
154 |
155 |
156 |
157 | DELETE FROM bucket_tag WHERE bucket_id = #{bucketId};
158 |
159 |
160 |
161 | DELETE FROM image WHERE bucket_id = #{bucketId};
162 |
163 |
164 |
165 | INSERT INTO bucket_log (bucket_id, update_type, content)
166 | VALUES
167 |
168 | (#{item.bucketId}, #{item.updateType}, #{item.content})
169 |
170 |
171 |
172 |
173 | INSERT INTO bucket_log (bucket_id, content)
174 | VALUES
175 |
176 |
177 | (#{bucketId}, CONCAT('제목이 ', #{content}, '로 변경되었습니다.'))
178 |
179 |
180 | (#{bucketId}, CONCAT('완료일이 ', #{content}, '로 변경되었습니다.'))
181 |
182 |
183 |
184 |
185 |
186 | INSERT INTO bucket_log (bucket_id, update_type, content)
187 | SELECT id, 1, bucket_name
188 | FROM bucket WHERE id = #{bucketId};
189 |
190 |
191 |
192 | INSERT INTO bucket_log (bucket_id, update_type, content)
193 | SELECT id, 0, end_date
194 | FROM bucket WHERE id = #{bucketId};
195 |
196 |
197 |
198 | UPDATE bucket
199 | SET
200 | bookmark = #{isBookmark}
201 | WHERE id = #{bucketId};
202 |
203 |
204 |
205 | UPDATE bucket
206 | SET
207 | fin = #{isFin}
208 | WHERE id = #{bucketId};
209 |
210 |
211 |
212 | SELECT t.tag_name as tagName
213 | FROM bucket_tag bt
214 | JOIN tag t
215 | ON t.id = bt.tag_id
216 | WHERE bt.bucket_id = #{bucketId}
217 |
218 |
219 |
220 | SELECT i.image_url as imageUrl
221 | FROM image i
222 | JOIN bucket b
223 | ON i.bucket_id = b.id
224 | WHERE b.id = #{bucketId} AND b.user_id = #{userId}
225 |
226 |
227 |
228 | SELECT bl.content,
229 | bl.modified_date as modifiedDate
230 | FROM bucket b
231 | JOIN bucket_log bl
232 | ON b.id = bl.bucket_id
233 | where b.id = #{bucketId} AND b.user_id = #{userId}
234 | ORDER BY bl.modified_date DESC
235 |
236 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/friendMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | SELECT COUNT(*)
8 | FROM follow
9 | WHERE friend_status = 1 AND follower_id = #{userId}
10 |
11 |
12 |
13 | SELECT u.id as userId,
14 | u.email,
15 | u.nickname,
16 | u.intro,
17 | u.profile_url as profileUrl,
18 | f.friend_status as friendStatus
19 | FROM user u
20 | JOIN follow f
21 | ON f.following_id = u.id
22 | WHERE (f.follower_id = #{userId} AND f.friend_status = 1);
23 |
24 |
25 |
26 | SELECT IFNULL((
27 | SELECT friend_status
28 | FROM follow
29 | WHERE (following_id = #{myUserId} AND follower_id = #{otherUserId}) LIMIT 1), 3)
30 | as friend_status;
31 |
32 |
33 |
34 | INSERT INTO follow (following_id, follower_id, friend_status, alarm_id)
35 | VALUES (#{friendId}, #{myUserId}, #{followRequest}, #{alarmId})
36 |
37 |
38 |
39 | UPDATE follow
40 | SET friend_status = #{friendStatus}
41 | WHERE following_id = #{myUserId} AND follower_id = #{friendId}
42 |
43 |
44 |
45 | DELETE FROM follow
46 | WHERE (following_id = #{myUserId} AND follower_id = #{friendId})
47 |
48 |
49 |
50 | SELECT alarm_id
51 | FROM follow f
52 | WHERE (f.following_id = #{myUserId} AND f.follower_id = #{friendId})
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/profileMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | SELECT id,
8 | email,
9 | nickname,
10 | intro,
11 | created_date as createdDate,
12 | profile_url as profileUrl,
13 | social_type as socialType,
14 | social_id as socialId
15 | FROM user WHERE id = #{userId};
16 |
17 |
18 |
19 | UPDATE
20 | user as a
21 | SET a.nickname = #{profile.nickname},
22 | a.intro = #{profile.intro},
23 | a.profile_url = #{profile.profileUrl}
24 | WHERE (
25 | SELECT c.nickname as nickname
26 | FROM (
27 | SELECT b.nickname as nickname
28 | FROM user as b
29 | WHERE b.id NOT IN (#{userId})
30 | ) as c
31 | WHERE c.nickname IN (#{profile.nickname})
32 | ) IS NULL
33 | AND a.id = #{userId};
34 |
35 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/searchMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | SELECT DISTINCT(b.id),
8 | b.bucket_name as bucketName,
9 | b.bucket_content as content,
10 | b.created_date as createdDate,
11 | b.end_date as endDate,
12 | b.bucket_state as bucketState,
13 | b.bookmark as isBookmark,
14 | b.fin as isFin
15 | FROM bucket b
16 | LEFT JOIN (SELECT bt.bucket_id, t.* FROM bucket_tag bt JOIN tag t ON t.id = bt.tag_id) as t
17 | ON b.id = t.bucket_id
18 | WHERE (b.bucket_name LIKE CONCAT("%", #{keyword}, "%") OR t.tag_name LIKE CONCAT("%", #{keyword}, "%"))
19 | AND user_id = #{userId}
20 |
21 |
22 |
23 | SELECT DISTINCT (u.id) as userId,
24 | u.nickname,
25 | u.intro,
26 | u.profile_url as profileUrl,
27 | IFNULL(f.friend_status, 3) as friendStatus
28 | FROM (
29 | SELECT * FROM user u
30 | WHERE (u.nickname LIKE CONCAT("%", #{keyword}, "%") OR u.intro LIKE CONCAT("%", #{keyword}, "%")) AND u.id NOT IN (#{userId})
31 | ) as u
32 | LEFT OUTER JOIN follow f
33 | ON (u.id = f.follower_id OR f.following_id = u.id) AND (f.follower_id = #{userId} OR f.following_id = #{userId})
34 | ORDER BY friend_status DESC
35 |
36 |
37 |
38 | SELECT DISTINCT (b.id),
39 | u.id as userId,
40 | b.bucket_name as bucketName,
41 | bucket_content as content,
42 | b.bucket_state as bucketState,
43 | b.created_date as createdDate,
44 | b.end_date as endDate,
45 | u.profile_url as userProfileUrl,
46 | c.id as categoryId,
47 | b.bookmark as isBookmark,
48 | b.fin as isFin
49 | FROM bucket b
50 | LEFT JOIN (SELECT bt.bucket_id, t.* FROM bucket_tag bt JOIN tag t ON t.id = bt.tag_id) as t
51 | ON b.id = t.bucket_id
52 | JOIN user u
53 | ON b.user_id = u.id
54 | JOIN category c
55 | ON b.category_id = c.id
56 | WHERE (b.bucket_name LIKE CONCAT("%", #{keyword}, "%")
57 | OR c.category_name LIKE CONCAT("%", #{keyword}, "%"))
58 | AND u.id NOT IN (#{userId}) AND b.bookmark = true
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/tokenMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 | INSERT INTO token (user_id, token)
9 | VALUES (#{userId}, #{refreshToken}) ON DUPLICATE KEY
10 | UPDATE
11 | token = #{refreshToken};
12 |
13 |
14 |
15 | SELECT token
16 | FROM token
17 | WHERE user_id = #{userId};
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/userMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | INSERT INTO user (social_type, password, nickname, intro, social_id, device_token)
10 | VALUES (#{socialType}, #{password}, #{nickname}, #{intro}, #{socialId}, #{deviceToken})
11 |
12 |
13 | INSERT INTO user (email, social_type, password, nickname, intro, social_id, device_token)
14 | VALUES (#{email}, #{socialType}, #{password}, #{nickname}, #{intro}, #{socialId}, #{deviceToken})
15 |
16 |
17 |
18 |
19 |
20 | SELECT id, nickname
21 | FROM user
22 | WHERE id = #{userId};
23 |
24 |
25 |
26 | SELECT id, email, password
27 | FROM user
28 | WHERE email = #{email};
29 |
30 |
31 |
32 | SELECT nickname
33 | FROM user
34 | WHERE nickname = #{nickname};
35 |
36 |
37 |
38 | SELECT id
39 | FROM user
40 | WHERE social_id = #{socialId}
41 | AND social_type = #{socialType};
42 |
43 |
44 |
45 | UPDATE user
46 | SET password = #{password}
47 | WHERE id = #{userId};
48 |
49 |
50 |
51 | SELECT device_token
52 | FROM user
53 | WHERE id = #{userId}
54 |
55 |
56 |
57 | SELECT device_token
58 | FROM user
59 |
60 |
61 |
62 | SELECT alarm_check
63 | FROM user
64 | WHERE id = #{userId}
65 |
66 |
67 |
68 | UPDATE user
69 | SET alarm_check = #{alarmReadStatus}
70 | WHERE id = #{userId}
71 |
72 |
73 |
74 | DELETE
75 | FROM user
76 | WHERE id = #{userId};
77 |
78 |
--------------------------------------------------------------------------------
/src/main/resources/templates/email.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
비밀번호를 잊으셨나요? 너무 걱정 마세요. 저희도 가끔 잊어버린답니다.
7 |
32322323
8 |
buok으로 돌아가 위 인증번호를 입력해 주세요.
9 |
10 | 혹시 비밀번호 재설정을 요청하지 않으셨거나,
11 | 비밀번호를 찾으셨다면 이 이메일을 무시해 주세요.
12 |
13 | 그럼, 계속 저희와 함께 미래 계획을 세워나가 볼까요?
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/test/java/com/yapp/ios1/DBConnectionTest.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1;
2 |
3 | import org.springframework.boot.test.context.SpringBootTest;
4 |
5 | //@SpringBootTest(properties = "spring.config.location=classpath:application.yml")
6 | public class DBConnectionTest {
7 |
8 | // private final Logger logger = LoggerFactory.getLogger(this.getClass());
9 | //
10 | // @Value("${spring.datasource.driver-class-name}")
11 | // private String DRIVER;
12 | //
13 | // @Value("${spring.datasource.url}")
14 | // private String URL;
15 | //
16 | // @Value("${spring.datasource.username}")
17 | // private String USER;
18 | //
19 | // @Value("${spring.datasource.password}")
20 | // private String PASSWORD;
21 | //
22 | // @Test
23 | // public void testConnection() throws ClassNotFoundException {
24 | // Class.forName(DRIVER);
25 | // try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD)) {
26 | // logger.info("Connection : " + connection);
27 | // } catch (Exception e) {
28 | // logger.info("Exception : " + e.getMessage());
29 | // }
30 | // }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/com/yapp/ios1/Ios1ApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class Ios1ApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/java/com/yapp/ios1/dto/ResponseDtoTest.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.dto;
2 |
3 | import org.junit.jupiter.api.DisplayName;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static org.assertj.core.api.Assertions.assertThat;
7 |
8 | /**
9 | * created by ayoung 2021/04/10
10 | */
11 | public class ResponseDtoTest {
12 |
13 | @DisplayName("응답 테스트")
14 | @Test
15 | public void responseTest() {
16 |
17 | // //given
18 | // User userDto = new User("ayong703@gmail.com", SocialType.GOOGLE, "문아영","test", "test");
19 | //
20 | // //when
21 | // ResponseDto res1 = ResponseDto.of(HttpStatus.OK, "응답 테스트 메세지1", userDto);
22 | // ResponseDto res2 = ResponseDto.of(HttpStatus.BAD_REQUEST, "응답 테스트 메세지2");
23 | //
24 | // //then
25 | // assertThat(res1.getStatus()).isEqualTo(200);
26 | // assertThat(res1.getMessage()).isEqualTo("응답 테스트 메세지1");
27 | // assertThat(res1.getData()).isEqualTo(userDto);
28 | //
29 | // assertThat(res2.getStatus()).isEqualTo(400);
30 | // assertThat(res2.getMessage()).isEqualTo("응답 테스트 메세지2");
31 | // assertThat(res2.getData()).isEqualTo(null);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/yapp/ios1/service/EmailServiceTest.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.yapp.ios1.error.exception.user.EmailNotExistException;
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 |
8 | import static org.junit.jupiter.api.Assertions.assertThrows;
9 |
10 | /**
11 | * created by ayoung 2021/06/15
12 | */
13 | //@SpringBootTest
14 | class EmailServiceTest {
15 |
16 | // @Autowired
17 | // private EmailService emailService;
18 | //
19 | // @Test
20 | // void 이메일_전송_성공_테스트() {
21 | // emailService.sendEmailMessage("ayong0310@naver.com");
22 | // }
23 | //
24 | // @Test
25 | // void 이메일_존재X_실패_테스트() {
26 | // assertThrows(EmailNotExistException.class,
27 | // () -> emailService.sendEmailMessage("ang0310@naver.com"));
28 | // }
29 | }
--------------------------------------------------------------------------------
/src/test/java/com/yapp/ios1/service/JwtServiceTest.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
4 | import com.nimbusds.jwt.SignedJWT;
5 | import org.junit.jupiter.api.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.text.ParseException;
10 | import java.util.Date;
11 |
12 | /**
13 | * 임시 토큰 테스트
14 | *
15 | * created by ayoung 2021/05/15
16 | */
17 | public class JwtServiceTest {
18 |
19 | private final Logger logger = LoggerFactory.getLogger(this.getClass());
20 |
21 | @Test
22 | public void decode_테스트() throws ParseException {
23 | SignedJWT signedJWT = SignedJWT.parse("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNjIyODU5ODk0fQ.nLl9b-mGhDdL7p3jnJzVE6Se07nzFkPnHvKF8mhA_6Q");
24 | ReadOnlyJWTClaimsSet payload = signedJWT.getJWTClaimsSet();
25 |
26 | Date currentTime = new Date(System.currentTimeMillis());
27 | if (!currentTime.before(payload.getExpirationTime())) {
28 | logger.info("유효기간 지남");
29 | }
30 |
31 | logger.info("" + payload.getSubject());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/yapp/ios1/service/UserServiceTest.java:
--------------------------------------------------------------------------------
1 | package com.yapp.ios1.service;
2 |
3 | import com.yapp.ios1.mapper.UserMapper;
4 | import com.yapp.ios1.service.user.UserService;
5 | import org.junit.jupiter.api.extension.ExtendWith;
6 | import org.mockito.InjectMocks;
7 | import org.mockito.Mock;
8 | import org.mockito.junit.jupiter.MockitoExtension;
9 |
10 | import static org.assertj.core.api.Assertions.assertThat;
11 |
12 | @ExtendWith(MockitoExtension.class)
13 | public class UserServiceTest {
14 |
15 | @Mock
16 | private UserMapper userMapper;
17 |
18 | @InjectMocks
19 | private UserService userService;
20 | //
21 | // @Test
22 | // @DisplayName("해당 이메일 존재하지 않을 때 리턴값 테스트")
23 | // public void 이메일_존재X_테스트() throws SQLException {
24 | // Optional optional = Optional.ofNullable(null);
25 | // given(userMapper.findByEmail("없는계정@naver.com")).willReturn(optional);
26 | //
27 | // assertThat(userService.emailCheck("없는계정@naver.com")).isEqualTo(Optional.empty());
28 | // }
29 | //
30 | // @Test
31 | // @DisplayName("해당 이메일 존재할 때 리턴값 테스트")
32 | // public void 이메일_존재O_테스트() throws SQLException {
33 | // User user = new User("ayong0310@naver.com", null, "문아영", "test", "test");
34 | // Optional optional = Optional.of(user);
35 | // given(userMapper.findByEmail("ayong0310@naver.com")).willReturn(optional);
36 | //
37 | // Optional retUser = userService.emailCheck("ayong0310@naver.com");
38 | // assertThat(retUser).isEqualTo(Optional.of(user));
39 | // }
40 | }
41 |
--------------------------------------------------------------------------------