181 Commits

Author SHA1 Message Date
sdw086 1eac5db02d admin/front 분리2 2026-07-20 17:49:39 +09:00
sdw086 ed41ef24cb admin/front 분리 2026-07-20 17:49:24 +09:00
sdw086 9269278e40 [PATCH] swagger 문서 버전 정보 기입 2026-06-29 11:48:10 +09:00
sdw086 9a1a1a02c9 [api] admin/notice/~
공지사항 api 추가
2026-06-25 17:42:41 +09:00
sdw086 f6df6bc7cb [api] admin/member/delete
회원 정보삭제 다중으로 받을수 있게 수정
2026-06-24 14:53:24 +09:00
sdw086 d00b7dca70 [api] admin/member/delete
회원 정보삭제 다중으로 받을수 있게 수정
2026-06-24 10:49:59 +09:00
sdw086 70f674f6e7 [api] admin/member/add
회원 정보 등록 추가
2026-06-23 16:30:16 +09:00
sdw086 35b89d861c [api] admin/member/add
회원 정보 등록 추가
2026-06-23 10:27:18 +09:00
sdw086 4b65caee2b [api] md 파일 갱신 2026-05-28 15:05:43 +09:00
sdw086 e8004a7da9 [api] SSO 관리 작업 2026-05-28 14:53:52 +09:00
sdw086 b0646a0d3d [api] 스케줄 관리 작업 2026-05-28 10:30:10 +09:00
sdw086 cbea6bc2af [api] tus 수정 2026-05-27 15:18:03 +09:00
sdw086 85d593fb9d [api] tus 주소 부터 일단변경 2026-05-26 10:02:08 +09:00
sdw086 797b12b459 [api] SecurityConfig.java 수정 2026-05-26 09:04:46 +09:00
sdw086 96fd237aeb [api] fornt 패키지 로 front 파일 이동 2026-05-22 17:44:22 +09:00
sdw086 059d690c93 [api] FileController.java 컨벤션 맞춰 변경 2026-05-22 16:40:22 +09:00
sdw086 24783da7a0 [api] UserController.java 컨벤션 맞춰 변경 및 개인정보 상세 추가 2026-05-22 15:53:15 +09:00
sdw086 7b10ef0db8 [api] SsoController.java, AuthController.java 컨벤션 맞춰 변경 2026-05-22 11:55:48 +09:00
sdw086 3a4f4679c0 [api] CorsController.java 이쪽 컨벤션 맞춰 변경 2026-05-21 18:04:38 +09:00
sdw086 bdaaec4f97 [api] AdminUserController.java 이쪽 컨벤션 맞춰 변경 2026-05-21 17:17:59 +09:00
sdw086 05cf8281f2 [api] AdminAuthController 이쪽 컨벤션 맞춰 변경 2026-05-21 16:56:04 +09:00
sdw086 4c30133285 [api] AdminMemberController 이쪽 컨벤션 맞춰 변경 2026-05-21 16:02:45 +09:00
sdw086 41b3cd5b33 [api] 크로스도메인 등록 목록 작업 2026-05-21 11:56:22 +09:00
sdw086 ada6dfc7b4 [api] 관리자 휴면/탈퇴/삭제 추가 2026-05-20 17:48:07 +09:00
sdw086 b58a321482 [api] 회원 탈퇴 관련 api 추가 2026-05-20 09:00:06 +09:00
sdw086 d5483b790d [api] 회원 목록 & 수정 & 상세 추가 / 각 vo dto contorller schema 추가 2026-05-19 16:17:05 +09:00
sdw086 4cc6078484 [api] 회원정보 수정 & 비밀번호 변경 2026-05-18 10:55:16 +09:00
sdw086 58252a0fda [api] 회원 비밀번호 확인 추가2 2026-05-15 17:39:50 +09:00
sdw086 1f0c76bbd4 [api] 회원 비밀번호 확인 추가2 2026-05-15 17:39:43 +09:00
sdw086 8cdcc81aaf [api] 회원 비밀번호 확인 추가 2026-05-15 17:37:35 +09:00
sdw086 4368eccc82 [api] userType, userRole 추가 2026-05-12 17:40:07 +09:00
sdw086 c7b8478ad0 [api] 회원가입 샘플 추가 2026-05-12 15:00:08 +09:00
sdw086 376a9bb576 [api] tus 파일 다운로드 업로드 주소 변경 2026-05-12 14:48:25 +09:00
sdw086 4e6c87798f [api] 파일업로드, TUS path통일, 권한 내용 변경 2026-05-12 14:40:54 +09:00
sdw086 a4a8b551b0 [api] 파일업로드 공개 2026-05-11 09:50:12 +09:00
sdw086 13e41f6e3c [api] 파일업로드, tus파일 주소변경, md 파일 변경 2026-05-08 17:21:19 +09:00
sdw086 0fc91fddac [api] file -> tusFile 패키지로 변경 2026-05-07 09:45:11 +09:00
sdw086 5d3f5dc15d [admin] 로그인 로그아웃 작업 추가 2026-04-30 08:32:03 +09:00
sdw086 6cae972c0c [개발]AGENTS 문서 업데이트 2026-04-24 10:58:14 +09:00
sdw086 88c3a4364b [api] 코딩 컨벤션 추가 2026-04-09 10:54:53 +09:00
sdw086 b9d534ac7e [API] 멀티 데이터 소스 적용 및 이전 회원조회 작업 2026-04-06 10:57:22 +09:00
sdw086 1ebd75dad1 [API] 로그인 상태 확인시 토큰 존재 유무도 함께 전달 2026-03-31 18:02:41 +09:00
sdw086 9da2585f29 [API] SSO 다중 도메인 로그인 작업 커밋 2026-03-31 17:46:33 +09:00
sdw086 07683e843d [API] SSO 다중 도메인 로그인 작업 커밋 2026-03-31 11:55:23 +09:00
sdw086 6e58d57821 [API] 파일삭제 추가 2026-03-23 14:25:48 +09:00
sdw086 8c78f5b192 [API] 에이전트 엠디 수정 2026-03-18 17:58:17 +09:00
sdw086 64c5d87a99 [API] 파일 상태 조회시 취소 로직 삭제 취소는 스케줄러에서 하기로 2026-03-17 16:06:34 +09:00
sdw086 a121c7710e [위치이동] file 위치이동 2026-03-13 17:49:36 +09:00
sdw086 67667724ee [README] 문서 갱신 2026-03-11 10:44:18 +09:00
sdw086 2a5d7cbc64 [File] 파비콘 없는 애러 수정 2026-03-10 17:58:40 +09:00
sdw086 940d9002ea [File] 이미지 다운로드 뷰 방식 변경 2026-03-10 17:31:51 +09:00
sdw086 bb8f6d27f1 [File] 로컬에서 -> api서버에서 다운로드 가능하게 추가 2026-03-10 16:49:27 +09:00
sdw086 961ea80060 [설정] localhost login 가능하게 수정 2026-03-10 16:15:21 +09:00
sdw086 b52a4eda67 [설정] SSO ON OFF 추가 2026-03-10 15:20:44 +09:00
sdw086 2103183bf5 [설정] SSO ON OFF 추가 2026-03-10 15:10:32 +09:00
sdw086 290c25aa21 [파일 업로드] 파일업로드 뷰 & 다운로드
- 파일 뷰 & 다운로드 작업 커밋
2026-03-10 14:00:33 +09:00
sdw086 7395ebfc79 [파일 업로드] tusHook 작업
- 도커 컴포저 파일 마운트
2026-03-10 08:51:45 +09:00
sdw086 999f36a2b3 [파일 업로드] tusHook 작업
- 파일 이동작업
2026-03-09 18:02:04 +09:00
sdw086 63a6bc82c8 [파일 업로드] tusHook 작업
- 파일 이동작업
2026-03-09 17:50:33 +09:00
sdw086 2d1bc74099 [파일 업로드] tusHook 작업
- 파일 이동작업
2026-03-09 17:29:27 +09:00
sdw086 cf3fa4845f [파일 업로드] tusHook 작업
- 파일 이동작업
2026-03-09 17:04:41 +09:00
sdw086 48f59d7d62 [파일 업로드] tusHook 작업
- 파일 이동작업
2026-03-09 17:02:58 +09:00
sdw086 25bad9c5fc [파일 업로드] tusHook 작업
- 업로드 작업
2026-03-09 16:07:08 +09:00
sdw086 6733aafd79 [파일 업로드] tusHook 작업
- 리줌 키로 다른 파일 올릴때 막기
2026-03-09 15:29:26 +09:00
sdw086 2275c857e9 [파일 업로드] tusHook 작업
- 리줌 키로 다른 파일 올릴때 막기
2026-03-09 11:40:04 +09:00
sdw086 bc5c44b4d7 [파일 업로드] tusHook 작업
- 종료인 상태 update 되지 않도록 수정
2026-03-09 10:57:59 +09:00
sdw086 d8ab8bc4e1 [파일 업로드] tusHook 작업
- 멀티업로드 상태 업로드
2026-03-09 10:45:12 +09:00
sdw086 673635ffeb [파일 업로드] tusHook 작업
- 멀티업로드 상태 업로드
2026-03-09 10:45:00 +09:00
sdw086 47a5e85789 [파일 업로드] tusHook 작업
- 멀티업로드 상태 업로드
2026-03-06 17:51:21 +09:00
sdw086 8ae793626b [파일 업로드] tusHook 작업
- 멀티업로드 상태 업로드
2026-03-06 17:45:46 +09:00
sdw086 5311c816d2 [파일 업로드] tusHook 작업
- 멀티업로드 변경
2026-03-06 16:34:13 +09:00
sdw086 c57b80b950 [파일 업로드] tusHook 작업
- 실시간 상태 조회
2026-03-06 11:44:36 +09:00
sdw086 a40e2b5161 [파일 업로드] tusHook 작업
- 여러번 db 호출 redis로 캐싱화
2026-03-06 10:45:00 +09:00
sdw086 82cd4049af [파일 업로드] tusHook 작업
- 진행중
2026-03-05 17:48:50 +09:00
sdw086 70e0b951c4 [파일 업로드] tusHook 작업
- 진행중
2026-03-05 17:26:53 +09:00
sdw086 bb308493d5 [파일 업로드] tusHook 작업
- 진행중
2026-03-05 17:23:19 +09:00
sdw086 d021c736ad [파일 업로드] tusHook 작업
- 진행중
2026-03-05 17:18:50 +09:00
sdw086 0a6228d66b [파일 업로드] tusHook 작업
- 진행중
2026-03-05 17:15:23 +09:00
sdw086 5a2ef8f754 [파일 업로드] tusHook 작업
- 진행중
2026-03-05 17:12:00 +09:00
sdw086 68bcd449fe [파일 업로드] tusHook 작업
- 빈바디 오류
2026-03-05 16:24:48 +09:00
sdw086 309f44a011 [파일 업로드] tusHook 작업 2026-03-05 16:20:48 +09:00
sdw086 35f3f9d679 [파일 업로드] tus 훅추가 2026-03-05 16:05:14 +09:00
sdw086 4360298934 [tus] 파일업로드 추가 2026-03-05 14:50:52 +09:00
sdw086 be9b62d05e [tus] 파일업로드 추가 2026-03-05 14:06:44 +09:00
sdw086 407f9e4cb2 [tus] 파일업로드 추가 2026-03-05 12:01:36 +09:00
sdw086 93446e5b41 [tus] 파일업로드 추가 2026-03-05 11:55:16 +09:00
sdw086 f2fe4f10c1 [SSO] 추가 2026-03-03 15:16:59 +09:00
shindw 0cf29d4f52 [api] 타임아웃 설정 변경 2026-02-26 16:26:03 +09:00
shindw 719b25ce06 [api] cors 단순화
-수정
2026-02-26 16:16:13 +09:00
shindw 1cda5257ef [api] cors 단순화
- user 제거
2026-02-26 16:12:32 +09:00
shindw 0651014274 [api] cors 단순화
- user 제거
2026-02-26 16:01:27 +09:00
shindw 2d2747f4b9 [api] 오류수정 2026-02-26 15:26:36 +09:00
shindw bb95da21cf [api] 오류수정 2026-02-26 15:25:24 +09:00
shindw 2e08d813d9 [api] 오류수정 2026-02-26 14:57:05 +09:00
shindw 8c6347a5e0 [api] 오류수정 2026-02-26 14:53:04 +09:00
shindw 41ffc865e8 [api] 오류수정
- 도커 no cache
2026-02-26 14:47:10 +09:00
shindw 752bc008aa [api] swagger 셋팅중
- 메모리 방식으로 수정
2026-02-26 14:22:40 +09:00
shindw c71c86792c [api] swagger 셋팅중
- 메모리 방식으로 수정
2026-02-26 14:18:58 +09:00
shindw 4a8a3a9d6d [api] swagger 셋팅중
- 메모리 방식으로 수정
2026-02-26 13:59:58 +09:00
shindw 36cc65add9 [api] swagger 셋팅중
- 캐싱 추가
2026-02-26 11:52:56 +09:00
shindw 4032dbdd41 [api] swagger 셋팅중
- 캐싱 추가
2026-02-26 11:49:42 +09:00
shindw 63ae5ed6c9 [api] swagger 셋팅중
- cors 화이트리스트 허용방식 변경
2026-02-26 11:10:00 +09:00
shindw 2799a61380 [api] swagger 셋팅중
- cors 화이트리스트 허용방식 변경
2026-02-26 09:36:31 +09:00
shindw 43d3f8947e [api] swagger 셋팅중
- cors 화이트리스트 허용방식 변경
2026-02-26 09:35:21 +09:00
shindw 936c26c787 [api] swagger 셋팅중
- cors 추가
2026-02-26 09:19:25 +09:00
shindw 9a03ff19d1 [api] swagger 셋팅중
- cors 추가
2026-02-25 18:04:24 +09:00
shindw 41b7eba619 [api] swagger 셋팅중
- 로그인 추가
2026-02-25 17:11:17 +09:00
shindw b1d4b6a60e 커밋 2026-02-24 17:58:17 +09:00
shindw db245fa0f8 Merge commit '5367465027cfd9d978e6e5f19182b2f38a7ecfb5' 2026-02-24 17:14:28 +09:00
shindw 5367465027 [api] utf8mb4_uca1400_ai_ci 변경 2026-02-24 16:54:40 +09:00
shindw d8239f635e [api] 호스트 db 인식하도록 추가 2026-02-24 16:01:09 +09:00
shindw f293406661 [api] 테스트 user 커밋 2026-02-24 15:51:13 +09:00
shindw 6e734f2b92 [api] 테스트 커밋 2026-02-24 12:02:23 +09:00
shindw b59e6d54e4 [api] claude.md 수정 2026-02-24 09:45:37 +09:00
shindw 7067238dfd [api] claude 변경사항 추가 2026-02-24 09:33:04 +09:00
shindw bfa5166941 [api] claude.md 파일 생성 2026-02-23 11:03:53 +09:00
shindw cf89281616 [api] swagger 셋팅중
- 패스 수정
2026-02-11 17:18:16 +09:00
shindw aa6bb2b579 [api] swagger 셋팅중
- 체인설정 수정
2026-02-11 17:16:07 +09:00
shindw 5a59c78d83 [api] swagger 셋팅중
- swagger login 처리
2026-02-11 17:04:06 +09:00
shindw 9bc499ab97 [api] swagger 셋팅중 2026-02-11 11:36:41 +09:00
shindw d40ec9488b [api] 로그백설정
로그백설정
2026-02-10 09:28:30 +09:00
shindw 98da8b9c30 [api] 로그백설정
로그백설정
2026-02-09 17:55:12 +09:00
shindw 454ddeb95a [api] 포트변경
헬스체크 변경
2026-02-06 10:37:04 +09:00
shindw 5b905bb520 [api] 포트변경 2026-02-05 17:10:02 +09:00
shindw 633be0a143 [api] 포트변경 2026-02-05 16:45:08 +09:00
shindw 61eb97215e [api] logback
- 압축안하게 설정
2026-02-05 15:04:41 +09:00
shindw cfd6ec852c [api] Jenkinsfile.pjt
- 레파지토리 이미지 삭제
2026-02-05 11:15:33 +09:00
shindw c3d65c8874 [api] Jenkinsfile.pjt
- 레파지토리 이미지 삭제
2026-02-05 09:57:38 +09:00
shindw b5bf7d795c [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-05 09:25:33 +09:00
shindw 7385627622 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-05 09:24:05 +09:00
shindw 64382f6741 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:58:49 +09:00
shindw 355441c322 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:54:54 +09:00
shindw af4b2d40a3 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:39:16 +09:00
shindw a956a94cbf [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:38:08 +09:00
shindw 567d658773 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:34:59 +09:00
shindw b952a8d841 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:27:23 +09:00
shindw 68cb556370 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:04:47 +09:00
shindw 77454edd41 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 17:04:21 +09:00
shindw 87f382aaec [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 16:45:37 +09:00
shindw 494f18c451 [api] Jenkinsfile.pjt
- 레파지토리 이미지 목록 조회
2026-02-04 16:43:50 +09:00
shindw bbedb7a46d [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:33:54 +09:00
shindw d28f9eca26 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:31:44 +09:00
shindw 203d65ac36 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:26:07 +09:00
shindw 92d18791d6 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:23:42 +09:00
shindw 1967654d4a [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:22:21 +09:00
shindw 18863643ea [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:20:59 +09:00
shindw 1f9399837b [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:15:12 +09:00
shindw 06faa99267 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 16:06:01 +09:00
shindw 8d38ae1a9c [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 15:53:09 +09:00
shindw 6722d774a7 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 15:47:04 +09:00
shindw 0e8876e66f [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 15:44:48 +09:00
shindw 9c85d89f07 [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 15:41:34 +09:00
shindw 5618d54a7c [api] Jenkinsfile.pjt
- 삭제정책 추가
2026-02-04 15:20:27 +09:00
shindw a3be7202a3 [api] Jenkinsfile.pjt
- 포트 변경
2026-02-04 14:25:52 +09:00
shindw 0add5e1cd8 [api] Jenkinsfile.pjt
- 도커 푸시
2026-02-04 10:28:35 +09:00
shindw 4d4c998770 [api] Jenkinsfile.pjt
- 도커 푸시
2026-02-04 10:19:05 +09:00
shindw e4f353b097 [api] Jenkinsfile.pjt
- 도커 up
2026-02-03 17:55:10 +09:00
shindw 1cdf8977ae [api] Jenkinsfile.pjt
- 도커 pull까지 완성
2026-02-03 17:24:32 +09:00
shindw 02b13d18fe [api] Jenkinsfile.pjt
- 도커 pull까지 완성
2026-02-03 17:19:30 +09:00
shindw 494ba05690 [api] Jenkinsfile.pjt
- 도커 pull까지 완성
2026-02-03 17:03:27 +09:00
shindw fd432ff0dd [api] Jenkinsfile.pjt
- 도커 pull까지 완성
2026-02-03 17:01:29 +09:00
shindw cbf40f3099 [api] Jenkinsfile.pjt
- 도커 pull까지 완성
2026-02-03 17:00:54 +09:00
shindw a5ec049040 [api] Jenkinsfile.pjt
- 도커 pull까지 완성
2026-02-03 16:56:46 +09:00
shindw 1113355c74 [api] Jenkinsfile.pjt
- 컴포즈 복사2
2026-02-03 16:24:51 +09:00
shindw 18eb159f26 [api] Jenkinsfile.pjt
- 컴포즈 복사
2026-02-03 16:23:49 +09:00
shindw f87828b4e5 [api] Jenkinsfile.pjt 작업중 2026-02-03 15:49:41 +09:00
shindw 6de8ebca9b [api] Jenkinsfile.pjt 작업중
- 도커 푸시2
2026-02-03 11:07:35 +09:00
shindw 7341f28f9d [api] Jenkinsfile.pjt 작업중
- 도커 푸시
2026-02-03 11:05:28 +09:00
shindw 2a2193fdcd [api] Jenkinsfile.pjt 작업중
- gradle 에 jar 하나만 생성되게 수정
2026-02-03 10:56:31 +09:00
shindw c1b4f4a6fd [api] Jenkinsfile.pjt 작업중
- 도커 빌드
2026-02-03 10:35:59 +09:00
shindw e0f731718e [api] Jenkinsfile.pjt 작업중 2026-02-03 10:26:15 +09:00
shindw 81ef72f843 [api] Jenkinsfile.pjt 작업중 2026-02-03 10:24:06 +09:00
shindw 8649829e51 [api] Jenkinsfile.pjt 작업중 2026-02-03 10:22:34 +09:00
shindw 38813d8ef6 [api] 빌드번호 삭제 2026-02-03 10:21:08 +09:00
shindw a69293fb51 [api] 젠킨스 파일 테그 이미지 생성 2026-02-03 09:31:01 +09:00
shindw b57bc4aaf4 [api] 젠킨스 파일 오류 수정 2026-02-02 16:51:47 +09:00
shindw a6dfbb93a5 [api] 서버 포트 설정 2026-02-02 16:37:57 +09:00
shindw 72e4fff956 [api] 서버 포트 설정 2026-02-02 16:32:27 +09:00
shindw 75d1dc0dff [api] compose 설정 및 dockerfile 생성 jenkinsfile생성 logback 기본생성 배너파일추가 2026-02-02 16:29:33 +09:00
shindw cbc0d644be [api] gradle boot web 추가 2026-02-02 10:47:45 +09:00
shindw bac18a72f5 [api] 디폴트 셋팅 2026-01-30 18:05:35 +09:00
493 changed files with 20100 additions and 69 deletions
+3
View File
@@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
+40
View File
@@ -0,0 +1,40 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Claude Code ###
.claude/
+34
View File
@@ -0,0 +1,34 @@
plugins {
id 'java-library'
}
dependencies {
api 'org.springframework.boot:spring-boot-starter'
api 'org.springframework.boot:spring-boot-starter-web'
api 'org.springframework.boot:spring-boot-starter-validation'
api 'org.springframework.boot:spring-boot-starter-security'
api 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
api 'io.swagger.core.v3:swagger-annotations-jakarta:2.2.27'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
runtimeOnly 'com.microsoft.sqlserver:mssql-jdbc:12.8.1.jre11'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
jar {
enabled = true
}
@@ -0,0 +1,119 @@
package com.alist.api.core.common.exception;
import com.alist.api.core.common.response.ApiResponse;
import com.alist.api.core.common.response.ApiResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import java.util.LinkedHashMap;
import java.util.Map;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ApiResponse<Void>> handleIllegalArgument(IllegalArgumentException e) {
log.warn("IllegalArgumentException: {}", e.getMessage());
return ApiResponse.entity(ApiResponseCode.CODE_400);
}
@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseEntity<ApiResponse<Void>> handleMissingParam(MissingServletRequestParameterException e) {
log.warn("Missing request parameter: {} (type={})", e.getParameterName(), e.getParameterType());
return ApiResponse.entity(ApiResponseCode.CODE_4003);
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseEntity<ApiResponse<Void>> handleMethodNotSupported(HttpRequestMethodNotSupportedException e) {
log.warn("Method not supported: {} (supported={})", e.getMethod(), e.getSupportedHttpMethods());
return ApiResponse.entity(ApiResponseCode.CODE_405);
}
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<ApiResponse<Void>> handleNotFound(NotFoundException e) {
log.warn("Not found: {}", e.getMessage());
return ApiResponse.entity(ApiResponseCode.CODE_404);
}
// 입력오류
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiResponse<Map<String, String>>> handleMethodArgumentNotValid(MethodArgumentNotValidException e) {
Map<String, String> fieldErrors = new LinkedHashMap<>();
for (FieldError fe : e.getBindingResult().getFieldErrors()) {
fieldErrors.putIfAbsent(fe.getField(), fe.getDefaultMessage());
}
log.warn("Validation failed: {}", e.getMessage());
return ApiResponse.entity(fieldErrors, ApiResponseCode.CODE_4001);
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<ApiResponse<Void>> handleTypeMismatch(MethodArgumentTypeMismatchException e) {
log.warn("Type mismatch: name={}, value={}", e.getName(), e.getValue());
return ApiResponse.entity(ApiResponseCode.CODE_4001);
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<ApiResponse<Void>> handleNotReadable(HttpMessageNotReadableException e) {
log.warn("Unreadable message (json parse?) : {}", e.getMessage());
return ApiResponse.entity(ApiResponseCode.CODE_4001);
}
@ExceptionHandler(BindException.class)
public ResponseEntity<ApiResponse<Map<String, String>>> handleBindException(BindException e) {
Map<String, String> fieldErrors = new LinkedHashMap<>();
for (FieldError fe : e.getBindingResult().getFieldErrors()) {
fieldErrors.putIfAbsent(fe.getField(), fe.getDefaultMessage());
}
log.warn("Bind failed: {}", e.getMessage());
return ApiResponse.entity(fieldErrors, ApiResponseCode.CODE_4001);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Void>> handleException(Exception e) {
log.error("Unhandled exception occurred", e);
return ApiResponse.entity(ApiResponseCode.CODE_500);
}
@ExceptionHandler(NoResourceFoundException.class)
public ResponseEntity<ApiResponse<Void>> handleNoResourceFound(NoResourceFoundException e) {
String resourcePath = e.getResourcePath();
if ("favicon.ico".equals(resourcePath) || "/favicon.ico".equals(resourcePath)) {
return ApiResponse.entity(ApiResponseCode.CODE_204);
}
log.error("Unhandled exception occurred", e);
return ApiResponse.entity(ApiResponseCode.CODE_404);
}
}
@@ -0,0 +1,155 @@
package com.alist.api.core.common.file.service;
import com.alist.api.core.config.file.FileUploadProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Iterator;
@Service
public class FileImageService {
public record ImageSize(int width, int height) {
}
public ImageSize resizeAndSave(MultipartFile multipartFile, Path savePath, FileUploadProperties.Resize resize, String extension) throws IOException {
BufferedImage source = ImageIO.read(multipartFile.getInputStream());
if (source == null) {
throw new IllegalArgumentException("invalid image");
}
BufferedImage target;
if (resize.getWidth() != null && resize.getHeight() != null) {
target = cropAndResize(source, resize.getWidth(), resize.getHeight());
} else if (resize.getMaxWidth() != null && source.getWidth() > resize.getMaxWidth()) {
target = resizeByMaxWidth(source, resize.getMaxWidth());
} else {
target = source;
}
writeImage(target, imageFormat(extension), savePath, resize.getQuality());
return new ImageSize(target.getWidth(), target.getHeight());
}
public ImageSize readSize(Path path) throws IOException {
BufferedImage image = ImageIO.read(path.toFile());
if (image == null) {
return null;
}
return new ImageSize(image.getWidth(), image.getHeight());
}
private BufferedImage cropAndResize(BufferedImage source, int targetWidth, int targetHeight) {
double targetRatio = (double) targetWidth / targetHeight;
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
double sourceRatio = (double) sourceWidth / sourceHeight;
int cropWidth = sourceWidth;
int cropHeight = sourceHeight;
if (sourceRatio > targetRatio) {
cropWidth = (int) Math.round(sourceHeight * targetRatio);
} else {
cropHeight = (int) Math.round(sourceWidth / targetRatio);
}
BufferedImage cropped = source.getSubimage(
(sourceWidth - cropWidth) / 2
, (sourceHeight - cropHeight) / 2
, cropWidth
, cropHeight
);
return resize(cropped, targetWidth, targetHeight);
}
private BufferedImage resizeByMaxWidth(BufferedImage source, int maxWidth) {
int targetWidth = maxWidth;
int targetHeight = (int) Math.round((double) source.getHeight() * targetWidth / source.getWidth());
return resize(source, targetWidth, targetHeight);
}
private BufferedImage resize(BufferedImage source, int width, int height) {
BufferedImage target = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = target.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.drawImage(source, 0, 0, width, height, null);
graphics.dispose();
return target;
}
private void writeImage(BufferedImage image, String format, Path savePath, Float quality) throws IOException {
if (!"jpeg".equals(format)) {
boolean written = ImageIO.write(image, format, savePath.toFile());
if (!written) {
throw new IllegalArgumentException("unsupported image format");
}
return;
}
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpeg");
if (!writers.hasNext()) {
throw new IllegalArgumentException("unsupported image format");
}
ImageWriter writer = writers.next();
ImageWriteParam parameter = writer.getDefaultWriteParam();
if (parameter.canWriteCompressed()) {
parameter.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
parameter.setCompressionQuality(normalizeQuality(quality));
}
try (ImageOutputStream output = ImageIO.createImageOutputStream(savePath.toFile())) {
writer.setOutput(output);
writer.write(null, new IIOImage(image, null, null), parameter);
} finally {
writer.dispose();
}
}
private float normalizeQuality(Float quality) {
if (quality == null) {
return 0.9f;
}
if (quality < 0.0f) {
return 0.0f;
}
if (quality > 1.0f) {
return 1.0f;
}
return quality;
}
private String imageFormat(String extension) {
if ("jpg".equalsIgnoreCase(extension)) {
return "jpeg";
}
return extension.toLowerCase();
}
}
@@ -0,0 +1,288 @@
package com.alist.api.core.common.file.service;
import com.alist.api.core.common.file.vo.FileStorageUploadVo;
import com.alist.api.core.config.file.FileUploadProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.Locale;
import java.util.UUID;
@Service
public class FileStorageService {
private static final String PUBLIC_PREFIX = "/uploads";
@Value("${file.storage.root-path}")
private String rootPath;
@Value("${file.storage.view-domain}")
private String viewDomain;
private final FileUploadProperties fileUploadProperties;
private final FileImageService fileImageService;
public FileStorageService(FileUploadProperties fileUploadProperties, FileImageService fileImageService) {
this.fileUploadProperties = fileUploadProperties;
this.fileImageService = fileImageService;
}
public FileStorageUploadVo saveFileUpload(String folder, MultipartFile multipartFile) {
if (folder == null || folder.isBlank()) {
throw new IllegalArgumentException("invalid folder");
}
if (multipartFile == null || multipartFile.isEmpty()) {
throw new IllegalArgumentException("empty file");
}
FileUploadProperties.UploadType uploadType = resolveUploadType(folder);
String originalFileName = cleanFileName(multipartFile.getOriginalFilename());
String extension = extractExtension(originalFileName);
validateExtension(extension);
validateSize(multipartFile.getSize(), uploadType);
boolean image = isImageExtension(extension);
if (uploadType.isImageOnly() && !image) {
throw new IllegalArgumentException("image only");
}
LocalDate today = LocalDate.now();
String storedFileName = UUID.randomUUID().toString().replace("-", "") + "." + extension;
Path savePath = Paths.get(
rootPath
, uploadType.getFolder()
, String.valueOf(today.getYear())
, "%02d".formatted(today.getMonthValue())
, "%02d".formatted(today.getDayOfMonth())
, storedFileName
).normalize().toAbsolutePath();
ensureUnderRoot(savePath);
try {
Files.createDirectories(savePath.getParent());
FileImageService.ImageSize imageSize = null;
if (image && uploadType.getResize() != null && uploadType.getResize().isEnabled()) {
imageSize = fileImageService.resizeAndSave(multipartFile, savePath, uploadType.getResize(), extension);
} else {
multipartFile.transferTo(savePath);
if (image) {
imageSize = fileImageService.readSize(savePath);
}
}
FileStorageUploadVo fileStorageUploadVo = new FileStorageUploadVo();
fileStorageUploadVo.setUploadPath(toUploadPath(savePath));
fileStorageUploadVo.setOriginalFileName(originalFileName);
fileStorageUploadVo.setStoredFileName(storedFileName);
fileStorageUploadVo.setFileExtension(extension);
fileStorageUploadVo.setContentType(multipartFile.getContentType());
fileStorageUploadVo.setFileSize(Files.size(savePath));
fileStorageUploadVo.setWidth(imageSize == null ? null : imageSize.width());
fileStorageUploadVo.setHeight(imageSize == null ? null : imageSize.height());
return fileStorageUploadVo;
} catch (IOException exception) {
throw new IllegalStateException("file save failed", exception);
}
}
public ResponseEntity<Resource> loadFileResource(String uploadPath, boolean inline) {
try {
Path filePath = resolveUploadPath(uploadPath);
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
return ResponseEntity.notFound().build();
}
String contentType = Files.probeContentType(filePath);
if (contentType == null || contentType.isBlank()) {
contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
}
ContentDisposition contentDisposition = inline
? ContentDisposition.inline().filename(filePath.getFileName().toString(), StandardCharsets.UTF_8).build()
: ContentDisposition.attachment().filename(filePath.getFileName().toString(), StandardCharsets.UTF_8).build();
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.contentLength(Files.size(filePath))
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
.body(new InputStreamResource(Files.newInputStream(filePath)));
} catch (IOException exception) {
throw new IllegalStateException("file read failed", exception);
}
}
public String buildFileViewUrl(String uploadPath) {
if (viewDomain == null || viewDomain.isBlank()) {
throw new IllegalStateException("file.storage.view-domain is empty");
}
String fileDomain = viewDomain.endsWith("/")
? viewDomain.substring(0, viewDomain.length() - 1)
: viewDomain;
String normalizedUploadPath = uploadPath.startsWith("/") ? uploadPath : "/" + uploadPath;
return fileDomain + normalizedUploadPath;
}
private Path resolveUploadPath(String uploadPath) {
if (uploadPath == null || uploadPath.isBlank()) {
throw new IllegalArgumentException("empty path");
}
String normalizedUploadPath = uploadPath.trim().replace("\\", "/");
if (!normalizedUploadPath.startsWith(PUBLIC_PREFIX + "/")) {
throw new IllegalArgumentException("invalid path");
}
String relativePath = normalizedUploadPath.substring((PUBLIC_PREFIX + "/").length());
if (relativePath.contains("..") || relativePath.startsWith("/") || relativePath.contains(":")) {
throw new IllegalArgumentException("invalid path");
}
Path rootPath = rootPath();
Path resolvedPath = rootPath.resolve(relativePath).normalize().toAbsolutePath();
if (!resolvedPath.startsWith(rootPath)) {
throw new IllegalArgumentException("invalid path");
}
return resolvedPath;
}
private String toUploadPath(Path savePath) {
Path rootPath = rootPath();
Path absolutePath = savePath.normalize().toAbsolutePath();
if (!absolutePath.startsWith(rootPath)) {
throw new IllegalArgumentException("invalid path");
}
return PUBLIC_PREFIX + "/" + rootPath.relativize(absolutePath).toString().replace("\\", "/");
}
private void ensureUnderRoot(Path path) {
if (!path.startsWith(rootPath())) {
throw new IllegalArgumentException("invalid save path");
}
}
private Path rootPath() {
return Paths.get(rootPath).normalize().toAbsolutePath();
}
private void validateSize(long fileSize, FileUploadProperties.UploadType uploadType) {
long maxSize = uploadType.getMaxSize() == null
? fileUploadProperties.getMaxSize().toBytes()
: uploadType.getMaxSize().toBytes();
if (fileSize > maxSize) {
throw new IllegalArgumentException("file size exceeded");
}
}
private void validateExtension(String extension) {
if (extension.isBlank() || fileUploadProperties.getAllowedExtensions().stream().noneMatch(extension::equalsIgnoreCase)) {
throw new IllegalArgumentException("invalid extension");
}
}
private String cleanFileName(String fileName) {
if (fileName == null || fileName.isBlank()) {
throw new IllegalArgumentException("empty file name");
}
return Paths.get(fileName).getFileName().toString();
}
private String extractExtension(String fileName) {
int extensionIndex = fileName.lastIndexOf('.');
if (extensionIndex < 0 || extensionIndex == fileName.length() - 1) {
return "";
}
return fileName.substring(extensionIndex + 1).trim().toLowerCase(Locale.ROOT);
}
private boolean isImageExtension(String extension) {
return "jpg".equals(extension)
|| "jpeg".equals(extension)
|| "png".equals(extension)
|| "gif".equals(extension);
}
private FileUploadProperties.UploadType resolveUploadType(String folder) {
String normalizedFolder = normalizeFolder(folder);
FileUploadProperties.UploadType uploadType = fileUploadProperties.getTypes() == null
? null
: fileUploadProperties.getTypes().get(normalizedFolder);
if (uploadType != null) {
uploadType.setFolder(normalizeFolder(uploadType.getFolder()));
return uploadType;
}
FileUploadProperties.UploadType fallbackUploadType = new FileUploadProperties.UploadType();
fallbackUploadType.setFolder(normalizedFolder);
fallbackUploadType.setMaxSize(null);
fallbackUploadType.setImageOnly(false);
fallbackUploadType.setResize(new FileUploadProperties.Resize());
fallbackUploadType.getResize().setEnabled(false);
return fallbackUploadType;
}
private String normalizeFolder(String folder) {
if (folder == null || folder.isBlank()) {
throw new IllegalArgumentException("invalid folder");
}
String normalizedFolder = folder.trim().replace("\\", "/");
while (normalizedFolder.startsWith("/")) {
normalizedFolder = normalizedFolder.substring(1);
}
while (normalizedFolder.endsWith("/")) {
normalizedFolder = normalizedFolder.substring(0, normalizedFolder.length() - 1);
}
if (normalizedFolder.isBlank()
|| normalizedFolder.contains("..")
|| normalizedFolder.contains(":")
|| normalizedFolder.startsWith("http://")
|| normalizedFolder.startsWith("https://")) {
throw new IllegalArgumentException("invalid folder");
}
if (!normalizedFolder.matches("^[a-zA-Z0-9/_-]+$")) {
throw new IllegalArgumentException("invalid folder");
}
return normalizedFolder;
}
}
@@ -0,0 +1,17 @@
package com.alist.api.core.common.file.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileStorageUploadVo {
private String uploadPath;
private String originalFileName;
private String storedFileName;
private String fileExtension;
private String contentType;
private Long fileSize;
private Integer width;
private Integer height;
}
@@ -0,0 +1,29 @@
package com.alist.api.core.common.jwt;
import com.alist.api.core.common.response.ApiResponse;
import com.alist.api.core.common.response.ApiResponseCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import java.io.IOException;
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException e) throws IOException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
ApiResponse<Void> body = ApiResponse.body(ApiResponseCode.CODE_403);
objectMapper.writeValue(response.getOutputStream(), body);
}
}
@@ -0,0 +1,28 @@
package com.alist.api.core.common.jwt;
import com.alist.api.core.common.response.ApiResponse;
import com.alist.api.core.common.response.ApiResponseCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import java.io.IOException;
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException e) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
ApiResponse<Void> body = ApiResponse.body(ApiResponseCode.CODE_401);
objectMapper.writeValue(response.getOutputStream(), body);
}
}
@@ -0,0 +1,101 @@
package com.alist.api.core.common.jwt;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.List;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenProvider jwtTokenProvider;
private final String requiredScope;
private final String accessTokenCookieName;
public JwtAuthenticationFilter(
JwtTokenProvider jwtTokenProvider,
String requiredScope,
String accessTokenCookieName
) {
this.jwtTokenProvider = jwtTokenProvider;
this.requiredScope = requiredScope;
this.accessTokenCookieName = accessTokenCookieName;
}
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {
try {
String token = resolveToken(request);
if (token != null && jwtTokenProvider.validateToken(token)) {
String principal = jwtTokenProvider.getUserTokenIdx(token);
String role = jwtTokenProvider.getRole(token);
String scope = jwtTokenProvider.getScope(token);
String tokenType = jwtTokenProvider.getTokenType(token);
boolean authenticatable =
requiredScope.equals(scope)
&& role != null
&& "ACCESS".equals(tokenType);
if (authenticatable) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
principal,
null,
List.of(new SimpleGrantedAuthority("ROLE_" + role))
);
authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (Exception e) {
SecurityContextHolder.clearContext();
}
filterChain.doFilter(request, response);
}
private String resolveToken(HttpServletRequest request) {
String bearer = request.getHeader(HttpHeaders.AUTHORIZATION);
if (bearer != null && bearer.startsWith("Bearer ")) {
String token = bearer.substring(7).trim();
if (!token.isEmpty()) {
return token;
}
}
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return null;
}
for (Cookie cookie : cookies) {
if (accessTokenCookieName.equals(cookie.getName())) {
String token = cookie.getValue();
if (token != null && !token.isBlank()) {
return token.trim();
}
}
}
return null;
}
}
@@ -0,0 +1,172 @@
package com.alist.api.core.common.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Date;
@Component
public class JwtTokenProvider {
private final SecretKey secretKey;
private final long accessTokenValiditySeconds;
private final long refreshTokenValiditySeconds;
public JwtTokenProvider(
@Value("${jwt.secret}") String secret,
@Value("${jwt.access-token-validity-seconds}") long accessTokenValiditySeconds,
@Value("${jwt.refresh-token-validity-seconds}") long refreshTokenValiditySeconds
) {
this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
this.accessTokenValiditySeconds = accessTokenValiditySeconds;
this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
}
/** 토큰생성 **/
public String createToken(String userId) {
Date now = new Date();
Date expiry = new Date(
now.getTime() + accessTokenValiditySeconds * 1000
);
return Jwts.builder()
.setSubject(userId)
.claim("role", "TEST")
.claim("scope", "USER")
.claim("tokenType", "ACCESS")
.setIssuedAt(now)
.setExpiration(expiry)
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
/* 엑세스 토큰 생성 */
public String createAccessToken(Integer userTokenIdx, String role) {
Instant now = Instant.now();
Instant expiry = now.plusSeconds(accessTokenValiditySeconds);
return Jwts.builder()
.setSubject(String.valueOf(userTokenIdx))
.claim("role", role)
.claim("scope", "USER")
.claim("tokenType", "ACCESS")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(expiry))
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
/* 리프레시 토큰 생성 */
public String createRefreshToken(Integer userTokenIdx) {
Instant now = Instant.now();
Instant expiry = now.plusSeconds(refreshTokenValiditySeconds);
return Jwts.builder()
.setSubject(String.valueOf(userTokenIdx))
.claim("scope", "USER")
.claim("tokenType", "REFRESH")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(expiry))
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
/** 토큰에서 subject 추출 */
public String getUserTokenIdx(String token) {
return parseClaims(token).getSubject();
}
/** 토큰 검증 */
public boolean validateToken(String token) {
try {
parseClaims(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}
private Claims parseClaims(String token) {
return Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token)
.getBody();
}
/* 업로드 전용 토큰*/
public String createUploadToken(long userTokenIdx) {
Instant now = Instant.now();
Instant expiry = now.plusSeconds(300); // 5분
return Jwts.builder()
.setSubject(String.valueOf(userTokenIdx))
.claim("scope", "UPLOAD")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(expiry))
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
public boolean hasUploadScope(String token) {
try {
Claims claims = parseClaims(token);
return "UPLOAD".equals(claims.get("scope", String.class));
} catch (Exception e) {
return false;
}
}
public String createAdminAccessToken(long userTokenIdx) {
Instant now = Instant.now();
Instant expiry = now.plusSeconds(accessTokenValiditySeconds);
return Jwts.builder()
.setSubject(String.valueOf(userTokenIdx))
.claim("role", "ADMIN")
.claim("scope", "ADMIN")
.claim("tokenType", "ACCESS")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(expiry))
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
public String createAdminRefreshToken(long userTokenIdx) {
Instant now = Instant.now();
Instant expiry = now.plusSeconds(refreshTokenValiditySeconds);
return Jwts.builder()
.setSubject(String.valueOf(userTokenIdx))
.claim("role", "ADMIN")
.claim("scope", "ADMIN")
.claim("tokenType", "REFRESH")
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(expiry))
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
public Claims getClaims(String token) {
return parseClaims(token);
}
public String getRole(String token) {
return parseClaims(token).get("role", String.class);
}
public String getScope(String token) {
return parseClaims(token).get("scope", String.class);
}
public String getTokenType(String token) {
return parseClaims(token).get("tokenType", String.class);
}
}
@@ -0,0 +1,32 @@
package com.alist.api.core.common.paging;
import com.alist.api.core.common.utils.PagingUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Setter;
@Setter
public class PagingRequest {
@Schema(description = "페이지 번호", example = "1")
private Integer page;
@Schema(description = "페이지 크기", example = "20")
private Integer size;
public Integer getPage() {
return PagingUtil.getPage(page);
}
public Integer getSize() {
return PagingUtil.getSize(size);
}
@Schema(hidden = true)
public Integer getLimit() {
return PagingUtil.getLimit(size);
}
@Schema(hidden = true)
public Integer getOffset() {
return PagingUtil.getOffset(page, size);
}
}
@@ -0,0 +1,36 @@
package com.alist.api.core.common.paging;
import com.alist.api.core.common.utils.PagingUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PagingResponse {
@Schema(description = "현재 페이지 번호", example = "1")
private int page;
@Schema(description = "페이지당 조회 개수", example = "20")
private int size;
@Schema(description = "전체 데이터 개수", example = "100")
private int totalCount;
@Schema(description = "전체 페이지 수", example = "5")
private int totalPage;
@Schema(
description = "현재 페이지 첫 번째 row 번호. 각 row 번호는 rowStartNum - memberList index로 계산합니다.",
example = "100"
)
private int rowStartNum;
public void setPaging(PagingRequest pagingRequest, int totalCount) {
this.page = pagingRequest.getPage();
this.size = pagingRequest.getSize();
this.totalCount = totalCount;
this.totalPage = PagingUtil.getTotalPage(totalCount, pagingRequest.getSize());
this.rowStartNum = PagingUtil.getRowStartNum(totalCount, pagingRequest.getPage(), pagingRequest.getSize());
}
}
@@ -0,0 +1,34 @@
package com.alist.api.core.common.response;
import lombok.Getter;
import org.springframework.http.ResponseEntity;
@Getter
public class ApiResponse<T> {
private T data; // 실제 데이터
private String code; // 결과 코드 (SUCCESS, ERROR_001 등)
private String message; // 사용자 메시지
public ApiResponse(T data, String code, String message) {
this.data = data;
this.code = code;
this.message = message;
}
public static ApiResponse<Void> body(ApiResponseCode code, Object... args) {
return new ApiResponse<>(null, code.code(), code.message(args));
}
public static <T> ApiResponse<T> body(T data, ApiResponseCode code, Object... args) {
return new ApiResponse<>(data, code.code(), code.message(args));
}
public static ResponseEntity<ApiResponse<Void>> entity(ApiResponseCode code, Object... args) {
return ResponseEntity.status(code.httpStatus()).body(ApiResponse.body(code, args));
}
public static <T> ResponseEntity<ApiResponse<T>> entity(T data, ApiResponseCode code, Object... args) {
return ResponseEntity.status(code.httpStatus()).body(ApiResponse.body(data, code, args));
}
}
@@ -0,0 +1,55 @@
package com.alist.api.core.common.response;
import org.springframework.http.HttpStatus;
import java.text.MessageFormat;
public enum ApiResponseCode {
// ===== Common =====
CODE_200 ("200", "성공", HttpStatus.OK),
CODE_204 ("204", "컨텐츠 없음", HttpStatus.NO_CONTENT),
CODE_400 ("400", "잘못된 요청", HttpStatus.BAD_REQUEST),
CODE_401 ("401", "인증 필요 합니다.", HttpStatus.UNAUTHORIZED),
CODE_403 ("403", "접근 권한 필요 합니다.", HttpStatus.FORBIDDEN),
CODE_404 ("404", "페이지를 찾을 수 없습니다. 입력하신 주소가 올바른지 확인해주세요.", HttpStatus.NOT_FOUND),
CODE_405 ("405", "잘못된 요청입니다. 요청 방식을 확인해 주세요.", HttpStatus.METHOD_NOT_ALLOWED),
CODE_500 ("500", "요청을 처리하는 중 오류가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
// ===== Success detail =====
CODE_2001("2001", "{0} 정보 조회에 성공하였습니다.", HttpStatus.OK),
CODE_2002("2002", "{0} 등록 되었습니다.", HttpStatus.CREATED),
CODE_2003("2003", "조회된 정보가 없습니다.", HttpStatus.OK),
CODE_2004("2004", "중복된 {0} 정보 입니다.", HttpStatus.CONFLICT),
CODE_2005("2005", "{0} 요청이 처리되었습니다.", HttpStatus.OK),
// ===== Client input errors =====
// @Valid / 바인딩 / 타입미스매치 / JSON 파싱 실패 등은 다 여기로
CODE_4001("4001", "입력값을 확인해주세요.", HttpStatus.BAD_REQUEST),
// 필수 요청 파라미터 누락
CODE_4003("4003", "필수 요청 파라미터가 누락되었습니다.", HttpStatus.BAD_REQUEST),
;
private final String code;
private final String message;
private final HttpStatus httpStatus;
ApiResponseCode(String code, String message, HttpStatus httpStatus) {
this.code = code;
this.message = message;
this.httpStatus = httpStatus;
}
public String code() { return code; }
public String message() { return message; }
public String message(Object... args) {
return MessageFormat.format(this.message, args);
}
public HttpStatus httpStatus() {
return httpStatus;
}
}
@@ -0,0 +1,16 @@
package com.alist.api.core.common.utils;
import java.security.SecureRandom;
import java.util.Base64;
public class ApiKeyGenerator {
private static final SecureRandom secureRandom = new SecureRandom();
private static final Base64.Encoder base64Encoder = Base64.getUrlEncoder().withoutPadding();
public static String userApiKeyProc() {
byte[] randomBytes = new byte[32]; // 256-bit
secureRandom.nextBytes(randomBytes);
return base64Encoder.encodeToString(randomBytes);
}
}
@@ -0,0 +1,26 @@
package com.alist.api.core.common.utils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashUtils {
public static String md5(String value) {
if (value == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] digest = messageDigest.digest(value.getBytes(StandardCharsets.UTF_8));
StringBuilder builder = new StringBuilder();
for (byte b : digest) {
builder.append(String.format("%02x", b));
}
return builder.toString();
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available", e);
}
}
}
@@ -0,0 +1,44 @@
package com.alist.api.core.common.utils;
public final class PagingUtil {
private static final int DEFAULT_PAGE = 1;
private static final int DEFAULT_SIZE = 10;
private static final int MAX_SIZE = 100;
private PagingUtil() {
}
public static int getPage(Integer page) {
return page == null || page < 1 ? DEFAULT_PAGE : page;
}
public static int getSize(Integer size) {
if (size == null || size < 1) {
return DEFAULT_SIZE;
}
return Math.min(size, MAX_SIZE);
}
public static int getLimit(Integer size) {
return getSize(size);
}
public static int getOffset(Integer page, Integer size) {
return (getPage(page) - 1) * getSize(size);
}
public static int getTotalPage(int totalCount, Integer size) {
return totalCount <= 0 ? 0 : (int) Math.ceil((double) totalCount / getSize(size));
}
public static int getRowStartNum(int totalCount, Integer page, Integer size) {
if (totalCount <= 0) {
return 0;
}
int offset = getOffset(page, size);
int rowStartNum = totalCount - offset;
return Math.max(rowStartNum, 0);
}
}
@@ -0,0 +1,19 @@
package com.alist.api.core.common.utils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
public class SecurityUtil {
public static Integer getLoginUserTokenIdx() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication.getPrincipal() == null) {
return null;
}
try {
return Integer.parseInt(authentication.getPrincipal().toString());
} catch (NumberFormatException e) {
return null;
}
}
}
@@ -0,0 +1,55 @@
package com.alist.api.core.common.utils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseCookie;
public class SessionUtil {
// 쿠키 삭제
public static void expireCookie(HttpServletResponse response, String name, String cookieDomain, boolean cookieSecure, String cookieSameSite) {
ResponseCookie.ResponseCookieBuilder builder = ResponseCookie.from(name, "")
.path("/")
.httpOnly(true)
.secure(cookieSecure)
.sameSite(cookieSameSite)
.maxAge(0);
if (cookieDomain != null && !cookieDomain.isBlank()) {
builder.domain(cookieDomain.trim());
}
response.addHeader("Set-Cookie", builder.build().toString());
}
// 쿠키 입력
public static void addTokenCookie(HttpServletResponse response, String name, String value, String cookieDomain, boolean cookieSecure, String cookieSameSite, long maxAgeSeconds) {
ResponseCookie.ResponseCookieBuilder builder = ResponseCookie.from(name, value)
.path("/")
.httpOnly(true)
.secure(cookieSecure)
.sameSite(cookieSameSite)
.maxAge(maxAgeSeconds);
if (cookieDomain != null && !cookieDomain.isBlank()) {
builder.domain(cookieDomain.trim());
}
response.addHeader("Set-Cookie", builder.build().toString());
}
// 쿠키에서 특정 이름 값 찾기
public static String resolveSsoCookieValue(HttpServletRequest request, String cookieName) {
if (request.getCookies() == null) {
return null;
}
for (Cookie cookie : request.getCookies()) {
if (cookieName.equals(cookie.getName())) {
return cookie.getValue();
}
}
return null;
}
}
@@ -0,0 +1,9 @@
package com.alist.api.core.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.alist.api.core")
public class ApiCoreConfig {
}
@@ -0,0 +1,89 @@
package com.alist.api.core.config.cors;
import com.alist.api.core.modules.standard.testCorsAllowedList.service.TestCorsAllowedListService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Slf4j
@Component
public class CorsCache {
public static final String REDIS_KEY = "alist:cors:allow-origins";
private final StringRedisTemplate stringRedisTemplate;
private final ObjectMapper objectMapper;
private final TestCorsAllowedListService testCorsAllowedListService;
private volatile List<String> allowedOriginList = List.of();
public CorsCache(StringRedisTemplate stringRedisTemplate, ObjectMapper objectMapper, TestCorsAllowedListService testCorsAllowedListService) {
this.stringRedisTemplate = stringRedisTemplate;
this.objectMapper = objectMapper;
this.testCorsAllowedListService = testCorsAllowedListService;
}
@PostConstruct
public void initialize() {
refreshFromRedis();
}
@Scheduled(fixedDelayString = "${cors.cache.redis-refresh-interval-ms:60000}")
public void refreshFromRedis() {
String allowedOriginJson = stringRedisTemplate.opsForValue().get(REDIS_KEY);
if (allowedOriginJson == null || allowedOriginJson.isBlank()) {
allowedOriginList = List.of();
return;
}
try {
List<String> redisAllowedOriginList = objectMapper.readValue(allowedOriginJson, new TypeReference<List<String>>() {
});
allowedOriginList = redisAllowedOriginList.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(allowedOrigin -> !allowedOrigin.isEmpty())
.distinct()
.toList();
} catch (JsonProcessingException e) {
log.error("CORS Redis cache JSON parsing failed.", e);
}
}
public void syncFromDatabase() {
List<String> databaseAllowedOriginList = testCorsAllowedListService.selectTestCorsAllowedListAllowedOriginList();
List<String> allowedOriginList = new ArrayList<>();
for (String allowedOrigin : databaseAllowedOriginList) {
if (allowedOrigin != null && !allowedOrigin.isBlank()) {
allowedOriginList.add(allowedOrigin.trim());
}
}
try {
String allowedOriginJson = objectMapper.writeValueAsString(allowedOriginList);
stringRedisTemplate.opsForValue().set(REDIS_KEY, allowedOriginJson);
this.allowedOriginList = List.copyOf(allowedOriginList);
} catch (JsonProcessingException e) {
throw new IllegalStateException("CORS Redis cache JSON creation failed.", e);
}
}
public boolean isAllowed(String origin) {
return allowedOriginList.contains("*") || allowedOriginList.contains(origin);
}
public List<String> getAllowedOriginList() {
return List.copyOf(allowedOriginList);
}
}
@@ -0,0 +1,19 @@
package com.alist.api.core.config.cors;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class CorsCachePublisher {
public static final String CHANNEL = "alist:cors:allow-origins:changed";
private final StringRedisTemplate stringRedisTemplate;
public CorsCachePublisher(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
public void publishReload() {
stringRedisTemplate.convertAndSend(CHANNEL, "reload");
}
}
@@ -0,0 +1,4 @@
package com.alist.api.core.config.cors;
public class CorsCacheRefreshEvent {
}
@@ -0,0 +1,22 @@
package com.alist.api.core.config.cors;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
@Component
public class CorsCacheRefreshEventListener {
private final CorsCache corsCache;
private final CorsCachePublisher corsCachePublisher;
public CorsCacheRefreshEventListener(CorsCache corsCache, CorsCachePublisher corsCachePublisher) {
this.corsCache = corsCache;
this.corsCachePublisher = corsCachePublisher;
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void refreshCorsCache(CorsCacheRefreshEvent corsCacheRefreshEvent) {
corsCache.syncFromDatabase();
corsCachePublisher.publishReload();
}
}
@@ -0,0 +1,19 @@
package com.alist.api.core.config.cors;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
@Component
public class CorsCacheSubscriber implements MessageListener {
private final CorsCache corsCache;
public CorsCacheSubscriber(CorsCache corsCache) {
this.corsCache = corsCache;
}
@Override
public void onMessage(Message message, byte[] pattern) {
corsCache.refreshFromRedis();
}
}
@@ -0,0 +1,21 @@
package com.alist.api.core.config.cors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class CorsRedisConfig {
@Bean
public RedisMessageListenerContainer corsRedisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory, CorsCacheSubscriber corsCacheSubscriber) {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
redisMessageListenerContainer.addMessageListener(corsCacheSubscriber, new ChannelTopic(CorsCachePublisher.CHANNEL));
return redisMessageListenerContainer;
}
}
@@ -0,0 +1,69 @@
package com.alist.api.core.config.datasource;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration
@ConditionalOnProperty(
prefix = "migration.datasource.alist"
, name = "enabled"
, havingValue = "true"
)
@MapperScan(
basePackages = "com.alist.api.core.modules.migration.alist",
sqlSessionFactoryRef = "migrationAlistSqlSessionFactory"
)
public class AlistDataSourceConfig {
@Bean(name = "migrationAlistDataSource")
@ConfigurationProperties(prefix = "migration.datasource.alist")
public HikariDataSource migrationAlistDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
}
@Bean(name = "migrationAlistSqlSessionFactory")
public SqlSessionFactory migrationAlistSqlSessionFactory(
@Qualifier("migrationAlistDataSource") DataSource migrationAlistDataSource
) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(migrationAlistDataSource);
factoryBean.setTypeAliasesPackage("com.alist.api.core.modules.migration.alist");
factoryBean.setConfiguration(mybatisConfiguration());
factoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath*:mapper/migration/alist/**/*.xml")
);
return factoryBean.getObject();
}
@Bean(name = "migrationAlistTransactionManager")
public DataSourceTransactionManager migrationAlistTransactionManager(
@Qualifier("migrationAlistDataSource") DataSource migrationAlistDataSource
) {
return new DataSourceTransactionManager(migrationAlistDataSource);
}
private org.apache.ibatis.session.Configuration mybatisConfiguration() {
org.apache.ibatis.session.Configuration configuration =
new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(Slf4jImpl.class);
return configuration;
}
}
@@ -0,0 +1,68 @@
package com.alist.api.core.config.datasource;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration
@ConditionalOnProperty(
prefix = "migration.datasource.eltown"
, name = "enabled"
, havingValue = "true"
)
@MapperScan(
basePackages = "com.alist.api.core.modules.migration.eltown",
sqlSessionFactoryRef = "migrationEltownSqlSessionFactory"
)
public class EltownDataSourceConfig {
@Bean(name = "migrationEltownDataSource")
@ConfigurationProperties(prefix = "migration.datasource.eltown")
public HikariDataSource migrationEltownDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
}
@Bean(name = "migrationEltownSqlSessionFactory")
public SqlSessionFactory migrationEltownSqlSessionFactory(
@Qualifier("migrationEltownDataSource") DataSource migrationEltownDataSource
) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(migrationEltownDataSource);
factoryBean.setTypeAliasesPackage("com.alist.api.core.modules.migration.eltown");
factoryBean.setConfiguration(mybatisConfiguration());
factoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath*:mapper/migration/eltown/**/*.xml")
);
return factoryBean.getObject();
}
@Bean(name = "migrationEltownTransactionManager")
public DataSourceTransactionManager migrationEltownTransactionManager(
@Qualifier("migrationEltownDataSource") DataSource migrationEltownDataSource
) {
return new DataSourceTransactionManager(migrationEltownDataSource);
}
private org.apache.ibatis.session.Configuration mybatisConfiguration() {
org.apache.ibatis.session.Configuration configuration =
new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(Slf4jImpl.class);
return configuration;
}
}
@@ -0,0 +1,100 @@
package com.alist.api.core.config.datasource;
import javax.sql.DataSource;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import java.util.Arrays;
import java.util.stream.Stream;
@Configuration
@MapperScan(
basePackages = {
"com.alist.api.core.modules.standard",
"com.alist.api.core.modules.bespoke"
},
annotationClass = Mapper.class,
sqlSessionFactoryRef = "mainSqlSessionFactory"
)
public class MainDataSourceConfig {
@Bean(name = "mainDataSourceProperties")
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties mainDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "mainDataSource")
@Primary
public DataSource mainDataSource(
@Qualifier("mainDataSourceProperties") DataSourceProperties mainDataSourceProperties
) {
return mainDataSourceProperties
.initializeDataSourceBuilder()
.build();
}
@Bean(name = "mainSqlSessionFactory")
@Primary
public SqlSessionFactory mainSqlSessionFactory(
@Qualifier("mainDataSource") DataSource mainDataSource
) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(mainDataSource);
factoryBean.setTypeAliasesPackage("com.alist.api.core");
factoryBean.setConfiguration(mybatisConfiguration());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] standardMappers = resolver.getResources("classpath*:mapper/standard/**/*.xml");
Resource[] bespokeMappers = resolver.getResources("classpath*:mapper/bespoke/**/*.xml");
Resource[] mapperLocations = Stream.of(
Arrays.stream(standardMappers)
, Arrays.stream(bespokeMappers)
).flatMap(stream -> stream).toArray(Resource[]::new);
factoryBean.setMapperLocations(mapperLocations);
return factoryBean.getObject();
}
@Bean(name = "mainSqlSessionTemplate")
@Primary
public SqlSessionTemplate mainSqlSessionTemplate(
@Qualifier("mainSqlSessionFactory") SqlSessionFactory mainSqlSessionFactory
) {
return new SqlSessionTemplate(mainSqlSessionFactory);
}
@Bean(name = "mainTransactionManager")
@Primary
public DataSourceTransactionManager mainTransactionManager(
@Qualifier("mainDataSource") DataSource mainDataSource
) {
return new DataSourceTransactionManager(mainDataSource);
}
private org.apache.ibatis.session.Configuration mybatisConfiguration() {
org.apache.ibatis.session.Configuration configuration =
new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(Slf4jImpl.class);
return configuration;
}
}
@@ -0,0 +1,9 @@
package com.alist.api.core.config.file;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(FileUploadProperties.class)
public class FileUploadConfig {
}
@@ -0,0 +1,38 @@
package com.alist.api.core.config.file;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.unit.DataSize;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@ConfigurationProperties(prefix = "file.upload")
public class FileUploadProperties {
private DataSize maxSize;
private List<String> allowedExtensions;
private Map<String, UploadType> types;
@Getter
@Setter
public static class UploadType {
private String folder;
private DataSize maxSize;
private boolean imageOnly;
private Resize resize = new Resize();
}
@Getter
@Setter
public static class Resize {
private boolean enabled;
private Integer width;
private Integer height;
private Integer maxWidth;
private Float quality = 0.9f;
}
}
@@ -0,0 +1,44 @@
package com.alist.api.core.config.filter;
import com.alist.api.core.config.cors.CorsCache;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DynamicCorsFilter extends OncePerRequestFilter {
private final CorsCache corsCache;
public DynamicCorsFilter(CorsCache corsCache) {
this.corsCache = corsCache;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String origin = request.getHeader("Origin");
if (origin != null && corsCache.isAllowed(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With, Accept, Origin, Referer, Content-Disposition, Content-Length");
response.setHeader("Access-Control-Expose-Headers", "Authorization, Set-Cookie");
response.setHeader("Access-Control-Max-Age", "3600");
}
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
filterChain.doFilter(request, response);
}
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.bespoke.fileDetail.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileDetailTusFileAuthDto {
private Integer userTokenIdx;
private String fileUuid;
private String originName;
private Long sizeBytes;
private String contentType;
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.bespoke.fileDetail.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileDetailTusFileListDto {
private Long fileMasterIdx;
private Integer userTokenIdx;
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.bespoke.fileDetail.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileDetailTusFileViewDto {
private String fileUuid;
private Integer userTokenIdx;
}
@@ -0,0 +1,27 @@
package com.alist.api.core.modules.bespoke.fileDetail.mapper;
import com.alist.api.core.modules.bespoke.fileDetail.dto.FileDetailTusFileAuthDto;
import com.alist.api.core.modules.bespoke.fileDetail.dto.FileDetailTusFileListDto;
import com.alist.api.core.modules.bespoke.fileDetail.dto.FileDetailTusFileViewDto;
import com.alist.api.core.modules.bespoke.fileDetail.vo.FileDetailTusFileListItemVo;
import com.alist.api.core.modules.bespoke.fileDetail.vo.FileDetailTusFileViewVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface FileDetailTusFileMapper {
int fileDetailTusFileUploadAuthCount(FileDetailTusFileAuthDto fileDetailTusFileAuthDto);
FileDetailTusFileViewVo fileDetailTusFileMetaView(FileDetailTusFileViewDto fileDetailTusFileViewDto);
FileDetailTusFileViewVo fileDetailTusFileMoveView(FileDetailTusFileViewDto fileDetailTusFileViewDto);
FileDetailTusFileViewVo fileDetailTusFileUploadCancelView(FileDetailTusFileViewDto fileDetailTusFileViewDto);
List<FileDetailTusFileListItemVo> fileDetailTusFileList(FileDetailTusFileListDto fileDetailTusFileListDto);
FileDetailTusFileViewVo fileDetailTusFileView(FileDetailTusFileViewDto fileDetailTusFileViewDto);
FileDetailTusFileViewVo fileDetailTusFileDeleteView(FileDetailTusFileViewDto fileDetailTusFileViewDto);
}
@@ -0,0 +1,56 @@
package com.alist.api.core.modules.bespoke.fileDetail.service;
import com.alist.api.core.modules.bespoke.fileDetail.dto.FileDetailTusFileAuthDto;
import com.alist.api.core.modules.bespoke.fileDetail.dto.FileDetailTusFileListDto;
import com.alist.api.core.modules.bespoke.fileDetail.dto.FileDetailTusFileViewDto;
import com.alist.api.core.modules.bespoke.fileDetail.mapper.FileDetailTusFileMapper;
import com.alist.api.core.modules.bespoke.fileDetail.vo.FileDetailTusFileListItemVo;
import com.alist.api.core.modules.bespoke.fileDetail.vo.FileDetailTusFileViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class FileDetailTusFileService {
private final FileDetailTusFileMapper fileDetailTusFileMapper;
public FileDetailTusFileService(FileDetailTusFileMapper fileDetailTusFileMapper) {
this.fileDetailTusFileMapper = fileDetailTusFileMapper;
}
@Transactional(readOnly = true)
public int fileDetailTusFileUploadAuthCount(FileDetailTusFileAuthDto fileDetailTusFileAuthDto) {
return fileDetailTusFileMapper.fileDetailTusFileUploadAuthCount(fileDetailTusFileAuthDto);
}
@Transactional(readOnly = true)
public FileDetailTusFileViewVo fileDetailTusFileMetaView(FileDetailTusFileViewDto fileDetailTusFileViewDto) {
return fileDetailTusFileMapper.fileDetailTusFileMetaView(fileDetailTusFileViewDto);
}
@Transactional(readOnly = true)
public FileDetailTusFileViewVo fileDetailTusFileMoveView(FileDetailTusFileViewDto fileDetailTusFileViewDto) {
return fileDetailTusFileMapper.fileDetailTusFileMoveView(fileDetailTusFileViewDto);
}
@Transactional(readOnly = true)
public FileDetailTusFileViewVo fileDetailTusFileUploadCancelView(FileDetailTusFileViewDto fileDetailTusFileViewDto) {
return fileDetailTusFileMapper.fileDetailTusFileUploadCancelView(fileDetailTusFileViewDto);
}
@Transactional(readOnly = true)
public List<FileDetailTusFileListItemVo> fileDetailTusFileList(FileDetailTusFileListDto fileDetailTusFileListDto) {
return fileDetailTusFileMapper.fileDetailTusFileList(fileDetailTusFileListDto);
}
@Transactional(readOnly = true)
public FileDetailTusFileViewVo fileDetailTusFileView(FileDetailTusFileViewDto fileDetailTusFileViewDto) {
return fileDetailTusFileMapper.fileDetailTusFileView(fileDetailTusFileViewDto);
}
@Transactional(readOnly = true)
public FileDetailTusFileViewVo fileDetailTusFileDeleteView(FileDetailTusFileViewDto fileDetailTusFileViewDto) {
return fileDetailTusFileMapper.fileDetailTusFileDeleteView(fileDetailTusFileViewDto);
}
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.bespoke.fileDetail.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileDetailTusFileListItemVo {
private Long fileDetailIdx;
private Long fileMasterIdx;
private String fileUuid;
private String originName;
private String contentType;
private Long sizeBytes;
}
@@ -0,0 +1,25 @@
package com.alist.api.core.modules.bespoke.fileDetail.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileDetailTusFileViewVo {
private Long fileDetailIdx;
private Long fileMasterIdx;
private String fileUuid;
private String originName;
private String contentType;
private Long sizeBytes;
private Long uploadedBytes;
private String tusUploadId;
private String folderPath;
private String saveName;
private String savePath;
private String ext;
private String moveYn;
private Integer moveTryCount;
private Integer status;
private Integer userIdx;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.fileMaster.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FileMasterTusFileModifyDto {
private String fileUuid;
}
@@ -0,0 +1,9 @@
package com.alist.api.core.modules.bespoke.fileMaster.mapper;
import com.alist.api.core.modules.bespoke.fileMaster.dto.FileMasterTusFileModifyDto;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface FileMasterTusFileMapper {
int fileMasterTusFileAggregateModify(FileMasterTusFileModifyDto fileMasterTusFileModifyDto);
}
@@ -0,0 +1,20 @@
package com.alist.api.core.modules.bespoke.fileMaster.service;
import com.alist.api.core.modules.bespoke.fileMaster.dto.FileMasterTusFileModifyDto;
import com.alist.api.core.modules.bespoke.fileMaster.mapper.FileMasterTusFileMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class FileMasterTusFileService {
private final FileMasterTusFileMapper fileMasterTusFileMapper;
public FileMasterTusFileService(FileMasterTusFileMapper fileMasterTusFileMapper) {
this.fileMasterTusFileMapper = fileMasterTusFileMapper;
}
@Transactional
public int fileMasterTusFileAggregateModify(FileMasterTusFileModifyDto fileMasterTusFileModifyDto) {
return fileMasterTusFileMapper.fileMasterTusFileAggregateModify(fileMasterTusFileModifyDto);
}
}
@@ -0,0 +1,16 @@
package com.alist.api.core.modules.bespoke.notice.dto;
import com.alist.api.core.common.paging.PagingRequest;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class NoticeNoticeListDto extends PagingRequest {
private String keyword;
private String noticeType;
private String targetScope;
private Long campusIdx;
private String pinYn;
private String useYn;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.notice.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class NoticeNoticeViewDto {
private Long noticeIdx;
}
@@ -0,0 +1,23 @@
package com.alist.api.core.modules.bespoke.notice.mapper;
import com.alist.api.core.modules.bespoke.notice.dto.NoticeNoticeListDto;
import com.alist.api.core.modules.bespoke.notice.dto.NoticeNoticeViewDto;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeCampusListItemVo;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeFileListItemVo;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeListItemVo;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeViewVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface NoticeNoticeMapper {
int noticeNoticeListCount(NoticeNoticeListDto noticeNoticeListDto);
List<NoticeNoticeListItemVo> noticeNoticeList(NoticeNoticeListDto noticeNoticeListDto);
NoticeNoticeViewVo noticeNoticeView(NoticeNoticeViewDto noticeNoticeViewDto);
List<NoticeNoticeCampusListItemVo> noticeNoticeCampusList(NoticeNoticeViewDto noticeNoticeViewDto);
List<NoticeNoticeFileListItemVo> noticeNoticeFileList(NoticeNoticeViewDto noticeNoticeViewDto);
}
@@ -0,0 +1,46 @@
package com.alist.api.core.modules.bespoke.notice.service;
import com.alist.api.core.modules.bespoke.notice.dto.NoticeNoticeListDto;
import com.alist.api.core.modules.bespoke.notice.dto.NoticeNoticeViewDto;
import com.alist.api.core.modules.bespoke.notice.mapper.NoticeNoticeMapper;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeCampusListItemVo;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeFileListItemVo;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeListItemVo;
import com.alist.api.core.modules.bespoke.notice.vo.NoticeNoticeViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class NoticeNoticeService {
private final NoticeNoticeMapper noticeNoticeMapper;
public NoticeNoticeService(NoticeNoticeMapper noticeNoticeMapper) {
this.noticeNoticeMapper = noticeNoticeMapper;
}
@Transactional(readOnly = true)
public int noticeNoticeListCount(NoticeNoticeListDto noticeNoticeListDto) {
return noticeNoticeMapper.noticeNoticeListCount(noticeNoticeListDto);
}
@Transactional(readOnly = true)
public List<NoticeNoticeListItemVo> noticeNoticeList(NoticeNoticeListDto noticeNoticeListDto) {
return noticeNoticeMapper.noticeNoticeList(noticeNoticeListDto);
}
@Transactional(readOnly = true)
public NoticeNoticeViewVo noticeNoticeView(NoticeNoticeViewDto noticeNoticeViewDto) {
return noticeNoticeMapper.noticeNoticeView(noticeNoticeViewDto);
}
@Transactional(readOnly = true)
public List<NoticeNoticeCampusListItemVo> noticeNoticeCampusList(NoticeNoticeViewDto noticeNoticeViewDto) {
return noticeNoticeMapper.noticeNoticeCampusList(noticeNoticeViewDto);
}
@Transactional(readOnly = true)
public List<NoticeNoticeFileListItemVo> noticeNoticeFileList(NoticeNoticeViewDto noticeNoticeViewDto) {
return noticeNoticeMapper.noticeNoticeFileList(noticeNoticeViewDto);
}
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.bespoke.notice.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class NoticeNoticeCampusListItemVo {
private Long noticeCampusIdx;
private Long campusIdx;
}
@@ -0,0 +1,19 @@
package com.alist.api.core.modules.bespoke.notice.vo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class NoticeNoticeFileListItemVo {
private Long noticeFileIdx;
private Long noticeIdx;
private String fileOriginalName;
private String fileSaveName;
private String filePath;
private Long fileSize;
private String fileExt;
private Integer sortOrder;
private LocalDateTime createDate;
}
@@ -0,0 +1,21 @@
package com.alist.api.core.modules.bespoke.notice.vo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class NoticeNoticeListItemVo {
private Long noticeIdx;
private String noticeType;
private String targetScope;
private String title;
private String pinYn;
private LocalDateTime startDate;
private LocalDateTime endDate;
private Integer viewCount;
private String useYn;
private LocalDateTime createDate;
private LocalDateTime updateDate;
}
@@ -0,0 +1,24 @@
package com.alist.api.core.modules.bespoke.notice.vo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class NoticeNoticeViewVo {
private Long noticeIdx;
private String noticeType;
private String targetScope;
private String title;
private String content;
private String pinYn;
private LocalDateTime startDate;
private LocalDateTime endDate;
private Integer viewCount;
private String useYn;
private LocalDateTime createDate;
private Long createMember;
private LocalDateTime updateDate;
private Long updateMember;
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.bespoke.testUser.dto;
import com.alist.api.core.common.paging.PagingRequest;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserAdminMemberListDto extends PagingRequest {
private String keyword;
private String userRole;
private String userType;
private String dormantYn;
private String withdrawStatus;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.testUser.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserAdminMemberViewDto {
private Integer userIdx;
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.bespoke.testUser.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserLoginViewDto {
private String id;
private String userType;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.testUser.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserSsoLoginViewDto {
private String id;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.testUser.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserUserPasswordViewDto {
private Integer userTokenIdx;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.testUser.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserUserProfileViewDto {
private Integer userTokenIdx;
}
@@ -0,0 +1,18 @@
package com.alist.api.core.modules.bespoke.testUser.mapper;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserAdminMemberListDto;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserAdminMemberViewDto;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserAdminMemberListItemVo;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserAdminMemberViewVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface TestUserAdminMemberMapper {
int testUserAdminMemberCount(TestUserAdminMemberListDto testUserAdminMemberListDto);
List<TestUserAdminMemberListItemVo> testUserAdminMemberList(TestUserAdminMemberListDto testUserAdminMemberListDto);
TestUserAdminMemberViewVo testUserAdminMemberView(TestUserAdminMemberViewDto testUserAdminMemberViewDto);
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.testUser.mapper;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserLoginViewDto;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserLoginViewVo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TestUserAuthMapper {
TestUserLoginViewVo testUserLoginView(TestUserLoginViewDto testUserLoginViewDto);
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.bespoke.testUser.mapper;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserSsoLoginViewDto;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserSsoLoginViewVo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TestUserSsoMapper {
TestUserSsoLoginViewVo testUserSsoLoginView(TestUserSsoLoginViewDto testUserSsoLoginViewDto);
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.bespoke.testUser.mapper;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserUserPasswordViewDto;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserUserProfileViewDto;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserUserPasswordViewVo;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserUserProfileViewVo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TestUserUserMapper {
TestUserUserPasswordViewVo testUserUserPasswordView(TestUserUserPasswordViewDto testUserUserPasswordViewDto);
TestUserUserProfileViewVo testUserUserProfileView(TestUserUserProfileViewDto testUserUserProfileViewDto);
}
@@ -0,0 +1,34 @@
package com.alist.api.core.modules.bespoke.testUser.service;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserAdminMemberListDto;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserAdminMemberViewDto;
import com.alist.api.core.modules.bespoke.testUser.mapper.TestUserAdminMemberMapper;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserAdminMemberListItemVo;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserAdminMemberViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class TestUserAdminMemberService {
private final TestUserAdminMemberMapper testUserBackOfficeMapper;
public TestUserAdminMemberService(TestUserAdminMemberMapper testUserBackOfficeMapper) {
this.testUserBackOfficeMapper = testUserBackOfficeMapper;
}
@Transactional(readOnly = true)
public int testUserAdminMemberCount(TestUserAdminMemberListDto testUserAdminMemberListDto) {
return testUserBackOfficeMapper.testUserAdminMemberCount(testUserAdminMemberListDto);
}
@Transactional(readOnly = true)
public List<TestUserAdminMemberListItemVo> testUserAdminMemberList(TestUserAdminMemberListDto testUserAdminMemberListDto) {
return testUserBackOfficeMapper.testUserAdminMemberList(testUserAdminMemberListDto);
}
@Transactional(readOnly = true)
public TestUserAdminMemberViewVo testUserAdminMemberView(TestUserAdminMemberViewDto testUserAdminMemberViewDto) {
return testUserBackOfficeMapper.testUserAdminMemberView(testUserAdminMemberViewDto);
}
}
@@ -0,0 +1,21 @@
package com.alist.api.core.modules.bespoke.testUser.service;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserLoginViewDto;
import com.alist.api.core.modules.bespoke.testUser.mapper.TestUserAuthMapper;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserLoginViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TestUserAuthService {
private final TestUserAuthMapper testUserAuthMapper;
public TestUserAuthService(TestUserAuthMapper testUserAuthMapper) {
this.testUserAuthMapper = testUserAuthMapper;
}
@Transactional(readOnly = true)
public TestUserLoginViewVo testUserLoginView(TestUserLoginViewDto testUserLoginViewDto) {
return testUserAuthMapper.testUserLoginView(testUserLoginViewDto);
}
}
@@ -0,0 +1,21 @@
package com.alist.api.core.modules.bespoke.testUser.service;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserSsoLoginViewDto;
import com.alist.api.core.modules.bespoke.testUser.mapper.TestUserSsoMapper;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserSsoLoginViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TestUserSsoService {
private final TestUserSsoMapper testUserSsoMapper;
public TestUserSsoService(TestUserSsoMapper testUserSsoMapper) {
this.testUserSsoMapper = testUserSsoMapper;
}
@Transactional(readOnly = true)
public TestUserSsoLoginViewVo testUserSsoLoginView(TestUserSsoLoginViewDto testUserSsoLoginViewDto) {
return testUserSsoMapper.testUserSsoLoginView(testUserSsoLoginViewDto);
}
}
@@ -0,0 +1,28 @@
package com.alist.api.core.modules.bespoke.testUser.service;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserUserPasswordViewDto;
import com.alist.api.core.modules.bespoke.testUser.dto.TestUserUserProfileViewDto;
import com.alist.api.core.modules.bespoke.testUser.mapper.TestUserUserMapper;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserUserPasswordViewVo;
import com.alist.api.core.modules.bespoke.testUser.vo.TestUserUserProfileViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TestUserUserService {
private final TestUserUserMapper testUserUserMapper;
public TestUserUserService(TestUserUserMapper testUserUserMapper) {
this.testUserUserMapper = testUserUserMapper;
}
@Transactional(readOnly = true)
public TestUserUserPasswordViewVo testUserUserPasswordView(TestUserUserPasswordViewDto testUserUserPasswordViewDto) {
return testUserUserMapper.testUserUserPasswordView(testUserUserPasswordViewDto);
}
@Transactional(readOnly = true)
public TestUserUserProfileViewVo testUserUserProfileView(TestUserUserProfileViewDto testUserUserProfileViewDto) {
return testUserUserMapper.testUserUserProfileView(testUserUserProfileViewDto);
}
}
@@ -0,0 +1,24 @@
package com.alist.api.core.modules.bespoke.testUser.vo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class TestUserAdminMemberListItemVo {
private Integer userIdx;
private Integer userTokenIdx;
private String id;
private String email;
private String hp;
private String userRole;
private String userType;
private String dormantYn;
private LocalDateTime dormantAt;
private String withdrawStatus;
private LocalDateTime withdrawAt;
private LocalDateTime createAt;
private LocalDateTime updateAt;
}
@@ -0,0 +1,4 @@
package com.alist.api.core.modules.bespoke.testUser.vo;
public class TestUserAdminMemberViewVo extends TestUserAdminMemberListItemVo {
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.bespoke.testUser.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserLoginViewVo {
private Integer userIdx;
private String id;
private String password;
private Integer userTokenIdx;
private String userRole;
private String userType;
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.bespoke.testUser.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserSsoLoginViewVo {
private Integer userIdx;
private Integer userTokenIdx;
private String id;
private String password;
private String userRole;
private String userType;
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.bespoke.testUser.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserUserPasswordViewVo {
private Integer userIdx;
private String password;
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.bespoke.testUser.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserUserProfileViewVo {
private Integer userIdx;
private String id;
private String email;
private String hp;
private String userRole;
private String userType;
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.bespoke.testUserToken.dto;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class TestUserTokenApiKeyLoginViewDto {
private String userApiKey;
private String userType;
private List<String> userTypes;
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.bespoke.testUserToken.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserTokenLoginCheckedViewDto {
private Integer userTokenIdx;
private String userType;
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.bespoke.testUserToken.dto;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class TestUserTokenRefreshViewDto {
private Integer userTokenIdx;
private String userType;
private List<String> userTypes;
}
@@ -0,0 +1,18 @@
package com.alist.api.core.modules.bespoke.testUserToken.mapper;
import com.alist.api.core.modules.bespoke.testUserToken.dto.TestUserTokenApiKeyLoginViewDto;
import com.alist.api.core.modules.bespoke.testUserToken.dto.TestUserTokenLoginCheckedViewDto;
import com.alist.api.core.modules.bespoke.testUserToken.dto.TestUserTokenRefreshViewDto;
import com.alist.api.core.modules.bespoke.testUserToken.vo.TestUserTokenApiKeyLoginViewVo;
import com.alist.api.core.modules.bespoke.testUserToken.vo.TestUserTokenLoginCheckedViewVo;
import com.alist.api.core.modules.bespoke.testUserToken.vo.TestUserTokenRefreshViewVo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TestUserTokenAuthMapper {
TestUserTokenApiKeyLoginViewVo testUserTokenApiKeyLoginView(TestUserTokenApiKeyLoginViewDto testUserTokenApiKeyLoginViewDto);
TestUserTokenLoginCheckedViewVo testUserTokenLoginCheckedView(TestUserTokenLoginCheckedViewDto testUserTokenLoginCheckedViewDto);
TestUserTokenRefreshViewVo testUserTokenRefreshView(TestUserTokenRefreshViewDto testUserTokenRefreshViewDto);
}
@@ -0,0 +1,35 @@
package com.alist.api.core.modules.bespoke.testUserToken.service;
import com.alist.api.core.modules.bespoke.testUserToken.dto.TestUserTokenApiKeyLoginViewDto;
import com.alist.api.core.modules.bespoke.testUserToken.dto.TestUserTokenLoginCheckedViewDto;
import com.alist.api.core.modules.bespoke.testUserToken.dto.TestUserTokenRefreshViewDto;
import com.alist.api.core.modules.bespoke.testUserToken.mapper.TestUserTokenAuthMapper;
import com.alist.api.core.modules.bespoke.testUserToken.vo.TestUserTokenApiKeyLoginViewVo;
import com.alist.api.core.modules.bespoke.testUserToken.vo.TestUserTokenLoginCheckedViewVo;
import com.alist.api.core.modules.bespoke.testUserToken.vo.TestUserTokenRefreshViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TestUserTokenAuthService {
private final TestUserTokenAuthMapper testUserTokenAuthMapper;
public TestUserTokenAuthService(TestUserTokenAuthMapper testUserTokenAuthMapper) {
this.testUserTokenAuthMapper = testUserTokenAuthMapper;
}
@Transactional(readOnly = true)
public TestUserTokenApiKeyLoginViewVo testUserTokenApiKeyLoginView(TestUserTokenApiKeyLoginViewDto testUserTokenApiKeyLoginViewDto) {
return testUserTokenAuthMapper.testUserTokenApiKeyLoginView(testUserTokenApiKeyLoginViewDto);
}
@Transactional(readOnly = true)
public TestUserTokenLoginCheckedViewVo testUserTokenLoginCheckedView(TestUserTokenLoginCheckedViewDto testUserTokenLoginCheckedViewDto) {
return testUserTokenAuthMapper.testUserTokenLoginCheckedView(testUserTokenLoginCheckedViewDto);
}
@Transactional(readOnly = true)
public TestUserTokenRefreshViewVo testUserTokenRefreshView(TestUserTokenRefreshViewDto testUserTokenRefreshViewDto) {
return testUserTokenAuthMapper.testUserTokenRefreshView(testUserTokenRefreshViewDto);
}
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.bespoke.testUserToken.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserTokenApiKeyLoginViewVo {
private Integer userIdx;
private String id;
private Integer userTokenIdx;
private String userRole;
private String userType;
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.bespoke.testUserToken.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserTokenLoginCheckedViewVo {
private Integer userIdx;
private String id;
private Integer userTokenIdx;
private String userRole;
private String userType;
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.bespoke.testUserToken.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestUserTokenRefreshViewVo {
private Integer userIdx;
private String id;
private Integer userTokenIdx;
private String refreshToken;
private String userRole;
private String userType;
}
@@ -0,0 +1,11 @@
package com.alist.api.core.modules.migration.alist.user.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlistUserMigrationDto {
private String id;
private String password;
}
@@ -0,0 +1,12 @@
package com.alist.api.core.modules.migration.alist.user.mapper;
import com.alist.api.core.modules.migration.alist.user.dto.AlistUserMigrationDto;
import com.alist.api.core.modules.migration.alist.user.vo.AlistUserMigrationVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface AlistUserMigrationMapper {
List<AlistUserMigrationVo> selectAlistUserMigrationList(AlistUserMigrationDto alistUserMigrationDto);
}
@@ -0,0 +1,27 @@
package com.alist.api.core.modules.migration.alist.user.service;
import com.alist.api.core.modules.migration.alist.user.dto.AlistUserMigrationDto;
import com.alist.api.core.modules.migration.alist.user.mapper.AlistUserMigrationMapper;
import com.alist.api.core.modules.migration.alist.user.vo.AlistUserMigrationVo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@ConditionalOnProperty(
prefix = "migration.datasource.alist",
name = "enabled",
havingValue = "true"
)
public class AlistUserMigrationService {
private final AlistUserMigrationMapper alistUserMigrationMapper;
public AlistUserMigrationService(AlistUserMigrationMapper alistUserMigrationMapper) {
this.alistUserMigrationMapper = alistUserMigrationMapper;
}
public List<AlistUserMigrationVo> selectAlistUserMigrationList(AlistUserMigrationDto alistUserMigrationDto) {
return alistUserMigrationMapper.selectAlistUserMigrationList(alistUserMigrationDto);
}
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.migration.alist.user.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlistUserMigrationVo {
private String id;
private String name;
private String hp;
private String email;
private String type;
private String joinDate;
}
@@ -0,0 +1,12 @@
package com.alist.api.core.modules.migration.eltown.user.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EltownUserMigrationDto {
private String id;
private String password;
private String md5Password;
}
@@ -0,0 +1,12 @@
package com.alist.api.core.modules.migration.eltown.user.mapper;
import com.alist.api.core.modules.migration.eltown.user.dto.EltownUserMigrationDto;
import com.alist.api.core.modules.migration.eltown.user.vo.EltownUserMigrationVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface EltownUserMigrationMapper {
List<EltownUserMigrationVo> selectEltownUserMigrationList(EltownUserMigrationDto eltownUserMigrationDto);
}
@@ -0,0 +1,30 @@
package com.alist.api.core.modules.migration.eltown.user.service;
import com.alist.api.core.common.utils.HashUtils;
import com.alist.api.core.modules.migration.eltown.user.dto.EltownUserMigrationDto;
import com.alist.api.core.modules.migration.eltown.user.mapper.EltownUserMigrationMapper;
import com.alist.api.core.modules.migration.eltown.user.vo.EltownUserMigrationVo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@ConditionalOnProperty(
prefix = "migration.datasource.eltown",
name = "enabled",
havingValue = "true"
)
public class EltownUserMigrationService {
private final EltownUserMigrationMapper eltownUserMigrationMapper;
public EltownUserMigrationService(EltownUserMigrationMapper eltownUserMigrationMapper) {
this.eltownUserMigrationMapper = eltownUserMigrationMapper;
}
public List<EltownUserMigrationVo> selectEltownUserMigrationList(EltownUserMigrationDto eltownUserMigrationDto) {
eltownUserMigrationDto.setMd5Password(HashUtils.md5(eltownUserMigrationDto.getPassword()));
return eltownUserMigrationMapper.selectEltownUserMigrationList(eltownUserMigrationDto);
}
}
@@ -0,0 +1,15 @@
package com.alist.api.core.modules.migration.eltown.user.vo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EltownUserMigrationVo {
private String id;
private String name;
private String hp;
private String email;
private String type;
private String joinDate;
}
@@ -0,0 +1,20 @@
package com.alist.api.core.modules.standard.alCalendar.dto;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
@Getter
@Setter
public class AlCalendarAddDto {
private String yyyymmdd;
private String yyyy;
private String mm;
private String dd;
private Short weekNo;
private String weekNm;
private String holidayYn;
private String holidayNm;
private LocalDate formatDate;
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.standard.alCalendar.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlCalendarDeleteDto {
private String yyyymmdd;
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.standard.alCalendar.dto;
import com.alist.api.core.common.paging.PagingRequest;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlCalendarListDto extends PagingRequest {
private String yyyymmdd;
private String yyyy;
private String mm;
private String holidayYn;
}
@@ -0,0 +1,31 @@
package com.alist.api.core.modules.standard.alCalendar.dto;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
@Getter
@Setter
public class AlCalendarModifyDto {
private String yyyymmdd;
private String yyyy;
private String mm;
private String dd;
private Short weekNo;
private String weekNm;
private String holidayYn;
private String holidayNm;
private LocalDate formatDate;
public boolean hasModifyValue() {
return yyyy != null
|| mm != null
|| dd != null
|| weekNo != null
|| weekNm != null
|| holidayYn != null
|| holidayNm != null
|| formatDate != null;
}
}
@@ -0,0 +1,10 @@
package com.alist.api.core.modules.standard.alCalendar.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlCalendarViewDto {
private String yyyymmdd;
}
@@ -0,0 +1,27 @@
package com.alist.api.core.modules.standard.alCalendar.mapper;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarAddDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarDeleteDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarListDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarModifyDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarViewDto;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarListItemVo;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarViewVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface AlCalendarMapper {
int selectAlCalendarListCount(AlCalendarListDto alCalendarListDto);
List<AlCalendarListItemVo> selectAlCalendarList(AlCalendarListDto alCalendarListDto);
AlCalendarViewVo selectAlCalendarView(AlCalendarViewDto alCalendarViewDto);
int insertAlCalendarAdd(AlCalendarAddDto alCalendarAddDto);
int updateAlCalendarModify(AlCalendarModifyDto alCalendarModifyDto);
int deleteAlCalendarDelete(AlCalendarDeleteDto alCalendarDeleteDto);
}
@@ -0,0 +1,82 @@
package com.alist.api.core.modules.standard.alCalendar.service;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarAddDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarDeleteDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarListDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarModifyDto;
import com.alist.api.core.modules.standard.alCalendar.dto.AlCalendarViewDto;
import com.alist.api.core.modules.standard.alCalendar.mapper.AlCalendarMapper;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarAddVo;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarDeleteVo;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarListVo;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarModifyVo;
import com.alist.api.core.modules.standard.alCalendar.vo.AlCalendarViewVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AlCalendarService {
private final AlCalendarMapper alCalendarMapper;
public AlCalendarService(AlCalendarMapper alCalendarMapper) {
this.alCalendarMapper = alCalendarMapper;
}
@Transactional(readOnly = true)
public AlCalendarListVo selectAlCalendarList(AlCalendarListDto alCalendarListDto) {
int totalCount = alCalendarMapper.selectAlCalendarListCount(alCalendarListDto);
AlCalendarListVo alCalendarListVo = new AlCalendarListVo();
alCalendarListVo.setAlCalendarList(alCalendarMapper.selectAlCalendarList(alCalendarListDto));
alCalendarListVo.setPaging(alCalendarListDto, totalCount);
return alCalendarListVo;
}
@Transactional(readOnly = true)
public AlCalendarViewVo selectAlCalendarView(AlCalendarViewDto alCalendarViewDto) {
return alCalendarMapper.selectAlCalendarView(alCalendarViewDto);
}
@Transactional
public AlCalendarAddVo insertAlCalendarAdd(AlCalendarAddDto alCalendarAddDto) {
int insertCount = alCalendarMapper.insertAlCalendarAdd(alCalendarAddDto);
AlCalendarAddVo alCalendarAddVo = new AlCalendarAddVo();
alCalendarAddVo.setAdded(insertCount > 0);
alCalendarAddVo.setYyyymmdd(alCalendarAddDto.getYyyymmdd());
alCalendarAddVo.setResultCode(insertCount > 0 ? 2002 : 500);
return alCalendarAddVo;
}
@Transactional
public AlCalendarModifyVo updateAlCalendarModify(AlCalendarModifyDto alCalendarModifyDto) {
AlCalendarModifyVo alCalendarModifyVo = new AlCalendarModifyVo();
alCalendarModifyVo.setYyyymmdd(alCalendarModifyDto.getYyyymmdd());
if (!alCalendarModifyDto.hasModifyValue()) {
alCalendarModifyVo.setUpdated(false);
alCalendarModifyVo.setResultCode(4001);
return alCalendarModifyVo;
}
int updateCount = alCalendarMapper.updateAlCalendarModify(alCalendarModifyDto);
alCalendarModifyVo.setUpdated(updateCount > 0);
alCalendarModifyVo.setResultCode(updateCount > 0 ? 2005 : 2003);
return alCalendarModifyVo;
}
@Transactional
public AlCalendarDeleteVo deleteAlCalendarDelete(AlCalendarDeleteDto alCalendarDeleteDto) {
int deleteCount = alCalendarMapper.deleteAlCalendarDelete(alCalendarDeleteDto);
AlCalendarDeleteVo alCalendarDeleteVo = new AlCalendarDeleteVo();
alCalendarDeleteVo.setDeleted(deleteCount > 0);
alCalendarDeleteVo.setYyyymmdd(alCalendarDeleteDto.getYyyymmdd());
alCalendarDeleteVo.setResultCode(deleteCount > 0 ? 2005 : 2003);
return alCalendarDeleteVo;
}
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.standard.alCalendar.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlCalendarAddVo {
private boolean added;
private String yyyymmdd;
@JsonIgnore
private Integer resultCode;
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.standard.alCalendar.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlCalendarDeleteVo {
private boolean deleted;
private String yyyymmdd;
@JsonIgnore
private Integer resultCode;
}
@@ -0,0 +1,20 @@
package com.alist.api.core.modules.standard.alCalendar.vo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
@Getter
@Setter
public class AlCalendarListItemVo {
private String yyyymmdd;
private String yyyy;
private String mm;
private String dd;
private Short weekNo;
private String weekNm;
private String holidayYn;
private String holidayNm;
private LocalDate formatDate;
}
@@ -0,0 +1,13 @@
package com.alist.api.core.modules.standard.alCalendar.vo;
import com.alist.api.core.common.paging.PagingResponse;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class AlCalendarListVo extends PagingResponse {
private List<AlCalendarListItemVo> alCalendarList;
}
@@ -0,0 +1,14 @@
package com.alist.api.core.modules.standard.alCalendar.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AlCalendarModifyVo {
private boolean updated;
private String yyyymmdd;
@JsonIgnore
private Integer resultCode;
}
@@ -0,0 +1,20 @@
package com.alist.api.core.modules.standard.alCalendar.vo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
@Getter
@Setter
public class AlCalendarViewVo {
private String yyyymmdd;
private String yyyy;
private String mm;
private String dd;
private Short weekNo;
private String weekNm;
private String holidayYn;
private String holidayNm;
private LocalDate formatDate;
}

Some files were not shown because too many files have changed in this diff Show More