├── .github
└── workflows
│ ├── build.yml
│ ├── deploy-docker.yml
│ └── deploy-mono.yml
├── .gitignore
├── README-ENG.md
├── README.md
├── build.gradle.kts
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── infra
├── README.md
├── infra
│ ├── .env
│ ├── docker-compose.yml
│ ├── mysql
│ │ └── conf
│ │ │ └── docker-mysql.cnf
│ └── nginx
│ │ └── sites-available
│ │ └── default
└── script
│ ├── deploy.sh
│ ├── shutdown.sh
│ └── startup.sh
├── settings.gradle.kts
└── src
├── course
├── rest
│ ├── Meeting.http
│ ├── asset
│ │ ├── large-size.jpg
│ │ └── test.jpg
│ ├── club
│ │ ├── Club.http
│ │ ├── ClubInfo.http
│ │ ├── album
│ │ │ ├── ClubAlbum.http
│ │ │ ├── ClubAlbumComment.http
│ │ │ └── ClubAlbumLike.http
│ │ ├── board
│ │ │ ├── ClubBoard.http
│ │ │ ├── ClubBoardComment.http
│ │ │ └── ClubBoardLike.http
│ │ └── role
│ │ │ └── Role.http
│ ├── common
│ │ └── temp-upload.http
│ ├── http-client.env.json
│ ├── region
│ │ └── region.http
│ └── user
│ │ └── user.http
└── sql
│ └── ddl.sql
├── docs
└── asciidoc
│ ├── club
│ ├── addClub.adoc
│ ├── addClubUser.adoc
│ ├── album
│ │ ├── club-album-comment-edit.adoc
│ │ ├── club-album-comment-register.adoc
│ │ ├── club-album-comment-remove.adoc
│ │ ├── club-album-comment-select-sub.adoc
│ │ ├── club-album-comment-select.adoc
│ │ ├── club-album-edit.adoc
│ │ ├── club-album-like-register.adoc
│ │ ├── club-album-like-remove.adoc
│ │ ├── club-album-register.adoc
│ │ ├── club-album-remove.adoc
│ │ ├── club-album-select-single.adoc
│ │ └── club-album-select.adoc
│ ├── board
│ │ ├── club-board-comment-edit.adoc
│ │ ├── club-board-comment-register.adoc
│ │ ├── club-board-comment-remove.adoc
│ │ ├── club-board-comment-select-sub.adoc
│ │ ├── club-board-comment-select.adoc
│ │ ├── club-board-delete.adoc
│ │ ├── club-board-edit.adoc
│ │ ├── club-board-like-register.adoc
│ │ ├── club-board-like-remove.adoc
│ │ ├── club-board-register.adoc
│ │ ├── club-board-select-list.adoc
│ │ └── club-board-select.adoc
│ ├── changeClubInterests.adoc
│ ├── changeClubRegions.adoc
│ ├── changeClubUserRole.adoc
│ ├── delete.adoc
│ ├── getMyClubUserInfo.adoc
│ ├── kick.adoc
│ ├── meeting
│ │ ├── create-meeting.adoc
│ │ ├── delete-meeting.adoc
│ │ ├── get-meeting-application-status.adoc
│ │ ├── get-meeting-application.adoc
│ │ ├── meeting-all.adoc
│ │ ├── meeting-application-cancel.adoc
│ │ ├── meeting-application.adoc
│ │ ├── meeting-one.adoc
│ │ └── modify-meeting.adoc
│ ├── modify.adoc
│ ├── myClubList.adoc
│ ├── searchClub.adoc
│ ├── selectClubInfoDetails.adoc
│ └── withdraw.adoc
│ ├── common
│ ├── error.adoc
│ ├── temp-file-upload.adoc
│ └── temp-image-upload.adoc
│ ├── docinfo-footer.html
│ ├── docinfo.html
│ ├── index.adoc
│ ├── interest
│ ├── changeUserInterest.adoc
│ ├── interest-group-all.adoc
│ └── userInterest.adoc
│ ├── region
│ ├── region-all.adoc
│ └── userRegions.adoc
│ └── user
│ ├── changeUserRegions.adoc
│ ├── kakaoUserProfileInfo.adoc
│ ├── saveKakaoToken.adoc
│ ├── user-change.adoc
│ ├── user-check-register.adoc
│ ├── userInfo.adoc
│ ├── userRegist.adoc
│ └── userWithdraw.adoc
├── main
├── kotlin
│ └── com
│ │ └── taskforce
│ │ └── superinvention
│ │ ├── SuperinventionApplication.kt
│ │ ├── app
│ │ ├── domain
│ │ │ ├── BaseEntity.kt
│ │ │ ├── club
│ │ │ │ ├── Club.kt
│ │ │ │ ├── ClubRepository.kt
│ │ │ │ ├── ClubService.kt
│ │ │ │ ├── album
│ │ │ │ │ ├── ClubAlbum.kt
│ │ │ │ │ ├── ClubAlbumRepository.kt
│ │ │ │ │ ├── ClubAlbumService.kt
│ │ │ │ │ ├── comment
│ │ │ │ │ │ ├── ClubAlbumComment.kt
│ │ │ │ │ │ ├── ClubAlbumCommentCTE.kt
│ │ │ │ │ │ ├── ClubAlbumCommentRepository.kt
│ │ │ │ │ │ └── ClubAlbumCommentService.kt
│ │ │ │ │ ├── image
│ │ │ │ │ │ └── ClubAlbumImageService.kt
│ │ │ │ │ └── like
│ │ │ │ │ │ ├── ClubAlbumLike.kt
│ │ │ │ │ │ ├── ClubAlbumLikeRepository.kt
│ │ │ │ │ │ └── ClubAlbumLikeService.kt
│ │ │ │ ├── board
│ │ │ │ │ ├── ClubBoard.kt
│ │ │ │ │ ├── ClubBoardRepository.kt
│ │ │ │ │ ├── ClubBoardService.kt
│ │ │ │ │ ├── comment
│ │ │ │ │ │ ├── ClubBoardComment.kt
│ │ │ │ │ │ ├── ClubBoardCommentCTE.kt
│ │ │ │ │ │ ├── ClubBoardCommentRepository.kt
│ │ │ │ │ │ └── ClubBoardCommentService.kt
│ │ │ │ │ ├── img
│ │ │ │ │ │ ├── ClubBoardImg.kt
│ │ │ │ │ │ ├── ClubBoardImgRepository.kt
│ │ │ │ │ │ └── ClubBoardImgService.kt
│ │ │ │ │ └── like
│ │ │ │ │ │ ├── ClubBoardLike.kt
│ │ │ │ │ │ ├── ClubBoardLikeRepository.kt
│ │ │ │ │ │ └── ClubBoardLikeService.kt
│ │ │ │ └── user
│ │ │ │ │ ├── ClubUser.kt
│ │ │ │ │ ├── ClubUserRepository.kt
│ │ │ │ │ └── ClubUserService.kt
│ │ │ ├── common
│ │ │ │ ├── FileService.kt
│ │ │ │ └── image
│ │ │ │ │ ├── ImageFormat.kt
│ │ │ │ │ ├── ImageService.kt
│ │ │ │ │ ├── resize
│ │ │ │ │ ├── ImageResizeService.kt
│ │ │ │ │ └── strategy
│ │ │ │ │ │ ├── GifResizeStrategy.kt
│ │ │ │ │ │ ├── ImageResizeStrategy.kt
│ │ │ │ │ │ ├── ImageResizeStrategyLocator.kt
│ │ │ │ │ │ ├── JpgResizeStrategy.kt
│ │ │ │ │ │ ├── PngResizeStrategy.kt
│ │ │ │ │ │ └── WebpResizeStrategy.kt
│ │ │ │ │ └── webp
│ │ │ │ │ └── convert
│ │ │ │ │ ├── WebpCompressionParam.kt
│ │ │ │ │ ├── WebpConvertService.kt
│ │ │ │ │ ├── handler
│ │ │ │ │ ├── Gif2WebpHandler.kt
│ │ │ │ │ ├── WebpAnimatedWriter.kt
│ │ │ │ │ └── WebpHandler.kt
│ │ │ │ │ └── strategy
│ │ │ │ │ ├── Gif2WebpStrategy.kt
│ │ │ │ │ ├── Jpg2WebpStrategy.kt
│ │ │ │ │ ├── Png2WebpStrategy.kt
│ │ │ │ │ ├── WebpConvertStrategy.kt
│ │ │ │ │ └── WebpConvertStrategyLocator.kt
│ │ │ ├── interest
│ │ │ │ ├── ClubInterest.kt
│ │ │ │ ├── ClubInterestRepository.kt
│ │ │ │ ├── interest
│ │ │ │ │ ├── Interest.kt
│ │ │ │ │ ├── InterestDto.kt
│ │ │ │ │ ├── InterestRepository.kt
│ │ │ │ │ ├── InterestRepositoryImpl.kt
│ │ │ │ │ └── InterestService.kt
│ │ │ │ └── interestGroup
│ │ │ │ │ ├── InterestGroup.kt
│ │ │ │ │ ├── InterestGroupDto.kt
│ │ │ │ │ ├── InterestGroupRepository.kt
│ │ │ │ │ ├── InterestGroupRepositoryImpl.kt
│ │ │ │ │ └── InterestGroupService.kt
│ │ │ ├── meeting
│ │ │ │ ├── Meeting.kt
│ │ │ │ ├── MeetingApplication.kt
│ │ │ │ ├── MeetingApplicationRepository.kt
│ │ │ │ ├── MeetingRepository.kt
│ │ │ │ └── MeetingService.kt
│ │ │ ├── region
│ │ │ │ ├── ClubRegion.kt
│ │ │ │ ├── ClubRegionRepository.kt
│ │ │ │ ├── Region.kt
│ │ │ │ ├── RegionRepository.kt
│ │ │ │ └── RegionService.kt
│ │ │ ├── role
│ │ │ │ ├── ClubUserRole.kt
│ │ │ │ ├── ClubUserRoleRepository.kt
│ │ │ │ ├── Role.kt
│ │ │ │ ├── RoleGroup.kt
│ │ │ │ ├── RoleGroupRepository.kt
│ │ │ │ ├── RoleGroupRepositorySupport.kt
│ │ │ │ ├── RoleRepository.kt
│ │ │ │ ├── RoleRepositorySupport.kt
│ │ │ │ └── RoleService.kt
│ │ │ └── user
│ │ │ │ ├── User.kt
│ │ │ │ ├── UserDetailsProvider.kt
│ │ │ │ ├── UserInfoService.kt
│ │ │ │ ├── UserRepository.kt
│ │ │ │ ├── UserService.kt
│ │ │ │ ├── UserType.kt
│ │ │ │ ├── userInterest
│ │ │ │ ├── UserInterest.kt
│ │ │ │ ├── UserInterestRepository.kt
│ │ │ │ └── UserInterestService.kt
│ │ │ │ ├── userRegion
│ │ │ │ ├── UserRegion.kt
│ │ │ │ ├── UserRegionRepository.kt
│ │ │ │ └── UserRegionService.kt
│ │ │ │ └── userRole
│ │ │ │ ├── UserRole.kt
│ │ │ │ ├── UserRoleRepository.kt
│ │ │ │ └── UserRoleService.kt
│ │ └── web
│ │ │ ├── common
│ │ │ └── response
│ │ │ │ ├── ErrorResponseDto.kt
│ │ │ │ └── ResponseDto.kt
│ │ │ ├── controller
│ │ │ ├── CommonController.kt
│ │ │ ├── InterestGroupController.kt
│ │ │ ├── club
│ │ │ │ ├── ClubController.kt
│ │ │ │ ├── album
│ │ │ │ │ ├── ClubAlbumCommentController.kt
│ │ │ │ │ ├── ClubAlbumController.kt
│ │ │ │ │ └── ClubAlbumLikeController.kt
│ │ │ │ └── board
│ │ │ │ │ ├── ClubBoardCommentController.kt
│ │ │ │ │ ├── ClubBoardController.kt
│ │ │ │ │ └── ClubBoardLikeController.kt
│ │ │ ├── meeting
│ │ │ │ ├── MeetingApplicationController.kt
│ │ │ │ └── MeetingController.kt
│ │ │ ├── region
│ │ │ │ └── RegionController.kt
│ │ │ └── user
│ │ │ │ ├── UserController.kt
│ │ │ │ ├── UserInterestController.kt
│ │ │ │ └── UserRegionController.kt
│ │ │ └── dto
│ │ │ ├── club
│ │ │ ├── ClubAddRequestDto.kt
│ │ │ ├── ClubDto.kt
│ │ │ ├── ClubSearchRequestDto.kt
│ │ │ ├── ClubUsersDto.kt
│ │ │ ├── album
│ │ │ │ ├── ClubAlbumDto.kt
│ │ │ │ ├── comment
│ │ │ │ │ └── ClubAlbumCommentDto.kt
│ │ │ │ └── like
│ │ │ │ │ └── ClubAlbumLikeDto.kt
│ │ │ └── board
│ │ │ │ ├── ClubBoardDto.kt
│ │ │ │ ├── comment
│ │ │ │ └── ClubBoardCommentListDto.kt
│ │ │ │ ├── img
│ │ │ │ └── ClubBoardImgDto.kt
│ │ │ │ └── like
│ │ │ │ └── ClubBoardLikeDto.kt
│ │ │ ├── common
│ │ │ ├── PageDto.kt
│ │ │ └── image
│ │ │ │ └── ResizeDto.kt
│ │ │ ├── interest
│ │ │ ├── InterestRequestDto.kt
│ │ │ ├── InterestWithPriorityDto.kt
│ │ │ └── UserInterestDto.kt
│ │ │ ├── kakao
│ │ │ └── kakaoDto.kt
│ │ │ ├── meeting
│ │ │ ├── MeetingApplicationDto.kt
│ │ │ └── MeetingDto.kt
│ │ │ ├── region
│ │ │ ├── RegionDto.kt
│ │ │ ├── RegionRequestDto.kt
│ │ │ ├── RegionWithPriorityDto.kt
│ │ │ └── SimpleRegionDto.kt
│ │ │ ├── role
│ │ │ └── RoleDto.kt
│ │ │ └── user
│ │ │ ├── UserDto.kt
│ │ │ ├── UserProfileUpdateDto.kt
│ │ │ ├── UserRegionDto.kt
│ │ │ └── info
│ │ │ ├── UserInfoDto.kt
│ │ │ ├── UserInfoInterestDto.kt
│ │ │ └── UserInfoRegionDto.kt
│ │ └── common
│ │ ├── advice
│ │ ├── AdviceDto.kt
│ │ ├── GlobalAdviceController.kt
│ │ └── GlobalSecurityExceptionHandler.kt
│ │ ├── config
│ │ ├── WebMvcConfig.kt
│ │ ├── argument
│ │ │ ├── converter
│ │ │ │ └── ClubBoardCategoryConverter.kt
│ │ │ └── resolver
│ │ │ │ └── auth
│ │ │ │ └── AuthorizeArgumentResolver.kt
│ │ ├── async
│ │ │ └── AsyncConfig.kt
│ │ ├── jpa
│ │ │ ├── CriteriaConfig.kt
│ │ │ ├── JpaConfig.kt
│ │ │ ├── QueryDslConfig.kt
│ │ │ └── dialect
│ │ │ │ └── CustomMysqlDialect.kt
│ │ ├── security
│ │ │ ├── AppToken.kt
│ │ │ ├── FilterChainExceptionHandler.kt
│ │ │ ├── JwtTokenFilter.kt
│ │ │ ├── JwtTokenFilterConfigurer.kt
│ │ │ ├── JwtTokenProvider.kt
│ │ │ └── WebSecurityConfig.kt
│ │ └── web
│ │ │ └── resttemplate
│ │ │ ├── RestTemplateConfig.kt
│ │ │ └── kakao
│ │ │ ├── KakaoApiResponseErrorHandler.kt
│ │ │ ├── KakaoAuthResponseErrorHandler.kt
│ │ │ └── KakaoRestTemplateConfig.kt
│ │ ├── exception
│ │ ├── BizException.kt
│ │ ├── InvalidInputException.kt
│ │ ├── ResourceNotFoundException.kt
│ │ ├── auth
│ │ │ ├── AccessTokenExpiredException.kt
│ │ │ ├── InsufficientAuthException.kt
│ │ │ ├── OnlyWriterCanAccessException.kt
│ │ │ ├── UserNotFoundException.kt
│ │ │ └── WithdrawClubUserNotAllowedException.kt
│ │ ├── club
│ │ │ ├── CannotJoinClubException.kt
│ │ │ ├── ClubNotFoundException.kt
│ │ │ ├── UserIsNotClubMemberException.kt
│ │ │ ├── album
│ │ │ │ ├── ClubAlbumNotFoundException.kt
│ │ │ │ └── NoAuthForClubAlbumException.kt
│ │ │ ├── board
│ │ │ │ └── ClubBoardNotFoundException.kt
│ │ │ └── meeting
│ │ │ │ ├── MeetingAlreadyApplicationException.kt
│ │ │ │ ├── MeetingIsClosedException.kt
│ │ │ │ └── MeetingMemberOverflowException.kt
│ │ └── common
│ │ │ ├── ImplementationIsNotSupported.kt
│ │ │ └── IsAlreadyDeletedException.kt
│ │ └── util
│ │ ├── aws
│ │ └── s3
│ │ │ ├── AwsS3Mo.kt
│ │ │ └── S3Path.kt
│ │ ├── extendFun
│ │ ├── LocalDateExtension.kt
│ │ └── StringExtension.kt
│ │ ├── file
│ │ ├── FileMo.kt
│ │ └── image
│ │ │ └── gif
│ │ │ └── GifMo.kt
│ │ └── kakao
│ │ └── KakaoOAuth.kt
└── resources
│ ├── application-dev.properties
│ ├── application-prod.properties
│ ├── application.properties
│ ├── banner.txt
│ ├── db
│ ├── data-interest-group.sql
│ ├── data-interest.sql
│ └── data-state.sql
│ ├── dist_webp_binaries
│ ├── cwebp
│ ├── dwebp
│ └── gif2webp
│ ├── logback-spring.xml
│ └── webp
│ ├── linux
│ ├── cwebp
│ ├── dwebp
│ └── gif2webp
│ ├── mac
│ ├── cwebp
│ ├── dwebp
│ └── gif2webp
│ └── window
│ ├── cwebp
│ ├── dwebp
│ └── gif2webp
└── test
├── kotlin
└── com
│ └── taskforce
│ └── superinvention
│ ├── app
│ └── domain
│ │ ├── club
│ │ ├── ClubServiceTest.kt
│ │ ├── album
│ │ │ ├── ClubAlbumServiceTest.kt
│ │ │ └── comment
│ │ │ │ └── ClubAlbumCommentServiceTest.kt
│ │ ├── board
│ │ │ ├── ClubBoardServiceTest.kt
│ │ │ ├── comment
│ │ │ │ └── ClubBoardCommentServiceTest.kt
│ │ │ └── like
│ │ │ │ └── ClubBoardLikeServiceTest.kt
│ │ └── user
│ │ │ └── ClubUserServiceTest.kt
│ │ ├── common
│ │ └── image
│ │ │ └── resize
│ │ │ └── ImageResizeServiceTest.kt
│ │ ├── interest
│ │ ├── interest
│ │ │ └── InterestRepoTest.kt
│ │ └── interestGroup
│ │ │ └── InterestGroupRepoTestData.kt
│ │ ├── meeting
│ │ └── MeetingServiceTest.kt
│ │ └── user
│ │ ├── UserServiceTest.kt
│ │ └── userRole
│ │ └── UserRoleDataTest.kt
│ ├── common
│ └── extendFun
│ │ └── StringExtensionTest.kt
│ ├── config
│ ├── MokitoHelper.kt
│ ├── documentation
│ │ └── ApiDocumentUtil.kt
│ ├── jpa
│ │ ├── CriteriaConfig.kt
│ │ └── JpaTestConfig.kt
│ └── test
│ │ ├── ApiDocumentationTest.kt
│ │ ├── ApiDocumentationTestV2.kt
│ │ ├── BaseTest.kt
│ │ ├── DataJpaRepoTest.kt
│ │ ├── IntegrationTest.kt
│ │ ├── MockTest.kt
│ │ ├── MockkTest.kt
│ │ └── TestEnv.kt
│ └── document
│ ├── club
│ ├── ClubDocumentation.kt
│ ├── ClubInfoDocumentation.kt
│ ├── album
│ │ ├── ClubAlbumCommentDocumentation.kt
│ │ ├── ClubAlbumDocumentation.kt
│ │ └── ClubAlbumLikeDocument.kt
│ └── board
│ │ ├── ClubBoardCommentDocumentation.kt
│ │ ├── ClubBoardDocumentation.kt
│ │ └── ClubBoardLikeDocument.kt
│ ├── common
│ └── CommonDocumentation.kt
│ ├── interest
│ └── InterestGroupDocumentation.kt
│ ├── meeting
│ ├── MeetingApplicationDocumentation.kt
│ └── MeetingDocumentation.kt
│ ├── region
│ └── RegionDocumentation.kt
│ └── user
│ └── UserDocumentation.kt
└── resources
└── img
├── animated.gif
├── animated.webp
├── big-animated.gif
├── large-size.jpg
├── large-size.png
├── not-animated.gif
├── not-animated.webp
├── test-large.jpg
└── test.jpg
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: '[Build] Super-Invention Server'
2 |
3 | on:
4 | pull_request:
5 | branches: [ develop ]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 |
13 | - name: Set up JDK 11
14 | uses: actions/setup-java@v1
15 | with:
16 | java-version: 11
17 |
18 | - name: Grant execute permission for gradlew
19 | run: chmod +x gradlew
20 |
21 | - name: Build with Gradle
22 | run: ./gradlew build
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**/build/
6 | !**/src/test/**/build/
7 |
8 | ### STS ###
9 | .apt_generated
10 | .classpath
11 | .factorypath
12 | .project
13 | .settings
14 | .springBeans
15 | .sts4-cache
16 |
17 | ### IntelliJ IDEA ###
18 | .idea
19 | *.iws
20 | *.iml
21 | *.ipr
22 | out/
23 | !**/src/main/**/out/
24 | !**/src/test/**/out/
25 |
26 | ### NetBeans ###
27 | /nbproject/private/
28 | /nbbuild/
29 | /dist/
30 | /nbdist/
31 | /.nb-gradle/
32 |
33 | ### VS Code ###
34 | .vscode/
35 |
36 | ### Spring RestDocs 파일 제외 - 각자 gradle task에서 빌드해서 쓰세요##
37 | /src/main/resources/static/docs/
38 |
39 | ### Secret .properties 파일 제외 - 프로퍼티 파일은 따로 공유!
40 | /src/main/resources/*-secret.properties
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | kapt.incremental.apt=true
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/infra/README.md:
--------------------------------------------------------------------------------
1 | ### [임시 인프라 파일]
2 |
3 | 현재 임시로 EC2 인스턴스에 도커 이미지로 모든 인프라가 올라가있습니다.
4 | 인프라에 문제가 생길 경우 이곳 환경을 참고하면됩니다.
5 |
6 | - t2.micro
7 | - mysql : DB
8 | - nginx : 리버스 프록시용 ( /api - > 서버로 )
9 |
10 |
11 | - script
12 | ~/app/scripts 폴더 내에 위치해있으며, 서버 가동, 정지 등의 스크립트를 담고 있습니다.
--------------------------------------------------------------------------------
/infra/infra/.env:
--------------------------------------------------------------------------------
1 | PINPOINT_VERSION=2.2.1
2 | AGENT_ID=super-invention-server
3 | APP_NAME=super-invention-server
--------------------------------------------------------------------------------
/infra/infra/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | super-invention-server:
4 | image: sightstudio/superinvention
5 | ports:
6 | - '8080:8080'
7 | environment:
8 | spring_datasource_url: $spring_datasource_url
9 | spring_datasource_username: $spring_datasource_username
10 | spring_datasource_password: $spring_datasource_password
11 | oauth_kakao_client_id: $oauth_kakao_client_id
12 | aws_s3_accessKey: $aws_s3_accessKey
13 | aws_s3_secretAccessKey: $aws_s3_secretAccessKey
14 | host_static_path: $host_static_path
15 | jwt_token_secret_key: $jwt_token_secret_key
16 | aws_s3_endpointUrl: $aws_s3_endpointUrl
17 | JAVA_OPTS: "-javaagent:/pinpoint-agent/pinpoint-bootstrap-${PINPOINT_VERSION}.jar -Dpinpoint.agentId=${AGENT_ID} -Dpinpoint.applicationName=${APP_NAME}"
18 | volumes:
19 | - data-volume:/pinpoint-agent
20 | networks:
21 | - super-invention
22 |
23 | volumes:
24 | data-volume:
25 | external: true
26 |
27 | networks:
28 | super-invention:
29 | driver: bridge
30 | external: true
31 |
--------------------------------------------------------------------------------
/infra/infra/mysql/conf/docker-mysql.cnf:
--------------------------------------------------------------------------------
1 | [mysqld]
2 | default-time-zone='+9:00'
3 | max_allowed_packet=500M
4 |
--------------------------------------------------------------------------------
/infra/script/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | sh ./shutdown.sh
3 |
4 | rm -f ./app.jar
5 |
6 | mv ./temp/app.jar ./app.jar
7 |
8 | sh ./startup.sh
9 |
10 | rm -f ./temp/app.jar
--------------------------------------------------------------------------------
/infra/script/shutdown.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | port=8080
3 | while getopts p:f:j:n opt
4 | do
5 | case $opt in
6 | p)
7 | port=$OPTARG
8 | ;;
9 | *)
10 | help
11 | exit 0
12 | ;;
13 | esac
14 | done
15 |
16 | SERVER_PID=$(lsof -i TCP:"$port" | awk 'NR == 2 {print $2}');
17 |
18 | if [ -z "$SERVER_PID" ]; then
19 | echo "[info] No running PID detected"
20 | else
21 | echo "kill -15 $CURRENT_PID"
22 | kill -15 "$SERVER_PID"
23 | echo "[info] Spring Boot Project Shutdown Success"
24 | fi
--------------------------------------------------------------------------------
/infra/script/startup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | help() {
3 | echo "
4 | [help] CLI 파라미터
5 | -p <포트번호>
6 | -f <스프링 프로파일>
7 | -j <실행할 jar 파일>
8 | -n <앱 이름>
9 | "
10 | }
11 |
12 | profile="dev" # Spring Profile 디폴트
13 | port=8080 # Spring 기본 포트
14 | runnableJarName="app.jar" # 실행할 jar 파일
15 | appName="Super Invertion Server"
16 |
17 | while getopts p:f:j:n opt
18 | do
19 | case $opt in
20 | n)
21 | appName=$OPTARG
22 | ;;
23 | p)
24 | port=$OPTARG
25 | ;;
26 | f)
27 | profile=$OPTARG
28 | ;;
29 | j)
30 | runnableJarName=$OPTARG
31 | ;;
32 | *)
33 | help
34 | exit 0
35 | ;;
36 | esac
37 | done
38 |
39 | nohup java -jar "$runnableJarName" \
40 | -Dserver.port="$port" \
41 | -Dspring.profiles.active="$profile" &
42 |
43 | if [ "$?" = "0" ]; then
44 | echo "($appName) Run Successfully"
45 | else
46 | echo "($appName) Run Fail"
47 | fi;
48 |
49 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "superinvention"
2 |
--------------------------------------------------------------------------------
/src/course/rest/asset/large-size.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/course/rest/asset/large-size.jpg
--------------------------------------------------------------------------------
/src/course/rest/asset/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/course/rest/asset/test.jpg
--------------------------------------------------------------------------------
/src/course/rest/club/Club.http:
--------------------------------------------------------------------------------
1 | ### [로컬] 내 클럽 조회
2 | GET http://localhost:8080/clubs/search
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDUxMDAxNjQ5Iiwic3ViIjoiMTQ1MTAwMTY0OSIsImlhdCI6MTYxODc0MzEzOSwiZXhwIjoxNjE5MzQ3OTM5fQ.9i64zN1FJIGB8NF-goqeDBtvSGDoKF566eB_w3O6xAw
6 |
7 | ### [개발] 내 클럽 조회
8 | GET {{host}}/clubs/my
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-dong}}
12 |
13 |
14 | ### [개발] 클럽 가입
15 | POST {{host}} /clubs/6212/users
16 | Accept: application/json
17 | Authorization: Bearer {{token-dong}}
18 |
19 |
20 | ### 모임 삭제
21 | DELETE {{host}}/clubs/6386
22 | Content-Type: application/json;charset=UTF-8
23 | Accept: application/json
24 | Authorization: Bearer {{token-jun}}
25 |
26 | ### 모임 수정
27 | PUT {{host}}/clubs/6164
28 | Content-Type: application/json;charset=UTF-8
29 | Accept: application/json
30 | Authorization: Bearer {{token-jun}}
31 |
32 | {
33 | "name": "제목을 이렇게 바꿔보자",
34 | "description": "설명을 이렇게 바꿔보자",
35 | "maximumNumber": 55,
36 | "mainImageUrl": null,
37 | "interestList":
38 | [
39 | {
40 | "seq": 10,
41 | "priority": 1
42 | }
43 | ],
44 | "regionList":
45 | [
46 | {
47 | "seq": 120,
48 | "priority": 1
49 | }
50 | ]
51 | }
--------------------------------------------------------------------------------
/src/course/rest/club/ClubInfo.http:
--------------------------------------------------------------------------------
1 | ### [로컬] 모임 상세 조회 - 클럽 미가입 && 로그인 상태
2 | GET {{host}}/clubs/6164
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-sdm}}
6 |
7 | ### [로컬] 모임 상세 조회 - 클럽 가입 && 로그인 상태
8 | GET {{host}}/clubs/8936
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-sdm}}
12 |
13 | ### [로컬] 클럽 상세 정보 조회 - 비로그인 상태
14 | GET {{host}}/clubs/6174
15 | Content-Type: application/json;charset=UTF-8
16 | Accept: application/json
17 |
18 | ### 모임 관심사 그룹으로 검색
19 | GET {{host}}/clubs/search?regionSeq=501
20 | Content-Type: application/json;charset=UTF-8
21 | Accept: application/json
22 | Authorization: Bearer {{token-jun}}
23 |
24 | ### 모임 그룹으로 검색
25 | GET {{host}}/clubs/search?size=20&page=0
26 | Content-Type: application/json;charset=UTF-8
27 | Accept: application/json
28 | Authorization: Bearer {{token-sdm}}
--------------------------------------------------------------------------------
/src/course/rest/club/album/ClubAlbum.http:
--------------------------------------------------------------------------------
1 | ### 모임 사진첩 등록
2 | POST {{host}}/club/6327/album
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-sdm}}
6 |
7 | {
8 | "title": "1234",
9 | "image": {
10 | "absolutePath": "https://super-invention-static.s3.ap-northeast-2.amazonaws.com/temp/img/20210413125934-3b9266dc-b87b-46ed-9244-84ec9eb87508-test-img.jpg",
11 | "filePath": "temp/img/20210413125934-3b9266dc-b87b-46ed-9244-84ec9eb87508-test-img.jpg",
12 | "fileName": "20210413125934-3b9266dc-b87b-46ed-9244-84ec9eb87508-test-img.jpg"
13 | }
14 | }
15 |
16 | ### 모임 사진첩 수정
17 | PUT {{host}}/club/6327/album/9078
18 | Content-Type: application/json;charset=UTF-8
19 | Accept: application/json
20 | Authorization: Bearer {{token-sdm}}
21 |
22 | {
23 | "title": "12342222",
24 | "image": {
25 | "absolutePath": "https://super-invention-static.s3.ap-northeast-2.amazonaws.com/temp/img/20210413011914-11e7686f-3e7f-4107-b0c5-960a5e1600dc-large-sizessssss.jpg",
26 | "filePath": "temp/img/20210413011914-11e7686f-3e7f-4107-b0c5-960a5e1600dc-large-sizessssss.jpg",
27 | "fileName": "20210413011914-11e7686f-3e7f-4107-b0c5-960a5e1600dc-large-sizessssss.jpg"
28 | }
29 | }
30 |
31 | ### 모임 사진첩 사진첩 조회
32 | GET {{host}}/club/6327/album?title=2
33 | Content-Type: application/json;charset=UTF-8
34 | Accept: application/json
35 | Authorization: Bearer {{token-sdm}}
36 |
37 | ### 모임 사진첩 단일 조회
38 | GET {{host}}/club/6327/album/9068
39 | Content-Type: application/json;charset=UTF-8
40 | Accept: application/json
41 | Authorization: Bearer {{token-sdm}}
42 |
--------------------------------------------------------------------------------
/src/course/rest/club/album/ClubAlbumComment.http:
--------------------------------------------------------------------------------
1 | ### 내 클럽 사진첩 댓글 조회
2 | GET {{host}}/club/6174/album/9108/comment
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-sdm}}
6 |
7 | ### 내 모임 사진첩 댓글 등록 - 루트
8 | POST {{host}}/club/9000/album/9120/comment
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-sdm}}
12 |
13 | {
14 | "content" : "테스트 댓글"
15 | }
16 |
17 | ### 내 모임 사진첩 대댓글 조회
18 | GET {{host}}/club/9000/album/9120/comment/12083?depthLimit=2
19 | Content-Type: application/json;charset=UTF-8
20 | Accept: application/json
21 | Authorization: Bearer {{token-sdm}}
22 |
23 | ### 내 모임 사진첩 대댓글 등록
24 | POST {{host}}/club/6174/album/6943/comment?parentCommentSeq=6887
25 | Content-Type: application/json;charset=UTF-8
26 | Accept: application/json
27 | Authorization: Bearer {{token-sdm}}
28 |
29 | {
30 | "content" : "테스트 대댓글"
31 | }
32 |
33 | ### 댓글 삭제
34 | DELETE {{host}}/club/9000/album/9120/comment/12083
35 | Content-Type: application/json;charset=UTF-8
36 | Authorization: Bearer {{token-sdm}}
37 |
--------------------------------------------------------------------------------
/src/course/rest/club/album/ClubAlbumLike.http:
--------------------------------------------------------------------------------
1 | ### 내 클럽 사진첩 좋아요 등록
2 | POST {{host}}/club/6327/album/6652/like
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-sdm}}
6 |
7 | ### 내 클럽 사진첩 좋아요 등록
8 | POST {{host}}/club/6327/album/6652/like
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-dong}}
12 |
13 |
14 | ### 내 클럽 사진첩 좋아요 취소
15 | DELETE {{host}}/club/6327/album/6652/like
16 | Content-Type: application/json;charset=UTF-8
17 | Accept: application/json
18 | Authorization: Bearer {{token-sdm}}
19 |
20 | ### 내 클럽 사진첩 좋아요 등록
21 | DELETE {{host}}/club/6174/album/6451/like
22 | Content-Type: application/json;charset=UTF-8
23 | Accept: application/json
24 | Authorization: Bearer {{token-sdm}}
--------------------------------------------------------------------------------
/src/course/rest/club/board/ClubBoardComment.http:
--------------------------------------------------------------------------------
1 | ### 내 모임 게시글 댓글 조회
2 | GET {{host}}/club/6174/board/7/comment
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-dong}}
6 |
7 | ### 내 모임 게시글 댓글 등록
8 | POST {{host}}/club/6327/board/7/comment
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-sdm}}
12 |
13 | {
14 | "content" : "테스트 댓글"
15 | }
16 |
17 | ### 내 모임 게시글 대댓글 등록
18 | POST {{host}}/club/6327/board/7/comment?parentCommentSeq=36
19 | Content-Type: application/json;charset=UTF-8
20 | Accept: application/json
21 | Authorization: Bearer {{token-sdm}}
22 |
23 | {
24 | "content" : "테스트 댓글"
25 | }
26 |
27 | ### 내 모임 게시글 댓글 조회
28 | GET {{host}}/club/6174/board/7/comment?page=0&size=20
29 | Content-Type: application/json;charset=UTF-8
30 | Accept: application/json
31 | Authorization: Bearer {{token-sdm}}
32 |
33 | ### 내 모임 게시글 대댓글 조회
34 | GET {{host}}/club/6174/board/7/comment/36
35 | Content-Type: application/json;charset=UTF-8
36 | Accept: application/json
37 | Authorization: Bearer {{token-sdm}}
38 |
39 | ### 내 모임 게시글 댓글 삭제
40 | DELETE {{host}}/club/6212/board/60/comment/107
41 | Content-Type: application/json;charset=UTF-8
42 | Accept: application/json
43 | Authorization: Bearer {{token-sdm}}
44 |
--------------------------------------------------------------------------------
/src/course/rest/club/board/ClubBoardLike.http:
--------------------------------------------------------------------------------
1 | ### 내 모임 게시글 좋아요 등록
2 | POST {{host}}/club/6174/board/2/like
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-sdm}}
6 |
7 | ### 내 모임 게시글 좋아요 취소
8 | DELETE {{host}}/club/6174/board/2/like
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-sdm}}
--------------------------------------------------------------------------------
/src/course/rest/club/role/Role.http:
--------------------------------------------------------------------------------
1 | ### 내 클럽 조회
2 | GET {{host}}/clubs/my
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 | Authorization: Bearer {{token-sdm}}
6 |
7 | ### 모임 매니저 조회
8 | GET {{host}}/clubs/6164/roles/managers
9 | Content-Type: application/json;charset=UTF-8
10 | Accept: application/json
11 | Authorization: Bearer {{token-sdm}}
12 |
--------------------------------------------------------------------------------
/src/course/rest/common/temp-upload.http:
--------------------------------------------------------------------------------
1 | ### 파일 임시저장
2 | POST {{host}}/common/temp/file
3 | Content-Type: multipart/form-data; boundary=boundary
4 | Authorization: Bearer {{token-sdm}}
5 |
6 | --boundary
7 | Content-Disposition: form-data; name="file"; filename="large-sizessssss.jpg"
8 |
9 | < ../asset/large-size.jpg
10 |
11 | ### 이미지 임시저장
12 | POST {{host}}/common/temp/image?width=200&height=100
13 | Content-Type: multipart/form-data; boundary=boundary
14 | Authorization: Bearer {{token-sdm}}
15 |
16 | --boundary
17 | Content-Disposition: form-data; name="file"; filename="test-img.jpg"
18 |
19 | < ../asset/test.jpg
20 |
--------------------------------------------------------------------------------
/src/course/rest/http-client.env.json:
--------------------------------------------------------------------------------
1 | {
2 | "dev": {
3 | "host": "mannal.ga/api",
4 | "token-sdm" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDM5NTI4NTk3Iiwic3ViIjoiMTQzOTUyODU5NyIsImlhdCI6MTYxNzI1MjE5MSwiZXhwIjoxNjQ4Nzg4MTkxfQ.mCDTjD_3dQqTyaM3OggRHGD7eY3Vv6Ud6JpfD7qlf2E",
5 | "token-jun" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDUxMDAxNjQ5Iiwic3ViIjoiMTQ1MTAwMTY0OSIsImlhdCI6MTU5OTI4MzIxOCwiZXhwIjoxNjMwODE5MjE4fQ.v-sfReNKli476qoHc1F2yoak-n4bh_D2Db5rczwS3Bs",
6 | "token-dong": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDEyMzc1MzA5Iiwic3ViIjoiMTQxMjM3NTMwOSIsImlhdCI6MTYwMDQ0MDc4OSwiZXhwIjoxNjMxOTc2Nzg5fQ.csOA38Zh0dL1OtG0AKqRudY4E8FQMg3gVC80h7XuPsY",
7 | "token-tester": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI2MTIiLCJzdWIiOiI2MTIiLCJpYXQiOjE2MTY1MDU1OTksImV4cCI6MTY0ODA0MTU5OX0.GIABJSsYJDZq54GO-zX681DnmYrX54q-2brt_5C9yvY"
8 | },
9 |
10 | "local": {
11 | "host": "http://localhost:8080",
12 | "token-sdm" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDM5NTI4NTk3Iiwic3ViIjoiMTQzOTUyODU5NyIsImlhdCI6MTYxNzI1MjE5MSwiZXhwIjoxNjQ4Nzg4MTkxfQ.mCDTjD_3dQqTyaM3OggRHGD7eY3Vv6Ud6JpfD7qlf2E",
13 | "token-jun" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDUxMDAxNjQ5Iiwic3ViIjoiMTQ1MTAwMTY0OSIsImlhdCI6MTYxNzgwNzg1NiwiZXhwIjoxNjE3ODA4NzU2fQ.4QgMeul4HmsfXpq3I3B2lDZXGNLgT62ubVSw6Zkg2iA",
14 | "token-dong": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNDEyMzc1MzA5Iiwic3ViIjoiMTQxMjM3NTMwOSIsImlhdCI6MTYwMDQ0MDc4OSwiZXhwIjoxNjMxOTc2Nzg5fQ.csOA38Zh0dL1OtG0AKqRudY4E8FQMg3gVC80h7XuPsY",
15 | "token-tester": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI2MTIiLCJzdWIiOiI2MTIiLCJpYXQiOjE2MTY1MDU1OTksImV4cCI6MTY0ODA0MTU5OX0.GIABJSsYJDZq54GO-zX681DnmYrX54q-2brt_5C9yvY"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/course/rest/region/region.http:
--------------------------------------------------------------------------------
1 | ### [로컬]
2 | GET {{host}} /regions
3 | Content-Type: application/json;charset=UTF-8
4 | Accept: application/json
5 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/addClub.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/addClub/http-request.adoc[]
14 |
15 | include::{sub-snippet}/addClub/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/addClub/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/addClub/http-response.adoc[]
21 |
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/addClubUser.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/addClubUser/http-request.adoc[]
14 |
15 | include::{sub-snippet}/addClubUser/path-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/addClubUser/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/addClubUser/http-response.adoc[]
21 |
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-comment-edit.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-comment-edit/http-request.adoc[]
14 | include::{sub-snippet}/club-album-comment-edit/path-parameters.adoc[]
15 | include::{sub-snippet}/club-album-comment-edit/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-album-comment-edit/response-fields.adoc[]
19 | include::{sub-snippet}/club-album-comment-edit/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-comment-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-comment-register/http-request.adoc[]
14 | include::{sub-snippet}/club-album-comment-register/request-parameters.adoc[]
15 | include::{sub-snippet}/club-album-comment-register/path-parameters.adoc[]
16 | include::{sub-snippet}/club-album-comment-register/request-fields.adoc[]
17 |
18 | Response
19 | include::{sub-snippet}/club-album-comment-register/response-fields.adoc[]
20 | include::{sub-snippet}/club-album-comment-register/http-response.adoc[]
21 |
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-comment-remove.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-comment-remove/http-request.adoc[]
14 | include::{sub-snippet}/club-album-comment-remove/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-comment-remove/response-fields.adoc[]
18 |
19 | include::{sub-snippet}/club-album-comment-remove/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-comment-select-sub.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-comment-select-sub/http-request.adoc[]
14 | include::{sub-snippet}/club-album-comment-select-sub/path-parameters.adoc[]
15 | include::{sub-snippet}/club-album-comment-select-sub/request-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-album-comment-select-sub/response-fields.adoc[]
19 | include::{sub-snippet}/club-album-comment-select-sub/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-comment-select.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-comment-select/http-request.adoc[]
14 | include::{sub-snippet}/club-album-comment-select/path-parameters.adoc[]
15 | include::{sub-snippet}/club-album-comment-select/request-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-album-comment-select/response-fields.adoc[]
19 | include::{sub-snippet}/club-album-comment-select/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-edit.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-edit/http-request.adoc[]
14 |
15 | include::{sub-snippet}/club-album-edit/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-album-edit/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/club-album-edit/http-response.adoc[]
21 |
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-like-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-like-register/http-request.adoc[]
14 | include::{sub-snippet}/club-album-like-register/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-like-register/response-fields.adoc[]
18 | include::{sub-snippet}/club-album-like-register/http-response.adoc[]
19 |
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-like-remove.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-like-remove/http-request.adoc[]
14 | include::{sub-snippet}/club-album-like-remove/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-like-remove/response-fields.adoc[]
18 | include::{sub-snippet}/club-album-like-remove/http-response.adoc[]
19 |
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-register/http-request.adoc[]
14 |
15 | include::{sub-snippet}/club-album-register/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-album-register/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/club-album-register/http-response.adoc[]
21 |
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-remove.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-remove/http-request.adoc[]
14 | include::{sub-snippet}/club-album-remove/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-remove/response-fields.adoc[]
18 |
19 | include::{sub-snippet}/club-album-remove/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-select-single.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-select-single/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/club-album-select-single/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/club-album-select-single/http-response.adoc[]
19 |
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/album/club-album-select.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-select/http-request.adoc[]
14 | include::{sub-snippet}/club-album-select/request-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-select/response-fields.adoc[]
18 |
19 | include::{sub-snippet}/club-album-select/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-comment-edit.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-board-comment-edit/http-request.adoc[]
14 | include::{sub-snippet}/club-board-comment-edit/path-parameters.adoc[]
15 | include::{sub-snippet}/club-board-comment-edit/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-board-comment-edit/response-fields.adoc[]
19 | include::{sub-snippet}/club-board-comment-edit/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-comment-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-board-comment-register/http-request.adoc[]
14 | include::{sub-snippet}/club-board-comment-register/request-parameters.adoc[]
15 | include::{sub-snippet}/club-board-comment-register/path-parameters.adoc[]
16 | include::{sub-snippet}/club-board-comment-register/request-fields.adoc[]
17 |
18 | Response
19 | include::{sub-snippet}/club-board-comment-register/response-fields.adoc[]
20 | include::{sub-snippet}/club-board-comment-register/http-response.adoc[]
21 |
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-comment-remove.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-board-comment-remove/http-request.adoc[]
14 | include::{sub-snippet}/club-board-comment-remove/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-board-comment-remove/response-fields.adoc[]
18 |
19 | include::{sub-snippet}/club-board-comment-remove/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-comment-select-sub.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-board-comment-select-sub/http-request.adoc[]
14 | include::{sub-snippet}/club-board-comment-select-sub/path-parameters.adoc[]
15 | include::{sub-snippet}/club-board-comment-select-sub/request-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-board-comment-select-sub/response-fields.adoc[]
19 | include::{sub-snippet}/club-board-comment-select-sub/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-comment-select.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-board-comment-select/http-request.adoc[]
14 | include::{sub-snippet}/club-board-comment-select/path-parameters.adoc[]
15 | include::{sub-snippet}/club-board-comment-select/request-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-board-comment-select/response-fields.adoc[]
19 | include::{sub-snippet}/club-board-comment-select/http-response.adoc[]
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-delete.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/delete-club-board/http-request.adoc[]
14 | include::{sub-snippet}/delete-club-board/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/delete-club-board/response-fields.adoc[]
18 | include::{sub-snippet}/delete-club-board/response-body.adoc[]
19 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-edit.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/edit-club-board/http-request.adoc[]
14 | include::{sub-snippet}/edit-club-board/path-parameters.adoc[]
15 | include::{sub-snippet}/edit-club-board/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/edit-club-board/response-fields.adoc[]
19 | include::{sub-snippet}/edit-club-board/response-body.adoc[]
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-like-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-like-register/http-request.adoc[]
14 | include::{sub-snippet}/club-album-like-register/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-like-register/response-fields.adoc[]
18 | include::{sub-snippet}/club-album-like-register/http-response.adoc[]
19 |
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-like-remove.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-album-like-remove/http-request.adoc[]
14 | include::{sub-snippet}/club-album-like-remove/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-album-like-remove/response-fields.adoc[]
18 | include::{sub-snippet}/club-album-like-remove/http-response.adoc[]
19 |
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/register-club-board/http-request.adoc[]
14 | include::{sub-snippet}/register-club-board/request-fields.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/register-club-board/response-fields.adoc[]
18 | include::{sub-snippet}/register-club-board/response-body.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-select-list.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/select-club-board-list/http-request.adoc[]
14 | include::{sub-snippet}/select-club-board-list/request-parameters.adoc[]
15 |
16 |
17 | Response
18 | include::{sub-snippet}/select-club-board-list/response-fields.adoc[]
19 | include::{sub-snippet}/select-club-board-list/response-body.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/board/club-board-select.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/select-club-board/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/select-club-board/response-fields.adoc[]
17 | include::{sub-snippet}/select-club-board/response-body.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/changeClubInterests.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/changeClubInterests/http-request.adoc[]
14 |
15 | include::{sub-snippet}/changeClubInterests/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/changeClubInterests/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/changeClubInterests/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/changeClubRegions.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/changeClubRegions/http-request.adoc[]
14 |
15 | include::{sub-snippet}/changeClubRegions/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/changeClubRegions/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/changeClubRegions/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/changeClubUserRole.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 |
13 |
14 | Request
15 | include::{sub-snippet}/changeClubUserRole/http-request.adoc[]
16 | |===
17 | | 권한번호 | 권한코드 | 권한명
18 |
19 | | 1
20 | | NONE
21 | | 없음 (미사용)
22 |
23 | | 2
24 | | MEMBER
25 | | 회원 (모임 미가입)
26 |
27 | | 3
28 | | CLUB_MEMBER
29 | | 모임원
30 |
31 | | 4
32 | | MANAGER
33 | | 매니저
34 |
35 | | 5
36 | | MASTER
37 | | 모임장
38 | |===
39 |
40 | Response
41 | include::{sub-snippet}/changeClubUserRole/response-fields.adoc[]
42 |
43 | include::{sub-snippet}/changeClubUserRole/http-response.adoc[]
44 |
45 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/delete.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-delete/http-request.adoc[]
14 | include::{sub-snippet}/club-delete/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-delete/http-response.adoc[]
18 | include::{sub-snippet}/club-delete/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/getMyClubUserInfo.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/getMyClubUserInfo/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/getMyClubUserInfo/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/getMyClubUserInfo/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/kick.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-kick/http-request.adoc[]
14 | include::{sub-snippet}/club-kick/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-kick/http-response.adoc[]
18 | include::{sub-snippet}/club-kick/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/create-meeting.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/create-meeting/http-request.adoc[]
14 |
15 | include::{sub-snippet}/create-meeting/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/create-meeting/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/create-meeting/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/delete-meeting.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/delete-meeting/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/delete-meeting/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/delete-meeting/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/get-meeting-application-status.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/get-meeting-application-status/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/get-meeting-application-status/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/get-meeting-application-status/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/get-meeting-application.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/get-meeting-application/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/get-meeting-application/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/get-meeting-application/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/meeting-all.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | ifndef::snippets[]
5 | :sub-snippet: ../../../../../build/generated-snippets
6 | endif::[]
7 | :doctype: book
8 | :icons: font
9 | :source-highlighter: highlightjs
10 | :toc: left
11 | :toclevels: 4
12 | :sectlinks:
13 | :site-url: /build/asciidoc/html5/state
14 |
15 | Request
16 | include::{sub-snippet}/meeting-all/http-request.adoc[]
17 |
18 | Response
19 | include::{sub-snippet}/meeting-all/response-fields.adoc[]
20 |
21 | include::{sub-snippet}/meeting-all/http-response.adoc[]
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/meeting-application-cancel.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/meeting-application-cancel/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/meeting-application-cancel/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/meeting-application-cancel/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/meeting-application.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/meeting-application/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/meeting-application/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/meeting-application/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/meeting-one.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | ifndef::snippets[]
5 | :sub-snippet: ../../../../../build/generated-snippets
6 | endif::[]
7 | :doctype: book
8 | :icons: font
9 | :source-highlighter: highlightjs
10 | :toc: left
11 | :toclevels: 4
12 | :sectlinks:
13 | :site-url: /build/asciidoc/html5/state
14 |
15 | Request
16 | include::{sub-snippet}/meeting-one/http-request.adoc[]
17 |
18 | Response
19 | include::{sub-snippet}/meeting-one/response-fields.adoc[]
20 |
21 | include::{sub-snippet}/meeting-one/http-response.adoc[]
22 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/meeting/modify-meeting.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/modify-meeting/http-request.adoc[]
14 |
15 | include::{sub-snippet}/modify-meeting/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/modify-meeting/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/modify-meeting/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/modify.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-modify/http-request.adoc[]
14 | include::{sub-snippet}/club-modify/path-parameters.adoc[]
15 | include::{sub-snippet}/club-modify/request-body.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/club-modify/http-response.adoc[]
19 | include::{sub-snippet}/club-modify/response-fields.adoc[]
20 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/myClubList.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/myClubList/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/myClubList/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/myClubList/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/searchClub.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/searchClub/http-request.adoc[]
14 |
15 | include::{sub-snippet}/searchClub/request-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/searchClub/http-response.adoc[]
19 |
20 | include::{sub-snippet}/searchClub/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/selectClubInfoDetails.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/select-club-info-detail/http-request.adoc[]
14 | include::{sub-snippet}/select-club-info-detail/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/select-club-info-detail/http-response.adoc[]
18 | include::{sub-snippet}/select-club-info-detail/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/club/withdraw.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/club-withdraw/http-request.adoc[]
14 | include::{sub-snippet}/club-withdraw/path-parameters.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/club-withdraw/http-response.adoc[]
18 | include::{sub-snippet}/club-withdraw/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/common/error.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/common
11 |
12 | Response
13 | include::{sub-snippet}/error/response-fields.adoc[]
14 | include::{sub-snippet}/error/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/common/temp-file-upload.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/common
11 |
12 | Request
13 | include::{sub-snippet}/temp-file-upload/http-request.adoc[]
14 | include::{sub-snippet}/temp-file-upload/request-parts.adoc[]
15 |
16 | Response
17 | include::{sub-snippet}/temp-file-upload/response-fields.adoc[]
18 | include::{sub-snippet}/temp-file-upload/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/common/temp-image-upload.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/common
11 |
12 | Request
13 | include::{sub-snippet}/temp-image-upload/http-request.adoc[]
14 | include::{sub-snippet}/temp-image-upload/request-parts.adoc[]
15 | include::{sub-snippet}/temp-image-upload/request-parameters.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/temp-image-upload/response-fields.adoc[]
19 | include::{sub-snippet}/temp-image-upload/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/docinfo-footer.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/docinfo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/interest/changeUserInterest.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/changeUserInterest/http-request.adoc[]
14 |
15 | include::{sub-snippet}/changeUserInterest/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/changeUserInterest/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/changeUserInterest/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/interest/interest-group-all.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/interest-group-all/http-request.adoc[]
14 |
15 | ....
16 | 요구 Request Header 없음
17 | ....
18 |
19 | ....
20 | 요구 Request Body 없음
21 | ....
22 |
23 | Response
24 | include::{sub-snippet}/interest-group-all/response-fields.adoc[]
25 |
26 | include::{sub-snippet}/interest-group-all/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/interest/userInterest.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/userInterest/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/userInterest/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/userInterest/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/region/region-all.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/region-all/http-request.adoc[]
14 |
15 | ....
16 | 요구 Request Header 없음
17 | ....
18 |
19 | ....
20 | 요구 Request Body 없음
21 | ....
22 |
23 | Response
24 | include::{sub-snippet}/region-all/response-fields.adoc[]
25 |
26 | include::{sub-snippet}/region-all/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/region/userRegions.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/user-states
11 |
12 | Request
13 | include::{sub-snippet}/userRegions/http-request.adoc[]
14 |
15 | ....
16 | 요구 Request Fields 없음
17 | ....
18 |
19 | Response
20 | include::{sub-snippet}/userRegions/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/changeUserRegions.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/changeUserRegions/http-request.adoc[]
14 |
15 | include::{sub-snippet}/changeUserRegions/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/changeUserRegions/response-fields.adoc[]
19 |
20 | include::{sub-snippet}/changeUserRegions/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/kakaoUserProfileInfo.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/kakaoUserProfileInfo/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/kakaoUserProfileInfo/response-fields.adoc[]
17 |
18 | include::{sub-snippet}/kakaoUserProfileInfo/http-response.adoc[]
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/saveKakaoToken.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | ....
14 | 요구 Request Header 없음
15 | ....
16 |
17 | include::{sub-snippet}/saveKakaoToken/http-request.adoc[]
18 | include::{sub-snippet}/saveKakaoToken/request-fields.adoc[]
19 |
20 | Response
21 | include::{sub-snippet}/saveKakaoToken/response-fields.adoc[]
22 | include::{sub-snippet}/saveKakaoToken/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/user-change.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/user-change/http-request.adoc[]
14 |
15 | include::{sub-snippet}/user-change/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/user-change/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/user-check-register.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/user-check-register/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/user-check-register/http-response.adoc[]
17 | include::{sub-snippet}/user-check-register/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/userInfo.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/user-info/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/user-info/http-response.adoc[]
17 | include::{sub-snippet}/user-info/response-fields.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/userRegist.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/userRegist/http-request.adoc[]
14 |
15 | include::{sub-snippet}/userRegist/request-fields.adoc[]
16 |
17 | Response
18 | include::{sub-snippet}/userRegist/http-response.adoc[]
--------------------------------------------------------------------------------
/src/docs/asciidoc/user/userWithdraw.adoc:
--------------------------------------------------------------------------------
1 | ifndef::snippets[]
2 | :sub-snippet: ../../../../build/generated-snippets
3 | endif::[]
4 | :doctype: book
5 | :icons: font
6 | :source-highlighter: highlightjs
7 | :toc: left
8 | :toclevels: 4
9 | :sectlinks:
10 | :site-url: /build/asciidoc/html5/state
11 |
12 | Request
13 | include::{sub-snippet}/userWithdraw/http-request.adoc[]
14 |
15 | Response
16 | include::{sub-snippet}/userWithdraw/http-response.adoc[]
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/SuperinventionApplication.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention
2 |
3 | import org.springframework.boot.autoconfigure.SpringBootApplication
4 | import org.springframework.boot.runApplication
5 | import org.springframework.web.servlet.config.annotation.EnableWebMvc
6 |
7 | @SpringBootApplication
8 | class SuperinventionApplication
9 |
10 | fun main(args: Array) {
11 | runApplication(*args)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/BaseEntity.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain
2 | import org.springframework.data.annotation.CreatedDate
3 | import org.springframework.data.annotation.LastModifiedDate
4 | import org.springframework.data.jpa.domain.support.AuditingEntityListener
5 | import java.time.LocalDateTime
6 | import javax.persistence.*
7 |
8 | @EntityListeners(AuditingEntityListener::class)
9 | @MappedSuperclass
10 | open class BaseEntity {
11 |
12 | @Id
13 | @GeneratedValue(strategy = GenerationType.IDENTITY)
14 | var seq: Long? = null
15 |
16 | @CreatedDate
17 | var createdAt: LocalDateTime? = LocalDateTime.now()
18 |
19 | @LastModifiedDate
20 | var updatedAt: LocalDateTime? = null
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/album/comment/ClubAlbumComment.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.album.comment
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.album.ClubAlbum
5 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
6 | import org.hibernate.annotations.Formula
7 | import javax.persistence.Entity
8 | import javax.persistence.FetchType
9 | import javax.persistence.JoinColumn
10 | import javax.persistence.ManyToOne
11 |
12 | @Entity
13 | class ClubAlbumComment(
14 | var content: String,
15 |
16 | @ManyToOne(fetch = FetchType.LAZY)
17 | @JoinColumn(name="club_user_seq")
18 | var clubUser: ClubUser,
19 |
20 | @ManyToOne(fetch = FetchType.LAZY)
21 | @JoinColumn(name="club_album_seq")
22 | var clubAlbum: ClubAlbum,
23 |
24 | @ManyToOne(fetch = FetchType.LAZY)
25 | @JoinColumn(name="parent_comment_seq")
26 | var parent: ClubAlbumComment?,
27 |
28 | var depth: Long,
29 |
30 | var deleteFlag: Boolean ?= false
31 | ): BaseEntity() {
32 |
33 | // 직전 하위 뎁스의 댓글 개수만 보여줌
34 | @Formula("(select count(*) from club_album_comment cac where cac.parent_comment_seq = seq and cac.depth = depth+1)")
35 | var subCommentCnt: Long ?= null
36 |
37 | // 모든 하위 뎁스의 댓글 개수만 보여줌
38 | @Formula("(select count(*) from club_album_comment cac where cac.parent_comment_seq = seq and cac.depth > depth)")
39 | var totalSubCommentCnt: Long ?= null
40 |
41 | constructor(content: String, clubUser: ClubUser, clubAlbum: ClubAlbum) :this(
42 | content = content,
43 | clubUser = clubUser,
44 | clubAlbum = clubAlbum,
45 | parent = null,
46 | depth = 1
47 | )
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/album/comment/ClubAlbumCommentCTE.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.album.comment
2 |
3 | import com.blazebit.persistence.CTE
4 | import com.taskforce.superinvention.app.domain.BaseEntity
5 | import com.taskforce.superinvention.app.domain.club.album.ClubAlbum
6 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
7 | import javax.persistence.Entity
8 | import javax.persistence.FetchType
9 | import javax.persistence.JoinColumn
10 | import javax.persistence.ManyToOne
11 |
12 | @CTE
13 | @Entity
14 | class ClubAlbumCommentCTE(
15 | var content: String,
16 |
17 | @ManyToOne(fetch = FetchType.LAZY)
18 | @JoinColumn(name="parent_comment_seq")
19 | var parent: ClubAlbumComment?,
20 |
21 | @ManyToOne(fetch = FetchType.LAZY)
22 | @JoinColumn(name="club_user_seq")
23 | var clubUser: ClubUser,
24 |
25 | @ManyToOne(fetch = FetchType.LAZY)
26 | @JoinColumn(name="club_album_seq")
27 | var clubAlbum: ClubAlbum,
28 |
29 | var depth: Long,
30 |
31 | var subCommentCnt: Long?,
32 |
33 | var deleteFlag: Boolean ?= false
34 |
35 | ): BaseEntity()
36 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/album/like/ClubAlbumLike.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.album.like
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.album.ClubAlbum
5 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
6 | import javax.persistence.*
7 |
8 | @Entity
9 | class ClubAlbumLike(
10 |
11 | @ManyToOne(fetch = FetchType.LAZY)
12 | @JoinColumn(name = "club_album_seq")
13 | val clubAlbum: ClubAlbum,
14 |
15 | @ManyToOne(fetch = FetchType.LAZY)
16 | @JoinColumn(name= "club_user_seq")
17 | val clubUser: ClubUser
18 | ): BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/album/like/ClubAlbumLikeRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.album.like
2 |
3 | import com.querydsl.core.types.Predicate
4 | import com.taskforce.superinvention.app.domain.club.album.ClubAlbum
5 | import com.taskforce.superinvention.app.domain.club.album.QClubAlbum
6 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
7 | import org.springframework.data.jpa.repository.JpaRepository
8 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
9 | import org.springframework.stereotype.Repository
10 |
11 | interface ClubAlbumLikeRepository: JpaRepository, ClubAlbumLikeCustom {
12 |
13 | fun findByClubAlbumAndClubUser(clubAlbum: ClubAlbum, clubUser: ClubUser): ClubAlbumLike?
14 | fun findByClubAlbumSeqAndClubUser(clubAlbumSeq: Long, clubUser: ClubUser): ClubAlbumLike?
15 | fun findByClubAlbumIn(clubAlbumList: List): List
16 | }
17 |
18 | interface ClubAlbumLikeCustom {
19 | fun getClubAlbumLikeCnt(clubAlbum: ClubAlbum): Long
20 | }
21 |
22 | @Repository
23 | class ClubAlbumLikeRepositoryImpl: ClubAlbumLikeCustom,
24 | QuerydslRepositorySupport(ClubAlbumLike::class.java) {
25 |
26 | override fun getClubAlbumLikeCnt(clubAlbum: ClubAlbum): Long {
27 | val clubAlbumLike = QClubAlbumLike.clubAlbumLike
28 |
29 | val query = from(clubAlbumLike)
30 | .where(eqSeq(clubAlbumLike.clubAlbum, clubAlbum))
31 |
32 | return query.fetchCount()
33 | }
34 |
35 |
36 | private fun eqSeq(clubAlbum: QClubAlbum, targetClubAlbum: ClubAlbum): Predicate {
37 | return clubAlbum.seq.eq(targetClubAlbum.seq)
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/board/comment/ClubBoardComment.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.board.comment
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
5 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
6 | import org.hibernate.annotations.Formula
7 | import javax.persistence.Entity
8 | import javax.persistence.FetchType
9 | import javax.persistence.JoinColumn
10 | import javax.persistence.ManyToOne
11 |
12 | @Entity
13 | class ClubBoardComment(
14 | var content: String,
15 |
16 | @ManyToOne( fetch = FetchType.LAZY)
17 | @JoinColumn(name = "club_user_seq")
18 | var clubUser: ClubUser,
19 |
20 | @ManyToOne( fetch = FetchType.LAZY)
21 | @JoinColumn(name = "club_board_seq")
22 | var clubBoard: ClubBoard,
23 |
24 | @ManyToOne( fetch = FetchType.LAZY)
25 | @JoinColumn(name = "parent_comment_seq")
26 | var parent: ClubBoardComment ?= null,
27 |
28 | var depth: Long,
29 |
30 | var deleteFlag: Boolean ?= false,
31 |
32 | ) : BaseEntity() {
33 |
34 | // 직전 하위 뎁스의 댓글 개수만 보여줌
35 | @Formula("(select count(*) from club_board_comment cac where cac.parent_comment_seq = seq and cac.depth = depth+1)")
36 | var subCommentCnt: Long ?= null
37 |
38 | // 모든 하위 뎁스의 댓글 개수만 보여줌
39 | @Formula("(select count(*) from club_board_comment cac where cac.parent_comment_seq = seq and cac.depth > depth)")
40 | var totalSubCommentCnt: Long ?= null
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/board/comment/ClubBoardCommentCTE.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.board.comment
2 |
3 | import com.blazebit.persistence.CTE
4 | import com.taskforce.superinvention.app.domain.BaseEntity
5 | import com.taskforce.superinvention.app.domain.club.album.ClubAlbum
6 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
7 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
8 | import javax.persistence.Entity
9 | import javax.persistence.FetchType
10 | import javax.persistence.JoinColumn
11 | import javax.persistence.ManyToOne
12 |
13 | @CTE
14 | @Entity
15 | class ClubBoardCommentCTE(
16 |
17 | var content: String,
18 |
19 | @ManyToOne(fetch = FetchType.LAZY)
20 | @JoinColumn(name="parent_comment_seq")
21 | var parent: ClubBoardComment?,
22 |
23 | @ManyToOne(fetch = FetchType.LAZY)
24 | @JoinColumn(name="club_user_seq")
25 | var clubUser: ClubUser,
26 |
27 | @ManyToOne(fetch = FetchType.LAZY)
28 | @JoinColumn(name="club_board_seq")
29 | var clubBoard: ClubBoard,
30 |
31 | var depth: Long,
32 |
33 | var subCommentCnt: Long?,
34 |
35 | var deleteFlag: Boolean ?= false,
36 |
37 | ): BaseEntity()
38 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/board/img/ClubBoardImg.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.board.img
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
5 | import javax.persistence.Entity
6 | import javax.persistence.FetchType
7 | import javax.persistence.JoinColumn
8 | import javax.persistence.ManyToOne
9 |
10 | @Entity
11 | class ClubBoardImg(
12 |
13 | @ManyToOne( fetch = FetchType.LAZY)
14 | @JoinColumn(name = "club_board_seq")
15 | var clubBoard: ClubBoard,
16 |
17 | var imgUrl : String,
18 |
19 | var imgName: String,
20 |
21 | var displayOrder: Long?,
22 |
23 | var deleteFlag: Boolean
24 | ): BaseEntity()
25 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/board/img/ClubBoardImgRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.board.img
2 |
3 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
4 | import com.taskforce.superinvention.app.domain.club.board.comment.ClubBoardComment
5 | import com.taskforce.superinvention.app.domain.club.board.comment.ClubBoardCommentRepositoryCustom
6 | import org.springframework.data.jpa.repository.JpaRepository
7 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
8 | import org.springframework.stereotype.Repository
9 |
10 | interface ClubBoardImgRepository : JpaRepository, ClubBoardImgRepositoryCustom {
11 | fun findByClubBoard(clubBoard: ClubBoard): List
12 | fun findBySeqIn(clubBoardSeqList: List): List
13 | }
14 |
15 | interface ClubBoardImgRepositoryCustom {
16 | fun findByClubBoardOrderByOrderAsc(clubBoard: ClubBoard): List
17 | }
18 |
19 | @Repository
20 | class ClubBoardImgRepositoryImpl: ClubBoardImgRepositoryCustom,
21 | QuerydslRepositorySupport(ClubBoardImg::class.java) {
22 |
23 | override fun findByClubBoardOrderByOrderAsc(clubBoard: ClubBoard): List {
24 | val clubBoardImg = QClubBoardImg.clubBoardImg
25 |
26 | return from(clubBoardImg)
27 | .where(
28 | clubBoardImg.clubBoard.eq(clubBoard),
29 | clubBoardImg.deleteFlag.isFalse,
30 | )
31 | .orderBy(clubBoardImg.displayOrder.asc())
32 | .fetch()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/board/like/ClubBoardLike.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.board.like
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
5 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
6 | import javax.persistence.*
7 |
8 | @Entity
9 | class ClubBoardLike(
10 |
11 | @ManyToOne(fetch = FetchType.LAZY)
12 | @JoinColumn(name = "club_board_seq")
13 | val clubBoard: ClubBoard,
14 |
15 | @ManyToOne(fetch = FetchType.LAZY)
16 | @JoinColumn(name= "club_user_seq")
17 | val clubUser: ClubUser
18 |
19 | ): BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/board/like/ClubBoardLikeRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.board.like
2 |
3 | import com.querydsl.core.types.dsl.BooleanExpression
4 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
5 | import com.taskforce.superinvention.app.domain.club.board.QClubBoard
6 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
7 | import org.springframework.data.jpa.repository.JpaRepository
8 | import org.springframework.data.jpa.repository.Query
9 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
10 | import org.springframework.stereotype.Repository
11 |
12 | interface ClubBoardLikeRepository: JpaRepository, ClubBoardLikeRepositoryCustom {
13 | fun findByClubBoardAndClubUser(board: ClubBoard, clubUser: ClubUser): ClubBoardLike?
14 | fun findByClubBoardIn(clubBoardList: List): List
15 | }
16 |
17 | interface ClubBoardLikeRepositoryCustom {
18 | fun getClubBoardLikeCnt(clubBoard: ClubBoard): Long
19 | }
20 |
21 | @Repository
22 | class ClubBoardLikeRepositoryImpl: ClubBoardLikeRepositoryCustom,
23 | QuerydslRepositorySupport(ClubBoard::class.java){
24 |
25 | override fun getClubBoardLikeCnt(clubBoard: ClubBoard): Long {
26 | val clubBoardLike = QClubBoardLike.clubBoardLike
27 |
28 | val query = from(clubBoardLike)
29 | .where(eqSeq(clubBoardLike.clubBoard, clubBoard))
30 |
31 | return query.fetchCount()
32 | }
33 |
34 | private fun eqSeq(clubBoard1: QClubBoard, clubBoard2: ClubBoard): BooleanExpression
35 | = clubBoard1.seq.eq(clubBoard2.seq)
36 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/user/ClubUser.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.user
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.Club
5 | import com.taskforce.superinvention.app.domain.role.ClubUserRole
6 | import com.taskforce.superinvention.app.domain.user.User
7 | import javax.persistence.*
8 |
9 | @Entity
10 | class ClubUser(
11 | @ManyToOne(fetch = FetchType.LAZY)
12 | @JoinColumn(name = "club_seq")
13 | var club: Club,
14 |
15 | @ManyToOne(fetch = FetchType.LAZY)
16 | @JoinColumn(name = "user_seq")
17 | var user: User,
18 |
19 | var isLiked: Boolean?
20 | ) : BaseEntity() {
21 |
22 | constructor(club: Club, user: User)
23 | : this(club, user, false)
24 |
25 | @OneToMany
26 | @JoinColumn(name = "club_user_seq")
27 | lateinit var clubUserRoles: MutableSet
28 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/club/user/ClubUserService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.club.user
2 |
3 | import com.taskforce.superinvention.app.domain.role.Role
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import com.taskforce.superinvention.app.web.dto.club.ClubUserStatusDto
6 | import com.taskforce.superinvention.common.exception.InvalidInputException
7 | import com.taskforce.superinvention.common.exception.club.UserIsNotClubMemberException
8 | import org.springframework.stereotype.Service
9 | import org.springframework.transaction.annotation.Transactional
10 |
11 | @Service
12 | class ClubUserService(
13 | private val clubUserRepository: ClubUserRepository
14 | ) {
15 |
16 | // 클럽에서의 유저 상태 표시
17 | @Transactional
18 | fun getClubUserDetails(user: User?, clubSeq: Long): ClubUserStatusDto? {
19 | if(user == null) {
20 | return null
21 | }
22 |
23 | val clubUser = clubUserRepository.findClubUserWithRole(clubSeq, user)
24 |
25 | return clubUser?.let ( ::ClubUserStatusDto )
26 | }
27 |
28 | fun getValidClubUser(clubSeq: Long, user: User): ClubUser {
29 | return clubUserRepository.findByClubSeqAndUser(clubSeq, user)
30 | ?: throw UserIsNotClubMemberException()
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/FileService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common
2 |
3 | import com.taskforce.superinvention.common.util.aws.s3.AwsS3Mo
4 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
5 | import org.springframework.stereotype.Service
6 | import org.springframework.web.multipart.MultipartFile
7 |
8 | @Service
9 | class FileService (
10 | private val awsS3Mo: AwsS3Mo,
11 | ){
12 | companion object {
13 | const val TEMP_IMG_DIR_PATH = "temp/img"
14 | }
15 |
16 | fun fileTempSave(multipartFile: MultipartFile): S3Path {
17 | return awsS3Mo.uploadFileWithUUID(multipartFile, TEMP_IMG_DIR_PATH)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/ImageFormat.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image
2 |
3 | enum class ImageFormat {
4 | JPEG, JPG, PNG, GIF, WEBP;
5 |
6 | companion object {
7 | private val map = values()
8 | fun extensionOf(value: String): ImageFormat? = values().find { it.name == value.toUpperCase() }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/ImageService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.resize.strategy.ImageResizeStrategyLocator
4 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
5 | import com.taskforce.superinvention.common.exception.InvalidInputException
6 | import com.taskforce.superinvention.common.util.aws.s3.AwsS3Mo
7 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
8 | import com.taskforce.superinvention.common.util.file.FileMo
9 | import org.apache.commons.io.FilenameUtils
10 | import org.springframework.stereotype.Service
11 | import org.springframework.web.multipart.MultipartFile
12 | import java.io.File
13 |
14 | @Service
15 | class ImageService(
16 | private val awsS3Mo: AwsS3Mo,
17 | private val imageResizeStrategyLocator: ImageResizeStrategyLocator
18 | ) {
19 | companion object {
20 | const val TEMP_IMG_DIR_PATH = "temp/img"
21 | val invalidInputException = InvalidInputException()
22 | }
23 |
24 | fun fileImageSave(multipartFile: MultipartFile, resize: ResizeDto = ResizeDto()): S3Path {
25 | val file = FileMo.convertMultiPartToFile(multipartFile)
26 |
27 | if(resize.width != null && resize.height != null) {
28 | return awsS3Mo.uploadFileWithUUID(resizeImage(file, resize), TEMP_IMG_DIR_PATH)
29 | }
30 |
31 | return awsS3Mo.uploadFileWithUUID(file, TEMP_IMG_DIR_PATH)
32 | }
33 |
34 | fun resizeImage(file: File, resize: ResizeDto): File {
35 | val extension = FilenameUtils.getExtension(file.name)
36 |
37 | val format: ImageFormat = ImageFormat.extensionOf(extension)
38 | ?: throw invalidInputException
39 |
40 | return imageResizeStrategyLocator.getStrategy(format)
41 | .resize(file, resize)
42 | .absoluteFile
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/ImageResizeService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.webp.convert.WebpConvertService
4 | import com.taskforce.superinvention.common.exception.InvalidInputException
5 | import org.springframework.stereotype.Service
6 |
7 | @Service
8 | class ImageResizeService(
9 | private val webpConversionService: WebpConvertService,
10 | ) {
11 |
12 | companion object {
13 | val invalidInputException = InvalidInputException()
14 | }
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/strategy/GifResizeStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize.strategy
2 |
3 | import com.drew.imaging.ImageMetadataReader
4 | import com.sksamuel.scrimage.ImmutableImage
5 | import com.sksamuel.scrimage.nio.GifWriter
6 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
7 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
8 | import com.taskforce.superinvention.common.util.file.image.gif.GifMo
9 | import org.springframework.stereotype.Service
10 | import java.io.File
11 |
12 | @Service
13 | class GifResizeStrategy: ImageResizeStrategy {
14 |
15 | override fun identify(imageFormat: ImageFormat): Boolean {
16 | return imageFormat == ImageFormat.GIF
17 | }
18 |
19 | override fun resize(file: File, resize: ResizeDto): File {
20 | val metadata = ImageMetadataReader.readMetadata(file)
21 | return if(GifMo.isAnimated(metadata)) {
22 | file
23 | } else {
24 | ImmutableImage
25 | .loader()
26 | .fromFile(file)
27 | .scaleTo(resize.width!!.toInt(), resize.height!!.toInt())
28 | .output(GifWriter.Default, File.createTempFile("s3-img", file.name))
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/strategy/ImageResizeStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize.strategy
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
4 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
5 | import java.io.File
6 |
7 | interface ImageResizeStrategy {
8 | fun identify(imageFormat: ImageFormat): Boolean
9 | fun resize(file: File, resize: ResizeDto): File
10 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/strategy/ImageResizeStrategyLocator.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize.strategy
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
4 | import com.taskforce.superinvention.common.exception.common.ImplementationIsNotSupported
5 | import org.springframework.stereotype.Service
6 |
7 | @Service
8 | class ImageResizeStrategyLocator(
9 | private val imageResizeStrategy: List
10 | ) {
11 |
12 | fun getStrategy(imageFormat: ImageFormat): ImageResizeStrategy {
13 | return imageResizeStrategy.find { service -> service.identify(imageFormat) }
14 | ?: throw ImplementationIsNotSupported()
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/strategy/JpgResizeStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize.strategy
2 |
3 | import com.sksamuel.scrimage.ImmutableImage
4 | import com.sksamuel.scrimage.nio.JpegWriter
5 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
6 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
7 | import org.springframework.stereotype.Service
8 | import java.io.File
9 |
10 | @Service
11 | class JpgResizeStrategy: ImageResizeStrategy {
12 |
13 | override fun identify(imageFormat: ImageFormat): Boolean {
14 | return imageFormat == ImageFormat.JPEG ||
15 | imageFormat == ImageFormat.JPG
16 | }
17 |
18 | override fun resize(file: File, resize: ResizeDto): File {
19 | return ImmutableImage
20 | .loader()
21 | .fromFile(file)
22 | .scaleTo(resize.width!!.toInt(), resize.height!!.toInt())
23 | .output(JpegWriter.Default, File.createTempFile("s3-img", file.name))
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/strategy/PngResizeStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize.strategy
2 |
3 | import com.sksamuel.scrimage.ImmutableImage
4 | import com.sksamuel.scrimage.nio.GifWriter
5 | import com.sksamuel.scrimage.nio.PngWriter
6 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
7 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
8 | import org.springframework.stereotype.Service
9 | import java.io.File
10 |
11 | @Service
12 | class PngResizeStrategy: ImageResizeStrategy {
13 |
14 | override fun identify(imageFormat: ImageFormat): Boolean {
15 | return imageFormat == ImageFormat.PNG
16 | }
17 |
18 | override fun resize(file: File, resize: ResizeDto): File {
19 | return ImmutableImage
20 | .loader()
21 | .fromFile(file)
22 | .scaleTo(resize.width!!.toInt(), resize.height!!.toInt())
23 | .output(PngWriter.NoCompression, File.createTempFile("s3-img", file.name))
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/resize/strategy/WebpResizeStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.resize.strategy
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
4 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
5 | import org.springframework.stereotype.Service
6 | import java.io.File
7 |
8 | @Service
9 | class WebpResizeStrategy: ImageResizeStrategy {
10 |
11 | override fun identify(imageFormat: ImageFormat): Boolean {
12 | return imageFormat == ImageFormat.WEBP
13 | }
14 |
15 | override fun resize(file: File, resize: ResizeDto): File {
16 | // @Todo webp는 resizing 하지 않음
17 | return file
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/WebpCompressionParam.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert
2 |
3 | data class WebpCompressionParam(
4 | val q: Int = -1 , // RGB 채널 압축 여부 ( 0 ~ 6 )
5 | val m: Int = -1, // 압축 방식 지정 ( 0 ~ 6 ) - 높을 수록 고효율 압축, 시간 증가
6 | val lossless: Boolean = false, // 손실 압축 여부
7 | )
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/WebpConvertService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
4 | import com.taskforce.superinvention.app.domain.common.image.webp.convert.strategy.WebpConvertStrategyLocator
5 | import com.taskforce.superinvention.common.config.async.AsyncConfig
6 | import com.taskforce.superinvention.common.exception.InvalidInputException
7 | import com.taskforce.superinvention.common.util.aws.s3.AwsS3Mo
8 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
9 | import org.apache.commons.io.FilenameUtils
10 | import org.springframework.scheduling.annotation.Async
11 | import org.springframework.stereotype.Service
12 | import java.io.File
13 |
14 | @Service
15 | class WebpConvertService(
16 | private val strategyLocator: WebpConvertStrategyLocator,
17 | private val awsS3Mo: AwsS3Mo
18 | ) {
19 |
20 | companion object {
21 | val invalidInputException = InvalidInputException()
22 | }
23 |
24 | // s3 상의 이미지 경로에 /이미지.webp 형태의 압축본 생성
25 | @Async(AsyncConfig.WEBP_CONVERSION)
26 | fun convertToWebP(s3Path: S3Path) {
27 | val folderPath = s3Path.folderPath()
28 |
29 | val fileName = FilenameUtils.removeExtension(s3Path.fileName)
30 | val extension = FilenameUtils.getExtension(s3Path.fileName)
31 | val s3File = awsS3Mo.getObjectAsFile(s3Path)
32 |
33 | val format: ImageFormat = ImageFormat.extensionOf(extension)
34 | ?: throw invalidInputException
35 |
36 | val convertStrategy = strategyLocator.getStrategy(format)
37 | val convertedFile: File = convertStrategy.convert(fileName, s3File, WebpCompressionParam())
38 |
39 | awsS3Mo.uploadFile(convertedFile, folderPath)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/handler/WebpAnimatedWriter.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert.handler
2 |
3 | import java.io.File
4 |
5 | class WebpAnimatedWriter(
6 | private var q: Int = -1,
7 | private var m: Int = -1,
8 | private var mixed: Boolean = true,
9 | private var lossy: Boolean = true,
10 | private var multiThread: Boolean = true,
11 | ) {
12 |
13 | companion object {
14 | val DEFAULT: WebpAnimatedWriter = WebpAnimatedWriter()
15 | val LOSSLESS_COMPRESSION: WebpAnimatedWriter = DEFAULT.withLossless()
16 | }
17 |
18 | private val handler = Gif2WebpHandler()
19 |
20 | fun withQ(q: Int): WebpAnimatedWriter {
21 | require(q >= 0) { "q must be between 0 and 100" }
22 | require(q <= 100) { "q must be between 0 and 100" }
23 | return WebpAnimatedWriter(q, m, lossy)
24 | }
25 |
26 | fun withM(m: Int): WebpAnimatedWriter {
27 | require(m >= 0) { "m must be between 0 and 6" }
28 | require(m <= 6) { "m must be between 0 and 6" }
29 | return WebpAnimatedWriter(q, m, lossy)
30 | }
31 |
32 | fun withLossless(): WebpAnimatedWriter {
33 | return WebpAnimatedWriter(q, m, false)
34 | }
35 |
36 | fun writeAsByteArray(gifImage: File): ByteArray {
37 | return handler.convert(gifImage, q, m, lossy, mixed, multiThread)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/handler/WebpHandler.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert.handler
2 |
3 | import org.apache.commons.lang3.SystemUtils
4 | import java.io.IOException
5 | import java.nio.file.Files
6 | import java.nio.file.Path
7 | import java.nio.file.StandardCopyOption
8 | import java.util.*
9 | import java.util.concurrent.TimeUnit
10 |
11 | abstract class WebpHandler {
12 |
13 | companion object {
14 | fun createPlaceholder(name: String): Path {
15 | return Files.createTempFile(name, "binary")
16 | }
17 |
18 | fun installBinary(output: Path, vararg sources: String) {
19 | for (source in sources) {
20 | val inputStream = WebpHandler::class.java.getResourceAsStream(source)
21 | if (inputStream != null) {
22 | Files.copy(inputStream, output, StandardCopyOption.REPLACE_EXISTING)
23 | inputStream.close()
24 | if (!SystemUtils.IS_OS_WINDOWS) {
25 | setExecutable(output)
26 | }
27 | return
28 | }
29 | }
30 | throw IOException("Could not locate webp binary at " + sources.contentToString())
31 | }
32 |
33 | private fun setExecutable(output: Path): Boolean {
34 | return try {
35 | ProcessBuilder("chmod", "+x", output.toAbsolutePath().toString())
36 | .start()
37 | .waitFor(30, TimeUnit.SECONDS)
38 | } catch (e: InterruptedException) {
39 | throw IOException(e)
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/strategy/Jpg2WebpStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert.strategy
2 |
3 | import com.sksamuel.scrimage.ImmutableImage
4 | import com.sksamuel.scrimage.webp.WebpWriter
5 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
6 | import com.taskforce.superinvention.app.domain.common.image.webp.convert.WebpCompressionParam
7 | import com.taskforce.superinvention.common.util.kakao.KakaoOAuth
8 | import org.apache.commons.io.FileUtils
9 | import org.slf4j.Logger
10 | import org.slf4j.LoggerFactory
11 | import org.springframework.stereotype.Service
12 | import java.io.File
13 | import java.io.FileOutputStream
14 | import java.io.IOException
15 |
16 | @Service
17 | class Jpg2WebpStrategy: WebpConvertStrategy {
18 |
19 | companion object {
20 | val LOG: Logger = LoggerFactory.getLogger(Jpg2WebpStrategy::class.java)
21 | }
22 |
23 | override fun identify(imageFormat: ImageFormat): Boolean {
24 | return imageFormat == ImageFormat.JPG ||
25 | imageFormat == ImageFormat.JPEG
26 | }
27 |
28 | override fun convert(fileName: String, file: File, param: WebpCompressionParam): File {
29 |
30 | return try {
31 | ImmutableImage.loader()
32 | .fromFile(file)
33 | .output(WebpWriter.DEFAULT, File("${fileName}.webp"))
34 | } catch (e: IOException) {
35 | LOG.error("JPG -> WebP간 변환 실패, 컨버팅을 취소합니다. {}", e)
36 | file
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/strategy/Png2WebpStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert.strategy
2 |
3 | import com.sksamuel.scrimage.ImmutableImage
4 | import com.sksamuel.scrimage.webp.WebpWriter
5 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
6 | import com.taskforce.superinvention.app.domain.common.image.webp.convert.WebpCompressionParam
7 | import org.apache.commons.io.FileUtils
8 | import org.slf4j.Logger
9 | import org.slf4j.LoggerFactory
10 | import org.springframework.stereotype.Service
11 | import java.io.File
12 | import java.io.FileOutputStream
13 | import java.io.IOException
14 |
15 | @Service
16 | class Png2WebpStrategy: WebpConvertStrategy {
17 |
18 | companion object {
19 | val LOG: Logger = LoggerFactory.getLogger(Png2WebpStrategy::class.java)
20 | }
21 |
22 | override fun identify(imageFormat: ImageFormat): Boolean {
23 | return imageFormat == ImageFormat.PNG
24 | }
25 |
26 | override fun convert(fileName: String, file: File, param: WebpCompressionParam): File {
27 |
28 | return try {
29 | ImmutableImage.loader()
30 | .fromFile(file)
31 | .output(WebpWriter.DEFAULT, File("${fileName}.webp"))
32 | } catch (e: IOException) {
33 | LOG.error("PNG -> WebP간 변환 실패, 컨버팅을 취소합니다. {}", e)
34 | file
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/strategy/WebpConvertStrategy.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert.strategy
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
4 | import com.taskforce.superinvention.app.domain.common.image.webp.convert.WebpCompressionParam
5 | import java.io.File
6 |
7 | interface WebpConvertStrategy {
8 | fun identify(imageFormat: ImageFormat): Boolean
9 | fun convert(fileName: String, file: File, param: WebpCompressionParam): File
10 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/common/image/webp/convert/strategy/WebpConvertStrategyLocator.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.common.image.webp.convert.strategy
2 |
3 | import com.taskforce.superinvention.app.domain.common.image.ImageFormat
4 | import com.taskforce.superinvention.common.exception.common.ImplementationIsNotSupported
5 | import org.springframework.stereotype.Service
6 |
7 | @Service
8 | class WebpConvertStrategyLocator(
9 | private val webpConvertStrategy: List
10 | ) {
11 |
12 | fun getStrategy(imageFormat: ImageFormat): WebpConvertStrategy {
13 | return webpConvertStrategy.find { service -> service.identify(imageFormat) }
14 | ?: throw ImplementationIsNotSupported()
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/ClubInterest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.Club
5 | import com.taskforce.superinvention.app.domain.interest.interest.Interest
6 | import com.taskforce.superinvention.app.domain.interest.interestGroup.InterestGroup
7 | import javax.persistence.Entity
8 | import javax.persistence.FetchType
9 | import javax.persistence.JoinColumn
10 | import javax.persistence.ManyToOne
11 |
12 | @Entity
13 | class ClubInterest(
14 | @ManyToOne(fetch = FetchType.LAZY)
15 | @JoinColumn(name = "club_seq")
16 | var club: Club,
17 | @ManyToOne(fetch = FetchType.LAZY)
18 | @JoinColumn(name = "interest_seq")
19 | var interest: Interest,
20 | var priority: Long
21 | ) : BaseEntity() {
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interest/Interest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interest
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.interest.interestGroup.InterestGroup
5 | import javax.persistence.Entity
6 | import javax.persistence.FetchType
7 | import javax.persistence.JoinColumn
8 | import javax.persistence.ManyToOne
9 |
10 | @Entity
11 | class Interest(
12 | var name: String,
13 |
14 | @ManyToOne(fetch = FetchType.LAZY)
15 | @JoinColumn(name = "interest_group_seq")
16 | var interestGroup: InterestGroup
17 | ) : BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interest/InterestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interest
2 |
3 | import com.taskforce.superinvention.app.domain.interest.interestGroup.SimpleInterestGroupDto
4 |
5 | class InterestDto {
6 | var seq: Long?
7 | var name: String
8 | var interestGroup: SimpleInterestGroupDto
9 |
10 | constructor(seq: Long?, name: String, interestGroup: SimpleInterestGroupDto) {
11 | this.seq = seq
12 | this.name = name
13 | this.interestGroup = interestGroup
14 | }
15 |
16 | constructor(interest: Interest) {
17 | this.seq = interest.seq
18 | this.name = interest.name
19 | this.interestGroup = SimpleInterestGroupDto(interest.interestGroup)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interest/InterestRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interest
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | interface InterestRepository : JpaRepository,
8 | InterestRepositoryCustom {
9 | }
10 |
11 | interface InterestRepositoryCustom {
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interest/InterestRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interest
2 |
3 | import com.querydsl.core.types.Projections
4 | import com.querydsl.jpa.impl.JPAQueryFactory
5 | import com.taskforce.superinvention.app.domain.interest.interest.QInterest.interest
6 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
7 | import org.springframework.stereotype.Repository
8 |
9 | @Repository
10 | class InterestRepositoryImpl(
11 | private val query: JPAQueryFactory
12 | ) : QuerydslRepositorySupport(Interest::class.java),
13 | InterestRepositoryCustom
14 | {
15 | fun findBySeq(seq: Long): Interest {
16 | return from(interest)
17 | .where(interest.seq.eq(seq))
18 | .fetchOne()
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interest/InterestService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interest
2 |
3 | import com.taskforce.superinvention.app.domain.user.userInterest.UserInterestRepository
4 | import com.taskforce.superinvention.common.exception.BizException
5 | import org.springframework.http.HttpStatus
6 | import org.springframework.stereotype.Service
7 | import org.springframework.transaction.annotation.Transactional
8 | import java.lang.IllegalArgumentException
9 |
10 | @Service
11 | class InterestService(
12 | private val interestRepository: InterestRepository,
13 | private val userInterestRepository: UserInterestRepository
14 | ) {
15 | fun findBySeq(seq: Long):Interest = interestRepository.findById(seq).orElseThrow{IllegalArgumentException()}
16 |
17 | @Transactional
18 | fun checkBeforeConvertClubInterest(interestList: Iterable): Iterable {
19 | if (!isInEqualsInterestGroup(interestList)) throw BizException("하나의 관심사 그룹에 속하는 관심사들만 등록할 수 있습니다", HttpStatus.BAD_REQUEST)
20 | return interestList
21 | }
22 |
23 | @Transactional
24 | fun isInEqualsInterestGroup(interests: Iterable): Boolean {
25 | return interests.map { it.interestGroup }.distinctBy { it.seq }.size == 1
26 | }
27 |
28 | @Transactional
29 | fun findBySeqList(seqList: Iterable): List = interestRepository.findAllById(seqList)
30 |
31 |
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interestGroup/InterestGroup.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interestGroup
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.interest.interest.Interest
5 | import javax.persistence.Entity
6 | import javax.persistence.OneToMany
7 |
8 | @Entity
9 | class InterestGroup (
10 | var name: String
11 | ) : BaseEntity() {
12 | @OneToMany(mappedBy = "interestGroup")
13 | lateinit var interestList: List
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interestGroup/InterestGroupDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interestGroup
2 |
3 | import com.taskforce.superinvention.app.domain.interest.interest.Interest
4 | import com.taskforce.superinvention.app.domain.interest.interest.InterestDto
5 |
6 | class InterestGroupDto {
7 | var name: String
8 | var groupSeq: Long?
9 | var interestList: List
10 |
11 | constructor(group: InterestGroup, interestList: List ) {
12 | this.name = group.name
13 | this.groupSeq = group.seq
14 | this.interestList = interestList.map { interest -> InterestDto(interest.seq, interest.name, SimpleInterestGroupDto(interest.interestGroup))}.toMutableList()
15 | }
16 |
17 | constructor(groupSeq: Long, name: String, interestList: List ) {
18 | this.name = name
19 | this.groupSeq = groupSeq
20 | this.interestList = interestList
21 | }
22 | }
23 |
24 | data class SimpleInterestGroupDto(
25 | val seq: Long,
26 | val name: String
27 | ) {
28 | constructor(interestGroup:InterestGroup): this(interestGroup.seq!!, interestGroup.name)
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interestGroup/InterestGroupRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interestGroup
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | interface InterestGroupRepository : JpaRepository,
8 | InterestGroupRepositoryCustom
9 |
10 | interface InterestGroupRepositoryCustom {
11 | fun findAllInterestGroupList(): List
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interestGroup/InterestGroupRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interestGroup
2 |
3 | import com.querydsl.core.group.GroupBy.groupBy
4 | import com.querydsl.core.group.GroupBy.list
5 | import com.querydsl.jpa.impl.JPAQueryFactory
6 | import com.taskforce.superinvention.app.domain.interest.interest.Interest
7 | import com.taskforce.superinvention.app.domain.interest.interest.QInterest.interest
8 | import com.taskforce.superinvention.app.domain.interest.interestGroup.QInterestGroup.interestGroup
9 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
10 | import org.springframework.stereotype.Repository
11 |
12 | @Repository
13 | class InterestGroupRepositoryImpl(
14 | private val query: JPAQueryFactory
15 | ): InterestGroupRepositoryCustom,
16 | QuerydslRepositorySupport(InterestGroup::class.java) {
17 |
18 | override fun findAllInterestGroupList(): MutableList {
19 |
20 | val groups: MutableMap> = query.
21 | select(interestGroup.seq, interestGroup.name, interest.seq, interest.name).
22 | from(interestGroup).
23 | innerJoin(interestGroup.interestList, interest).
24 | transform(groupBy(interestGroup).`as`(list(interest)))
25 |
26 | return groups.map { interestGroup ->
27 | InterestGroupDto(interestGroup.key, interestGroup.value)
28 | }.toMutableList()
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/interest/interestGroup/InterestGroupService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interestGroup
2 |
3 | import org.springframework.stereotype.Service
4 |
5 | @Service
6 | class InterestGroupService(
7 | private val interestGroupRepo: InterestGroupRepository
8 | ) {
9 |
10 | fun getInterestList(): List {
11 | val result = interestGroupRepo.findAllInterestGroupList()
12 | return result
13 | }
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/meeting/Meeting.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.meeting
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.Club
5 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
6 | import java.time.LocalDateTime
7 | import javax.persistence.*
8 |
9 | @Entity
10 | class Meeting(
11 | var title: String,
12 | var content: String,
13 | var startTimestamp: LocalDateTime,
14 | var endTimestamp: LocalDateTime,
15 | @ManyToOne
16 | var club: Club,
17 | var deleteFlag: Boolean,
18 | var maximumNumber: Int?,
19 | @ManyToOne
20 | var regClubUser: ClubUser,
21 | var region: String?,
22 | var regionURL: String?,
23 | var cost: Int?
24 | ) : BaseEntity() {
25 | @OneToMany(mappedBy = "meeting", fetch = FetchType.EAGER)
26 | @OrderBy("deleteFlag desc")
27 | var meetingApplications: List = listOf()
28 |
29 | fun isOpen(): Boolean = endTimestamp.isAfter(LocalDateTime.now())
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/meeting/MeetingApplication.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.meeting
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
5 | import javax.persistence.*
6 |
7 | @Entity
8 | class MeetingApplication(
9 | @ManyToOne
10 | @JoinColumn(name = "club_user_seq")
11 | var clubUser: ClubUser,
12 |
13 | @ManyToOne
14 | @JoinColumn(name = "meeting_seq")
15 | var meeting: Meeting,
16 | var deleteFlag: Boolean
17 | ) : BaseEntity(){
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/region/ClubRegion.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.region
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.Club
5 | import com.taskforce.superinvention.app.domain.region.Region
6 | import javax.persistence.Entity
7 | import javax.persistence.FetchType
8 | import javax.persistence.ManyToOne
9 |
10 | @Entity
11 | class ClubRegion(
12 | @ManyToOne(fetch = FetchType.LAZY)
13 | var club:Club,
14 |
15 | @ManyToOne(fetch = FetchType.LAZY)
16 | var region: Region,
17 | var priority: Long
18 | ) : BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/region/ClubRegionRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.region
2 |
3 | import com.taskforce.superinvention.app.domain.club.Club
4 | import org.springframework.data.jpa.repository.JpaRepository
5 | import org.springframework.stereotype.Repository
6 |
7 | @Repository
8 | interface ClubRegionRepository : JpaRepository {
9 | fun findByClub(club: Club): List
10 | fun findByClubSeq(clubSeq: Long): List?
11 | fun findByClubSeqIn(clubSeq: List): List
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/region/Region.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.region
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore
4 | import com.taskforce.superinvention.app.domain.BaseEntity
5 | import javax.persistence.*
6 |
7 | @Entity
8 | class Region(
9 |
10 | @ManyToOne(fetch = FetchType.LAZY)
11 | @JoinColumn(name="super_region_seq", foreignKey = ForeignKey(ConstraintMode.NO_CONSTRAINT))
12 | @JsonIgnore
13 | var superRegion: Region?,
14 | var name: String,
15 | var superRegionRoot: String,
16 | var level: Long
17 |
18 | ): BaseEntity() {
19 |
20 | @OneToMany
21 | @JoinColumn(name="super_region_seq", foreignKey = ForeignKey(ConstraintMode.NO_CONSTRAINT))
22 | var subRegions: List = listOf()
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/region/RegionRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.region
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
5 | import org.springframework.stereotype.Repository
6 |
7 | @Repository
8 | interface RegionRepository : JpaRepository, RegionRepositoryCustom {
9 |
10 | }
11 |
12 | interface RegionRepositoryCustom {
13 | fun findByLevelWithSubRegions(): List
14 | }
15 |
16 | @Repository
17 | class RegionRepositoryImpl: RegionRepositoryCustom,
18 | QuerydslRepositorySupport(Region::class.java) {
19 |
20 | override fun findByLevelWithSubRegions(): List {
21 | val superRegion = QRegion.region
22 | val subRegion = QRegion("r2")
23 |
24 | val result = from(superRegion)
25 | .join(superRegion.subRegions, subRegion).fetchJoin()
26 | .where(superRegion.superRegion.isNull)
27 |
28 | val fetch = result.fetch().distinct()
29 | return fetch
30 | }
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/region/RegionService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.region
2 |
3 | import com.taskforce.superinvention.app.web.dto.region.*
4 | import com.taskforce.superinvention.common.exception.BizException
5 | import org.springframework.http.HttpStatus
6 | import org.springframework.stereotype.Service
7 | import org.springframework.transaction.annotation.Transactional
8 | import java.lang.IllegalArgumentException
9 |
10 | @Service
11 | class RegionService(
12 | val regionRepository: RegionRepository
13 | ) {
14 | @Transactional
15 | fun findAllRegionDtoList(): List {
16 | val regions = regionRepository.findByLevelWithSubRegions().map { of(it, it.subRegions) }
17 | return regions
18 | }
19 |
20 | fun findBySeq(seq: Long): Region = regionRepository.findById(seq).orElseThrow{IllegalArgumentException()}
21 |
22 | @Transactional
23 | fun checkBeforeConvertClubRegion(regions: Iterable): Iterable {
24 | if (!isInEqualsSuperRegion(regions)) throw BizException("하나의 도/(특별)시 에 속하는 지역 끼리만 등록할 수 있습니다", HttpStatus.BAD_REQUEST)
25 | return regions
26 | }
27 |
28 | @Transactional
29 | fun isInEqualsSuperRegion(regions: Iterable): Boolean {
30 | return regions.map { it.superRegion?: it }.distinctBy { it.seq }.size == 1
31 | }
32 |
33 | @Transactional
34 | fun findBySeqList(seqList: Iterable) = regionRepository.findAllById(seqList)
35 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/ClubUserRole.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
5 | import javax.persistence.*
6 |
7 | @Entity
8 | class ClubUserRole(
9 | @ManyToOne(fetch = FetchType.LAZY)
10 | @JoinColumn(name = "club_user_seq")
11 | var clubUser: ClubUser,
12 |
13 | @ManyToOne(fetch = FetchType.LAZY)
14 | @JoinColumn(name = "role_seq")
15 | var role: Role
16 | ): BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/ClubUserRoleRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import com.taskforce.superinvention.app.domain.club.user.ClubUser
4 | import org.springframework.data.jpa.repository.JpaRepository
5 | import org.springframework.stereotype.Repository
6 |
7 | @Repository
8 | interface ClubUserRoleRepository : JpaRepository {
9 | fun findByClubUser(clubUser: ClubUser): Set
10 | fun findByClubUserIn(clubUsers: Iterable): List
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/Role.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import javax.persistence.*
5 |
6 | @Entity
7 | class Role (
8 | @Enumerated(EnumType.STRING)
9 | var name: RoleName,
10 |
11 | @ManyToOne(fetch = FetchType.LAZY)
12 | @JoinColumn(name = "role_group_seq")
13 | var roleGroup: RoleGroup,
14 |
15 | var level: Int
16 | ): BaseEntity() {
17 |
18 | companion object {
19 | const val NONE = "ROLE_NONE"
20 | const val MEMBER = "ROLE_MEMBER"
21 | const val CLUB_MEMBER = "ROLE_CLUB_MEMBER"
22 | const val MANAGER = "ROLE_MANAGER"
23 | const val MASTER = "ROLE_MASTER"
24 |
25 | private val lookup = RoleName.values().associateBy(RoleName::role)
26 | fun fromRoleName(role: String): RoleName = requireNotNull(lookup[role])
27 | }
28 |
29 | enum class RoleName(
30 | val label: String,
31 | val role : String
32 | ) {
33 | NONE("비회원", Role.NONE),
34 | MEMBER("회원", Role.MEMBER),
35 | CLUB_MEMBER("모임원", Role.CLUB_MEMBER),
36 | MANAGER("매니저", Role.MANAGER),
37 | MASTER("모임장",Role.MASTER)
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/RoleGroup.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import javax.persistence.Entity
5 |
6 | @Entity
7 | class RoleGroup(
8 | var name: String,
9 | var role_type: String
10 | ) : BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/RoleGroupRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | interface RoleGroupRepository : JpaRepository {
8 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/RoleGroupRepositorySupport.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | class RoleGroupRepositorySupport : QuerydslRepositorySupport(RoleGroup::class.java){
8 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/RoleRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | interface RoleRepository : JpaRepository {
8 | fun findByName(roleName: Role.RoleName): Role
9 | fun findBySeqIn(roleSeqList: Set): Set
10 | fun findByNameIn(roleNameList: Set): Set
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/role/RoleRepositorySupport.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.role
2 |
3 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | class RoleRepositorySupport : QuerydslRepositorySupport(Role::class.java)
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/UserDetailsProvider.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user
2 |
3 | import org.slf4j.LoggerFactory
4 | import org.springframework.security.core.userdetails.UserDetails
5 | import org.springframework.security.core.userdetails.UserDetailsService
6 | import org.springframework.stereotype.Service
7 | import org.springframework.transaction.annotation.Transactional
8 |
9 | @Service
10 | class UserDetailsProvider(
11 | private val userRepository: UserRepository
12 | ): UserDetailsService {
13 |
14 | companion object {
15 | val LOG = LoggerFactory.getLogger(UserDetailsProvider::class.java)
16 | }
17 |
18 | @Transactional
19 | override fun loadUserByUsername(userId: String): UserDetails {
20 | val user: User = userRepository.findByUserId(userId)!!
21 |
22 | return org.springframework.security.core.userdetails.User
23 | .withUsername(user.userId)
24 | .password("")
25 | .authorities(user.userRoles)
26 | .accountExpired(false)
27 | .accountLocked(false)
28 | .credentialsExpired(false)
29 | .disabled(false)
30 | .build()
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/UserInfoService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user
2 |
3 | import com.taskforce.superinvention.app.domain.user.userInterest.UserInterestService
4 | import com.taskforce.superinvention.app.domain.user.userRegion.UserRegionService
5 | import com.taskforce.superinvention.app.web.dto.user.info.UserInfoDto
6 | import com.taskforce.superinvention.app.web.dto.user.info.UserInfoInterestDto
7 | import com.taskforce.superinvention.app.web.dto.user.info.UserInfoRegionDto
8 | import org.springframework.stereotype.Service
9 | import org.springframework.transaction.annotation.Transactional
10 |
11 | @Service
12 | class UserInfoService(
13 | private val userRepository: UserRepository,
14 | private val userInterestService : UserInterestService,
15 | private val userRegionService: UserRegionService
16 | ){
17 | @Transactional
18 | fun getUserInfo(userData: User): UserInfoDto {
19 |
20 | val user = userRepository.findByUserId(userData.userId)!!
21 |
22 | // [1] 유저 관심사 조회
23 | val userInfoInterests: List = userInterestService.findUserInterests(user)
24 |
25 | // [2] 유저 관심 지역 조회
26 | val userRegions: List = userRegionService.findUserRegionList(user).userRegions
27 | .map { userRegions -> UserInfoRegionDto(userRegions.priority, userRegions.region) }
28 |
29 | return UserInfoDto(user, userRegions, userInfoInterests)
30 | }
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/UserRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | interface UserRepository : JpaRepository {
8 | fun findByUserId(userId: String?): User?
9 | fun findByUserName(username: String): User?
10 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/UserType.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user
2 |
3 | enum class UserType {
4 | KAKAO
5 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userInterest/UserInterest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userInterest
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.interest.interest.Interest
5 | import com.taskforce.superinvention.app.domain.user.User
6 | import javax.persistence.Entity
7 | import javax.persistence.FetchType
8 | import javax.persistence.JoinColumn
9 | import javax.persistence.ManyToOne
10 |
11 | @Entity
12 | class UserInterest(
13 | @ManyToOne(fetch = FetchType.LAZY)
14 | @JoinColumn(name = "user_seq")
15 | var user: User,
16 | @ManyToOne(fetch = FetchType.LAZY)
17 | @JoinColumn(name = "interest_seq")
18 | var interest: Interest,
19 | var priority: Long
20 | ) : BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userInterest/UserInterestRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userInterest
2 |
3 | import com.taskforce.superinvention.app.domain.interest.interest.QInterest
4 | import com.taskforce.superinvention.app.domain.interest.interestGroup.QInterestGroup
5 | import com.taskforce.superinvention.app.domain.user.User
6 | import org.springframework.data.jpa.repository.JpaRepository
7 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
8 | import org.springframework.stereotype.Repository
9 |
10 | @Repository
11 | interface UserInterestRepository : JpaRepository, UserInterestRepositoryCustom{
12 | fun findByUserOrderByPriority(user: User): List
13 | }
14 |
15 | interface UserInterestRepositoryCustom {
16 | fun findUserInterests(user: User): List
17 | }
18 |
19 | @Repository
20 | class UserInterestRepositoryImpl: UserInterestRepositoryCustom,
21 | QuerydslRepositorySupport(UserInterest::class.java) {
22 |
23 | override fun findUserInterests(user: User): List {
24 | val userInterest = QUserInterest.userInterest
25 | val interest = QInterest.interest
26 | val interestGroup = QInterestGroup.interestGroup
27 |
28 | val query = from(userInterest)
29 | .join(userInterest.interest, interest).fetchJoin()
30 | .join(interest.interestGroup, interestGroup).fetchJoin()
31 | .where(userInterest.user.seq.eq(user.seq))
32 |
33 | return query.fetch()
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userRegion/UserRegion.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userRegion
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.region.Region
5 | import com.taskforce.superinvention.app.domain.user.User
6 | import javax.persistence.Entity
7 | import javax.persistence.FetchType
8 | import javax.persistence.JoinColumn
9 | import javax.persistence.ManyToOne
10 |
11 | @Entity
12 | class UserRegion(
13 | @ManyToOne(fetch = FetchType.LAZY)
14 | @JoinColumn(name="user_seq")
15 | var user: User,
16 | @ManyToOne(fetch = FetchType.LAZY)
17 | @JoinColumn(name="region_seq")
18 | var region: Region,
19 | var priority: Long
20 | ) : BaseEntity()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userRegion/UserRegionRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userRegion
2 |
3 | import com.taskforce.superinvention.app.domain.region.QRegion
4 | import com.taskforce.superinvention.app.domain.user.QUser
5 | import org.springframework.data.jpa.repository.JpaRepository
6 | import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
7 | import org.springframework.stereotype.Repository
8 |
9 | @Repository
10 | interface UserRegionRepository : JpaRepository, UserRegionRepositoryCustom {
11 | fun findByUserSeq(userSeq: Long): List
12 | }
13 |
14 | interface UserRegionRepositoryCustom {
15 | fun findByUserWithRegion(userSeq: Long): List
16 | }
17 |
18 | @Repository
19 | class UserRegionRepositoryImpl: UserRegionRepositoryCustom,
20 | QuerydslRepositorySupport(UserRegion::class.java){
21 |
22 | override fun findByUserWithRegion(userSeq: Long): List {
23 |
24 | val user = QUser.user
25 | val userRegion = QUserRegion.userRegion
26 | val region = QRegion.region
27 |
28 | val query = from(userRegion)
29 | .join(userRegion.user, user).fetchJoin()
30 | .join(userRegion.region, region).fetchJoin()
31 | .where(userRegion.user.seq.eq(userSeq))
32 | return query.fetch()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userRole/UserRole.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userRole
2 |
3 | import com.taskforce.superinvention.app.domain.BaseEntity
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import org.springframework.security.core.GrantedAuthority
6 | import javax.persistence.Entity
7 | import javax.persistence.FetchType
8 | import javax.persistence.JoinColumn
9 | import javax.persistence.ManyToOne
10 |
11 | @Entity
12 | class UserRole(
13 | @ManyToOne(fetch = FetchType.LAZY)
14 | @JoinColumn(name = "user_seq")
15 | var user: User,
16 | var roleName: String
17 | ) : BaseEntity(), GrantedAuthority {
18 |
19 | override fun getAuthority(): String {
20 | return roleName
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userRole/UserRoleRepository.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userRole
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository
4 | import org.springframework.stereotype.Repository
5 |
6 | @Repository
7 | interface UserRoleRepository : JpaRepository {
8 | fun findByUserSeqAndRoleName(userSeq: Long, roleName: String): UserRole?
9 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/domain/user/userRole/UserRoleService.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userRole
2 |
3 | import com.taskforce.superinvention.app.domain.role.Role
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import org.springframework.stereotype.Service
6 |
7 | @Service
8 | class UserRoleService(
9 | val userRoleRepository: UserRoleRepository
10 | ) {
11 |
12 | fun addRole(user: User, roleName: Role.RoleName) {
13 | userRoleRepository.save(UserRole(user, roleName.role))
14 | }
15 |
16 | fun removeRoleIfExist(user: User, roleName: Role.RoleName) {
17 | val userRole = userRoleRepository.findByUserSeqAndRoleName(user.seq!!, roleName.role)
18 |
19 | if(userRole != null) {
20 | userRoleRepository.delete(userRole)
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/common/response/ErrorResponseDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.common.response
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 | import java.lang.RuntimeException
6 |
7 | class ErrorResponseDto(
8 | val httpStatus: HttpStatus,
9 | override val message: String
10 | ) : RuntimeException()
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/common/response/ResponseDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.common.response
2 |
3 |
4 | class ResponseDto (
5 | val data: T,
6 | val message: String = "success"
7 | ) {
8 | companion object {
9 | const val EMPTY = ""
10 | }
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/CommonController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller
2 |
3 | import com.taskforce.superinvention.app.domain.common.FileService
4 | import com.taskforce.superinvention.app.domain.common.image.ImageService
5 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
6 | import com.taskforce.superinvention.app.web.dto.common.image.ResizeDto
7 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
8 | import org.springframework.web.bind.annotation.PostMapping
9 | import org.springframework.web.bind.annotation.RequestMapping
10 | import org.springframework.web.bind.annotation.RestController
11 | import org.springframework.web.multipart.MultipartFile
12 |
13 | @RequestMapping("/common")
14 | @RestController
15 | class CommonController(
16 | private val fileService : FileService,
17 | private val imageService: ImageService
18 | ) {
19 | @PostMapping("/temp/image")
20 | fun imageTempSave(file: MultipartFile, resize: ResizeDto): ResponseDto {
21 | return ResponseDto(data = imageService.fileImageSave(file, resize))
22 | }
23 |
24 | @PostMapping("/temp/file")
25 | fun fileTempSave(file: MultipartFile): ResponseDto {
26 | return ResponseDto(data = fileService.fileTempSave(file))
27 | }
28 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/InterestGroupController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller
2 |
3 | import com.taskforce.superinvention.app.domain.interest.interestGroup.InterestGroupDto
4 | import com.taskforce.superinvention.app.domain.interest.interestGroup.InterestGroupService
5 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
6 | import org.springframework.web.bind.annotation.GetMapping
7 | import org.springframework.web.bind.annotation.RestController
8 |
9 | @RestController
10 | class InterestGroupController(
11 | private val interestGroupService: InterestGroupService
12 | ) {
13 |
14 | @GetMapping("/interestGroup/all")
15 | fun getInterestList(): ResponseDto> {
16 | val result = interestGroupService.getInterestList()
17 | return ResponseDto(data = result)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/club/album/ClubAlbumLikeController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller.club.album
2 |
3 | import com.taskforce.superinvention.app.domain.club.album.like.ClubAlbumLikeService
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
6 | import com.taskforce.superinvention.app.web.dto.club.album.like.ClubAlbumLikeDto
7 | import com.taskforce.superinvention.common.config.argument.resolver.auth.AuthUser
8 | import org.springframework.http.HttpStatus
9 | import org.springframework.web.bind.annotation.*
10 |
11 | @RestController
12 | @RequestMapping("/club/{clubSeq}/album/{clubAlbumSeq}/like")
13 | class ClubAlbumLikeController(
14 | private val clubAlbumLikeService: ClubAlbumLikeService
15 | ) {
16 | @PostMapping
17 | @ResponseStatus(HttpStatus.CREATED)
18 | fun registerClubAlbumLike(@AuthUser user: User,
19 | @PathVariable clubSeq: Long,
20 | @PathVariable clubAlbumSeq: Long): ResponseDto {
21 |
22 | return ResponseDto(data = clubAlbumLikeService.registerClubAlbumLike(user, clubSeq, clubAlbumSeq))
23 | }
24 |
25 | @DeleteMapping
26 | fun deleteClubAlbumLike(@AuthUser user: User,
27 | @PathVariable clubSeq: Long,
28 | @PathVariable clubAlbumSeq: Long): ResponseDto {
29 |
30 | return ResponseDto(data = clubAlbumLikeService.removeClubAlbumLike(user, clubSeq, clubAlbumSeq))
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/club/board/ClubBoardLikeController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller.club.board
2 |
3 | import com.taskforce.superinvention.app.domain.club.board.like.ClubBoardLikeService
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
6 | import com.taskforce.superinvention.app.web.dto.club.board.like.ClubBoardLikeDto
7 | import com.taskforce.superinvention.common.config.argument.resolver.auth.AuthUser
8 | import org.springframework.http.HttpStatus
9 | import org.springframework.web.bind.annotation.*
10 |
11 | @RestController
12 | @RequestMapping("/club/{clubSeq}/board/{clubBoardSeq}/like")
13 | class ClubBoardLikeController(
14 | private val clubBoardLikeService: ClubBoardLikeService
15 | ) {
16 | @PostMapping
17 | @ResponseStatus(HttpStatus.CREATED)
18 | fun registerClubBoardLike(@AuthUser user: User,
19 | @PathVariable clubSeq: Long,
20 | @PathVariable clubBoardSeq: Long): ResponseDto {
21 |
22 | return ResponseDto(data = clubBoardLikeService.registerClubBoardLike(user, clubSeq, clubBoardSeq))
23 | }
24 |
25 | @DeleteMapping
26 | fun deleteClubBoardLike(@AuthUser user: User,
27 | @PathVariable clubSeq: Long,
28 | @PathVariable clubBoardSeq: Long): ResponseDto {
29 |
30 | return ResponseDto(data = clubBoardLikeService.removeClubBoardLike(user, clubSeq, clubBoardSeq))
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/region/RegionController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller.region
2 |
3 | import com.taskforce.superinvention.app.domain.region.RegionService
4 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
5 | import com.taskforce.superinvention.app.web.dto.region.RegionDto
6 | import org.springframework.web.bind.annotation.GetMapping
7 | import org.springframework.web.bind.annotation.RestController
8 |
9 | @RestController
10 | class RegionController(
11 | val regionService: RegionService
12 | ) {
13 |
14 | @GetMapping("/regions")
15 | fun getAllRegionList(): ResponseDto> {
16 | val findByLevel = regionService.findAllRegionDtoList()
17 | return ResponseDto(data = findByLevel)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/user/UserInterestController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller.user
2 |
3 | import com.taskforce.superinvention.app.domain.role.Role
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import com.taskforce.superinvention.app.domain.user.userInterest.UserInterestService
6 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
7 | import com.taskforce.superinvention.app.web.dto.interest.InterestRequestDto
8 | import com.taskforce.superinvention.app.web.dto.interest.UserInterestDto
9 | import com.taskforce.superinvention.common.config.argument.resolver.auth.AuthUser
10 | import org.springframework.security.access.annotation.Secured
11 | import org.springframework.web.bind.annotation.*
12 |
13 | @RestController
14 | @RequestMapping("/users/interests")
15 | class UserInterestController(
16 | private val userInterestService: UserInterestService
17 | ) {
18 | @Secured(Role.MEMBER)
19 | @GetMapping
20 | fun getUserInterestList(@AuthUser user: User): ResponseDto {
21 | val findUserInterest: UserInterestDto = userInterestService.findUserInterest(user)
22 | return ResponseDto(data = findUserInterest)
23 | }
24 |
25 | @Secured(Role.MEMBER)
26 | @PutMapping
27 | fun changeUserInterest(@AuthUser user: User,
28 | @RequestBody interestRequestDto: List): ResponseDto {
29 | return ResponseDto(data = userInterestService.changeUserInterest(user, interestRequestDto))
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/controller/user/UserRegionController.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.controller.user
2 |
3 | import com.taskforce.superinvention.app.domain.role.Role
4 | import com.taskforce.superinvention.app.domain.user.User
5 | import com.taskforce.superinvention.app.domain.user.userRegion.UserRegionService
6 | import com.taskforce.superinvention.app.web.common.response.ResponseDto
7 | import com.taskforce.superinvention.app.web.dto.region.RegionRequestDto
8 | import com.taskforce.superinvention.app.web.dto.user.UserRegionDto
9 | import com.taskforce.superinvention.common.config.argument.resolver.auth.AuthUser
10 | import org.springframework.security.access.annotation.Secured
11 | import org.springframework.web.bind.annotation.*
12 |
13 | @RestController
14 | @RequestMapping("/users/regions")
15 | class UserRegionController(
16 | private val userRegionService: UserRegionService
17 | ) {
18 |
19 | @Secured(Role.NONE, Role.MEMBER)
20 | @GetMapping
21 | fun getUserRegionList(@AuthUser user: User): ResponseDto {
22 | val findUserRegionList = userRegionService.findUserRegionList(user)
23 | return ResponseDto(data = findUserRegionList)
24 | }
25 |
26 | @Secured(Role.NONE, Role.MEMBER)
27 | @PutMapping
28 | fun changeUserRegion(@AuthUser user: User,
29 | @RequestBody regionRequestDto: List): ResponseDto {
30 |
31 | return ResponseDto(data = userRegionService.changeUserRegion(user, regionRequestDto))
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/club/ClubAddRequestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.club
2 |
3 | import com.taskforce.superinvention.app.web.dto.interest.InterestRequestDto
4 | import com.taskforce.superinvention.app.web.dto.region.RegionRequestDto
5 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
6 | import javax.validation.constraints.Min
7 | import javax.validation.constraints.NotBlank
8 | import javax.validation.constraints.NotEmpty
9 |
10 | class ClubAddRequestDto(
11 | @get:NotBlank(message = "모임 명을 입력해주세요")
12 | var name: String,
13 | @get:NotBlank(message = "모임 설명을 작성해주세요")
14 | var description: String,
15 |
16 | @get:Min(value = 2, message = "최소 인원은 2명 이상이어야 합니다")
17 | var maximumNumber: Long,
18 |
19 | var img: S3Path?,
20 |
21 | @get:NotEmpty(message = "모임 관심사를 하나 이상 선택해주세요")
22 | var interestList: List,
23 |
24 | @get:NotEmpty(message = "모임 지역을 하나 이상 선택해주세요")
25 | var regionList: List
26 | )
27 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/club/ClubSearchRequestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.club
2 |
3 | class ClubSearchRequestDto {
4 | var regionSeq: Long? = null
5 | var interestSeq: Long? = null
6 | var interestGroupSeq: Long? = null
7 | var text: String? = null
8 |
9 | constructor(regionSeq: Long?, interestSeq: Long?, interestGroupSeq: Long?, query: String?) {
10 | this.regionSeq = regionSeq
11 | this.interestSeq = interestSeq
12 | this.interestGroupSeq = interestGroupSeq
13 | this.text = query
14 | }
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/club/album/like/ClubAlbumLikeDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.club.album.like
2 |
3 | data class ClubAlbumLikeDto(
4 | val clubSeq: Long,
5 | val clubAlbumSeq: Long,
6 | val likeCnt: Long
7 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/club/board/img/ClubBoardImgDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.club.board.img
2 |
3 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
4 |
5 | data class ClubBoardImgEditS3Path (
6 | val imgSeq: Long?,
7 | val img: S3Path
8 | )
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/club/board/like/ClubBoardLikeDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.club.board.like
2 |
3 | data class ClubBoardLikeDto(
4 | val clubSeq: Long,
5 | val clubBoardSeq: Long,
6 | val likeCnt: Long
7 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/common/PageDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.common
2 |
3 | import org.springframework.data.domain.Page
4 |
5 | data class PageDto(
6 | val pageable : PageableDto,
7 | val content : List,
8 | val last : Boolean,
9 | val size : Int,
10 | val totalPages: Int
11 | ) {
12 | constructor(page : Page) : this(
13 | content = page.content,
14 | pageable = PageableDto(page),
15 | last = page.isLast,
16 | size = page.size,
17 | totalPages = page.totalPages
18 | )
19 | }
20 |
21 | data class PageableDto (
22 | val pageNumber : Int
23 | ) {
24 | constructor(page: Page): this (
25 | pageNumber = page.pageable.pageNumber
26 | )
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/common/image/ResizeDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.common.image
2 |
3 | data class ResizeDto(
4 | val width : Long ? = null,
5 | val height: Long ? = null
6 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/interest/InterestRequestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.interest
2 |
3 | class InterestRequestDto(
4 | val seq: Long,
5 | val priority: Long
6 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/interest/InterestWithPriorityDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.interest
2 |
3 | import com.taskforce.superinvention.app.domain.interest.ClubInterest
4 | import com.taskforce.superinvention.app.domain.interest.interest.InterestDto
5 | import com.taskforce.superinvention.app.domain.user.userInterest.UserInterest
6 |
7 | data class InterestWithPriorityDto(
8 | val interest: InterestDto,
9 | val priority: Long
10 | ) {
11 | constructor(clubInterest: ClubInterest): this(InterestDto(clubInterest.interest), clubInterest.priority)
12 | constructor(userInterest: UserInterest): this(InterestDto(userInterest.interest), userInterest.priority)
13 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/interest/UserInterestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.interest
2 |
3 | class UserInterestDto(
4 | val userSeq: Long,
5 | val userId: String?,
6 | val interestList: List
7 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/kakao/kakaoDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.kakao
2 |
3 | import com.taskforce.superinvention.app.web.dto.interest.InterestRequestDto
4 | import com.taskforce.superinvention.app.web.dto.region.RegionRequestDto
5 | import java.time.LocalDate
6 |
7 | data class KakaoToken (
8 | val token_type : String? = "",
9 | val access_token : String? = "",
10 | val expires_in : Int? = 0,
11 | val refresh_token: String? = "",
12 | val refresh_token_expires_in: Int? = 0
13 | )
14 |
15 | data class KakaoOAuthResponse (
16 | val msg: String,
17 | val code: Int
18 | )
19 |
20 | data class KakaoUserInfo (
21 | val id: String,
22 | val properties: KakaoUserProperties,
23 | val kakao_account: KakaoUserAccount
24 | )
25 |
26 | data class KakaoUserRegistRequest (
27 | val userName: String?,
28 | val birthday: LocalDate?,
29 | val profileImageLink: String?,
30 | val userRegions: List,
31 | val userInterests: List
32 | )
33 |
34 | data class KakaoUserProperties (
35 | val nickname: String,
36 | val profile_image: String = "",
37 | val thumbnail_image: String = ""
38 | )
39 |
40 | data class KakaoUserAccount (
41 | val profile_needs_agreement: Boolean,
42 | val profile: KakaoUserProfile,
43 | val hasGender: Boolean,
44 | val gender_needs_agreement: Boolean
45 | )
46 |
47 | data class KakaoUserProfile(
48 | val nickname: String,
49 | val profile_image_url: String = "",
50 | val thumbnail_image_url: String = ""
51 | )
52 |
53 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/region/RegionDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.region
2 |
3 | import com.taskforce.superinvention.app.domain.region.Region
4 | import kotlin.streams.toList
5 |
6 |
7 | class RegionDto {
8 | var seq: Long?
9 | var name: String
10 | var superRegionRoot: String
11 | var level: Long
12 | var subRegions: List
13 |
14 | constructor(
15 | seq: Long?,
16 | name: String,
17 | superRegionRoot: String,
18 | level: Long,
19 | subRegions: List
20 | ) {
21 | this.seq = seq
22 | this.name = name
23 | this.superRegionRoot = superRegionRoot
24 | this.level = level
25 | this.subRegions = subRegions
26 | }
27 | }
28 |
29 |
30 | fun of(region: Region, findDepth: Long): RegionDto
31 | {
32 | return RegionDto(
33 | seq = region.seq,
34 | name = region.name,
35 | superRegionRoot = region.superRegionRoot,
36 | level = region.level,
37 | subRegions = if (findDepth > 0) region.subRegions.map { e -> of(e, findDepth - 1) }.toList() else emptyList()
38 | )
39 | }
40 |
41 |
42 | fun of(region: Region, subRegions: List): RegionDto
43 | {
44 | return RegionDto(
45 | seq = region.seq,
46 | name = region.name,
47 | superRegionRoot = region.superRegionRoot,
48 | level = region.level,
49 | subRegions = subRegions.map {
50 | RegionDto(
51 | seq = it.seq,
52 | name = it.name,
53 | superRegionRoot = it.superRegionRoot,
54 | level = it.level,
55 | subRegions = emptyList()
56 | ) }
57 | )
58 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/region/RegionRequestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.region
2 |
3 | class RegionRequestDto(
4 | var seq: Long,
5 | var priority: Long
6 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/region/RegionWithPriorityDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.region
2 |
3 | import com.taskforce.superinvention.app.domain.region.ClubRegion
4 |
5 | class RegionWithPriorityDto(
6 | val region: SimpleRegionDto,
7 | val priority: Long
8 | ) {
9 | constructor(clubRegion: ClubRegion): this(SimpleRegionDto(clubRegion.region), clubRegion.priority)
10 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/region/SimpleRegionDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.region
2 |
3 | import com.taskforce.superinvention.app.domain.region.ClubRegion
4 | import com.taskforce.superinvention.app.domain.region.Region
5 |
6 | class SimpleRegionDto(
7 | val seq: Long,
8 | val name: String,
9 | val superRegionRoot: String,
10 | val level: Long
11 | ) {
12 |
13 |
14 | constructor(region: Region): this(region.seq!!, region.name, region.superRegionRoot, region.level)
15 |
16 | constructor(clubRegion: ClubRegion):
17 | this(
18 | clubRegion.region.seq!!,
19 | clubRegion.region.name,
20 | clubRegion.region.superRegionRoot,
21 | clubRegion.region.level
22 | )
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/role/RoleDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.role
2 |
3 | import com.taskforce.superinvention.app.domain.role.Role
4 |
5 | data class RoleDto (
6 | var name: Role.RoleName,
7 | var roleGroupName: String
8 | ) {
9 | constructor(role: Role) :
10 | this(
11 | name = role.name,
12 | roleGroupName = role.roleGroup.name
13 | )
14 |
15 | constructor(nameStr: String, roleGroupName: String) :
16 | this(
17 | name = Role.fromRoleName(nameStr),
18 | roleGroupName = roleGroupName
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/user/UserDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.user
2 |
3 | import com.taskforce.superinvention.app.domain.user.User
4 | import com.taskforce.superinvention.app.domain.user.UserType
5 | import com.taskforce.superinvention.app.domain.user.userRole.UserRole
6 | import com.taskforce.superinvention.app.web.dto.role.RoleDto
7 | import com.taskforce.superinvention.common.util.extendFun.toBaseDate
8 | import java.time.LocalDate
9 | import javax.persistence.OneToMany
10 |
11 | data class UserMemberCheckDto(
12 | val isMember: Boolean
13 | )
14 |
15 | data class UserDto(
16 | var seq: Long,
17 | var userRoles: Set,
18 | var userName: String?,
19 | var birthday: String?,
20 | var profileImageLink: String?
21 | ) {
22 | constructor(user: User): this(
23 | seq = user.seq!!,
24 | userRoles = user.userRoles.map { it.roleName }.toSet(),
25 | userName = user.userName,
26 | birthday = user.birthday?.toBaseDate(),
27 | profileImageLink = user.profileImageLink
28 | )
29 | }
30 |
31 | data class UserIdAndNameDto(
32 | var seq: Long,
33 | var userName: String
34 | ) {
35 | constructor(user: User): this(user.seq!!, user.userName!!)
36 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/user/UserProfileUpdateDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.user
2 |
3 | import com.taskforce.superinvention.common.util.aws.s3.S3Path
4 |
5 | data class UserProfileUpdateDto (
6 | val profileImage: S3Path
7 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/user/UserRegionDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.user
2 |
3 | import com.taskforce.superinvention.app.domain.user.User
4 | import com.taskforce.superinvention.app.web.dto.region.RegionWithPriorityDto
5 |
6 | class UserRegionDto(user: User, regions: List) {
7 | val userSeq: Long?
8 | val userId: String?
9 | val userRegions: List
10 |
11 | init {
12 | this.userSeq = user.seq
13 | this.userId = user.userId
14 | this.userRegions = regions
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/user/info/UserInfoDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.user.info
2 |
3 | import com.taskforce.superinvention.app.domain.user.User
4 | import com.taskforce.superinvention.common.util.extendFun.toBaseDate
5 |
6 | data class UserInfoDto(
7 | val seq: Long,
8 | val userName: String = "",
9 | val birthday: String = "",
10 | val profileImageLink: String = "",
11 | val userRegions : List = emptyList(),
12 | val userInterests: List = emptyList()
13 | ) {
14 | constructor(user: User, userRegions: List, userInfoInterests: List): this(
15 | seq = user.seq!!,
16 | userName = user.userName ?: "",
17 | birthday = user.birthday?.toBaseDate() ?: "",
18 | profileImageLink = user.profileImageLink ?: "",
19 | userRegions = userRegions,
20 | userInterests = userInfoInterests
21 | )
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/user/info/UserInfoInterestDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.user.info
2 |
3 | import com.taskforce.superinvention.app.domain.interest.interestGroup.InterestGroup
4 | import com.taskforce.superinvention.app.domain.user.userInterest.UserInterest
5 |
6 |
7 | data class UserInfoInterestDto (
8 | val interest: UserInfoInterestItem,
9 | val priority: Long
10 | ) {
11 | constructor(userInterest: UserInterest):
12 | this(
13 | interest = UserInfoInterestItem(userInterest),
14 | priority = userInterest.priority
15 | )
16 | }
17 |
18 | data class UserInfoInterestItem (
19 | val seq : Long,
20 | val name: String = "",
21 | val interestGroup: UserInfoInterestGroupDto
22 | ) {
23 | constructor(userInterest: UserInterest):
24 | this(
25 | seq = userInterest.seq!!,
26 | name = userInterest.interest.name,
27 | interestGroup = UserInfoInterestGroupDto(userInterest.interest.interestGroup)
28 | )
29 | }
30 |
31 | data class UserInfoInterestGroupDto (
32 | val seq : Long,
33 | val name: String
34 | ) {
35 | constructor(interestGroup: InterestGroup) :
36 | this(
37 | seq = interestGroup.seq!!,
38 | name= interestGroup.name
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/app/web/dto/user/info/UserInfoRegionDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.web.dto.user.info
2 |
3 | import com.taskforce.superinvention.app.web.dto.region.SimpleRegionDto
4 |
5 | data class UserInfoRegionDto (
6 | val region : SimpleRegionDto,
7 | val priority: Long
8 | ) {
9 | constructor(priority: Long, simpleRegionDto: SimpleRegionDto): this (
10 | region = simpleRegionDto,
11 | priority = priority
12 | )
13 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/advice/AdviceDto.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.advice
2 |
3 |
4 | data class ErrorResponse(
5 | val message: String,
6 | val stackTrace: String = ""
7 | ) {
8 | companion object {
9 | const val defaultMessage = "서버에 에러가 발생하였습니다"
10 | fun sliceArrayAndJoin(arr: Array<*>): String {
11 | return arr.sliceArray(0..20).joinToString (separator = "\n"){ it.toString() }
12 | }
13 | }
14 |
15 | constructor(message: String, stackTrace: Array) :
16 | this(message, sliceArrayAndJoin(stackTrace))
17 |
18 | constructor(stackTrace: Array):
19 | this(defaultMessage, sliceArrayAndJoin(stackTrace))
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/advice/GlobalSecurityExceptionHandler.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.advice
2 |
3 | import com.taskforce.superinvention.common.util.kakao.KakaoOAuth
4 | import org.slf4j.Logger
5 | import org.slf4j.LoggerFactory
6 | import org.springframework.http.HttpStatus
7 | import org.springframework.http.ResponseEntity
8 | import org.springframework.security.access.AccessDeniedException
9 | import org.springframework.web.bind.annotation.ExceptionHandler
10 | import org.springframework.web.bind.annotation.RestControllerAdvice
11 |
12 | @RestControllerAdvice
13 | class GlobalControllerExceptionHandler {
14 |
15 | companion object {
16 | val LOG: Logger = LoggerFactory.getLogger(KakaoOAuth::class.java)
17 | }
18 |
19 | @ExceptionHandler(AccessDeniedException::class)
20 | fun forbiddenWithNoAuthException(e: AccessDeniedException) : ResponseEntity {
21 | LOG.error(e.message)
22 | return ResponseEntity(
23 | ErrorResponse("접근 권한이 없습니다.", e.stackTrace),
24 | HttpStatus.INTERNAL_SERVER_ERROR
25 | )
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/WebMvcConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config
2 |
3 | import com.taskforce.superinvention.common.config.argument.converter.ClubBoardCategoryConverter
4 | import com.taskforce.superinvention.common.config.argument.resolver.auth.AuthorizeArgumentResolver
5 | import org.springframework.context.annotation.Configuration
6 | import org.springframework.data.web.PageableHandlerMethodArgumentResolver
7 | import org.springframework.format.FormatterRegistry
8 | import org.springframework.web.method.support.HandlerMethodArgumentResolver
9 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
11 |
12 | @Configuration
13 | class WebMvcConfig(
14 | private val authorizeArgumentResolver: AuthorizeArgumentResolver
15 | ): WebMvcConfigurationSupport() {
16 |
17 | override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
18 | registry.addResourceHandler("/docs/**")
19 | .addResourceLocations("classpath:/static/docs/")
20 | }
21 |
22 | override fun addArgumentResolvers(argumentResolvers: MutableList) {
23 | argumentResolvers.add(authorizeArgumentResolver)
24 | argumentResolvers.add(PageableHandlerMethodArgumentResolver());
25 | }
26 |
27 | override fun addFormatters(registry: FormatterRegistry) {
28 | registry.addConverter(ClubBoardCategoryConverter())
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/argument/converter/ClubBoardCategoryConverter.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.argument.converter
2 |
3 | import com.taskforce.superinvention.app.domain.club.board.ClubBoard
4 | import com.taskforce.superinvention.common.exception.InvalidInputException
5 | import org.springframework.core.convert.converter.Converter
6 |
7 | class ClubBoardCategoryConverter: Converter {
8 |
9 | override fun convert(source: String): ClubBoard.Category {
10 | return ClubBoard.Category.fromCategoryLabel(source)
11 | ?: throw InvalidInputException(message = "해당 카테고리로를 검색할 수 없습니다.")
12 | }
13 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/argument/resolver/auth/AuthorizeArgumentResolver.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.argument.resolver.auth
2 |
3 | import com.taskforce.superinvention.app.domain.user.User
4 | import com.taskforce.superinvention.app.domain.user.UserRepository
5 | import com.taskforce.superinvention.common.exception.auth.UserNotFoundException
6 | import org.springframework.core.MethodParameter
7 | import org.springframework.security.core.Authentication
8 | import org.springframework.security.core.context.SecurityContextHolder
9 | import org.springframework.stereotype.Component
10 | import org.springframework.web.bind.support.WebDataBinderFactory
11 | import org.springframework.web.context.request.NativeWebRequest
12 | import org.springframework.web.method.support.HandlerMethodArgumentResolver
13 | import org.springframework.web.method.support.ModelAndViewContainer
14 |
15 | annotation class AuthUser(
16 | val allowAnonymous: Boolean = true
17 | )
18 |
19 | @Component
20 | class AuthorizeArgumentResolver(
21 | val userRepository: UserRepository
22 | ): HandlerMethodArgumentResolver {
23 |
24 | override fun supportsParameter(parameter: MethodParameter): Boolean {
25 | return parameter.hasParameterAnnotation(AuthUser::class.java)
26 | }
27 |
28 | override fun resolveArgument(parameter: MethodParameter, mavContainer: ModelAndViewContainer?, webRequest: NativeWebRequest, binderFactory: WebDataBinderFactory?): User? {
29 | val authUser = parameter.parameter.getAnnotation(AuthUser::class.java)
30 |
31 | val authentication: Authentication = SecurityContextHolder.getContext().authentication
32 | val userId = authentication.name
33 |
34 | val userEntity: User? = userRepository.findByUserId(userId)
35 |
36 | if(!authUser.allowAnonymous && userEntity == null) {
37 | throw UserNotFoundException()
38 | }
39 |
40 | return userEntity
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/async/AsyncConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.async
2 |
3 | import org.springframework.context.annotation.Bean
4 | import org.springframework.context.annotation.Configuration
5 | import org.springframework.scheduling.annotation.EnableAsync
6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
7 | import java.util.concurrent.Executor
8 |
9 | @Configuration
10 | @EnableAsync
11 | class AsyncConfig {
12 |
13 | companion object {
14 | const val WEBP_CONVERSION = "webpConversion"
15 | }
16 |
17 | @Bean(WEBP_CONVERSION)
18 | fun webpConversionAsyncTaskExecutor(): Executor {
19 |
20 | val threadPoolTaskExecutor = ThreadPoolTaskExecutor()
21 | threadPoolTaskExecutor.corePoolSize = 10
22 | threadPoolTaskExecutor.maxPoolSize = 30
23 | threadPoolTaskExecutor.setThreadNamePrefix("super-invention-webp-conversion")
24 |
25 | return threadPoolTaskExecutor
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/jpa/CriteriaConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.jpa
2 |
3 | import com.blazebit.persistence.Criteria
4 | import com.blazebit.persistence.CriteriaBuilderFactory
5 | import org.springframework.context.annotation.Bean
6 | import org.springframework.context.annotation.Configuration
7 | import javax.persistence.EntityManager
8 |
9 | @Configuration
10 | class CriteriaConfig(
11 | private val entityManager: EntityManager
12 | ) {
13 |
14 | @Bean
15 | fun createCriteriaBuilderFactory() : CriteriaBuilderFactory {
16 | val config = Criteria.getDefault()
17 | return config.createCriteriaBuilderFactory(entityManager.entityManagerFactory)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/jpa/JpaConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.jpa
2 |
3 | import org.springframework.context.annotation.Bean
4 | import org.springframework.context.annotation.Configuration
5 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing
6 | import org.springframework.orm.jpa.JpaVendorAdapter
7 | import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter
8 | import org.springframework.orm.jpa.vendor.Database
9 | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
10 |
11 |
12 | @Configuration
13 | @EnableJpaAuditing
14 | class JpaConfig {
15 |
16 | @Bean
17 | fun jpaVendorAdapter(): JpaVendorAdapter {
18 | val adapter: AbstractJpaVendorAdapter = HibernateJpaVendorAdapter()
19 | adapter.setShowSql(true)
20 | adapter.setDatabase(Database.MYSQL)
21 | adapter.setDatabasePlatform("com.taskforce.superinvention.common.config.jpa.dialect.CustomMysqlDialect")
22 | adapter.setGenerateDdl(false)
23 | return adapter
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/jpa/QueryDslConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.jpa
2 |
3 | import com.querydsl.jpa.impl.JPAQueryFactory
4 | import org.springframework.context.annotation.Bean
5 | import org.springframework.context.annotation.Configuration
6 | import javax.persistence.EntityManager
7 |
8 | @Configuration
9 | class QueryDslConfig (
10 | private val entityManager: EntityManager
11 | ) {
12 |
13 | @Bean
14 | fun jpaQueryFactory(): JPAQueryFactory = JPAQueryFactory(entityManager)
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/jpa/dialect/CustomMysqlDialect.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.jpa.dialect
2 |
3 | import org.hibernate.dialect.MySQL8Dialect
4 | import org.hibernate.dialect.function.SQLFunctionTemplate
5 | import org.hibernate.type.StandardBasicTypes
6 |
7 | class CustomMysqlDialect() : MySQL8Dialect() {
8 |
9 | init {
10 | this.registerFunction("group_concat", SQLFunctionTemplate(StandardBasicTypes.STRING, "group_concat(?1)"))
11 | }
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/security/AppToken.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.security
2 |
3 | data class AppToken(
4 | var isRegistered: Boolean?,
5 | var appToken : String?
6 | )
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/security/FilterChainExceptionHandler.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.security
2 |
3 | import org.springframework.web.filter.OncePerRequestFilter
4 | import java.lang.Exception
5 | import javax.servlet.FilterChain
6 | import javax.servlet.http.HttpServletRequest
7 | import javax.servlet.http.HttpServletResponse
8 | import org.springframework.web.servlet.HandlerExceptionResolver
9 |
10 | import org.springframework.beans.factory.annotation.Autowired
11 | import org.springframework.beans.factory.annotation.Qualifier
12 | import org.springframework.stereotype.Component
13 |
14 | @Component
15 | class FilterChainExceptionHandler : OncePerRequestFilter() {
16 |
17 | @Autowired
18 | @Qualifier("handlerExceptionResolver")
19 | lateinit var resolver: HandlerExceptionResolver
20 |
21 | override fun doFilterInternal(
22 | request: HttpServletRequest,
23 | response: HttpServletResponse,
24 | filterChain: FilterChain
25 | ) {
26 | try {
27 | filterChain.doFilter(request, response)
28 | } catch (e: Exception) {
29 | resolver.resolveException(request, response, null, e)
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/security/JwtTokenFilter.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.security
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.security.core.Authentication
5 | import org.springframework.security.core.context.SecurityContextHolder
6 | import org.springframework.web.filter.OncePerRequestFilter
7 | import javax.servlet.FilterChain
8 | import javax.servlet.http.HttpServletRequest
9 | import javax.servlet.http.HttpServletResponse
10 |
11 | class JwtTokenFilter(
12 | private val jwtTokenProvider: JwtTokenProvider
13 | ) : OncePerRequestFilter() {
14 |
15 | override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
16 | val token: String = resolveToken(request)
17 |
18 | try {
19 | if (isTokenValidate(token)) {
20 | val auth: Authentication = jwtTokenProvider.getAuthentication(token)
21 | SecurityContextHolder.getContext().authentication = auth
22 | }
23 | } catch (ex: BizException) {
24 | SecurityContextHolder.clearContext()
25 | response.sendError(ex.httpStatus.value(), ex.message)
26 | return
27 | }
28 | filterChain.doFilter(request, response)
29 | }
30 |
31 | private fun resolveToken(req: HttpServletRequest): String {
32 | val bearerToken = req.getHeader(JwtTokenProvider.TOKEN_HEADER)
33 | return if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
34 | bearerToken.substring(7)
35 | } else ""
36 | }
37 |
38 | private fun isTokenValidate(token: String): Boolean {
39 | if(token.isBlank()) {
40 | return false
41 | }
42 |
43 | if(jwtTokenProvider.validateToken(token)) {
44 | return true
45 | }
46 | return false
47 | }
48 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/security/JwtTokenFilterConfigurer.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.security
2 |
3 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity
5 | import org.springframework.security.web.DefaultSecurityFilterChain
6 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
7 |
8 | class JwtTokenFilterConfigurer(
9 | private val jwtTokenProvider: JwtTokenProvider
10 | ) : SecurityConfigurerAdapter() {
11 |
12 | override fun configure(http: HttpSecurity) {
13 | val customFilter = JwtTokenFilter(jwtTokenProvider)
14 | http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter::class.java)
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/web/resttemplate/RestTemplateConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.web.resttemplate
2 |
3 | import org.apache.http.client.HttpClient
4 | import org.apache.http.impl.client.HttpClientBuilder
5 | import org.springframework.context.annotation.Bean
6 | import org.springframework.context.annotation.Configuration
7 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
8 | import org.springframework.web.client.RestTemplate
9 |
10 | @Configuration
11 | class RestTemplateConfig {
12 |
13 | @Bean
14 | fun restTemplate(): RestTemplate {
15 | val factory = HttpComponentsClientHttpRequestFactory()
16 | val httpClient: HttpClient = HttpClientBuilder.create()
17 | .setMaxConnTotal(50)
18 | .setMaxConnPerRoute(30)
19 | .build()
20 |
21 | factory.httpClient = httpClient
22 | factory.setConnectTimeout(2000)
23 | factory.setReadTimeout(2000)
24 |
25 | return RestTemplate(factory)
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/config/web/resttemplate/kakao/KakaoAuthResponseErrorHandler.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.config.web.resttemplate.kakao
2 |
3 | import org.slf4j.Logger
4 | import org.slf4j.LoggerFactory
5 | import org.springframework.http.HttpStatus.Series.*
6 | import org.springframework.http.client.ClientHttpResponse
7 | import org.springframework.stereotype.Component
8 | import org.springframework.web.client.ResponseErrorHandler
9 |
10 | @Component
11 | class KakaoAuthResponseErrorHandler: ResponseErrorHandler {
12 |
13 | companion object {
14 | val LOG: Logger = LoggerFactory.getLogger(KakaoAuthResponseErrorHandler::class.java)
15 | }
16 |
17 | override fun hasError(response: ClientHttpResponse): Boolean {
18 | return (
19 | response.statusCode.series() == CLIENT_ERROR // 400 번대
20 | || response.statusCode.series() == SERVER_ERROR // 500 번대
21 | )
22 | }
23 |
24 | override fun handleError(response: ClientHttpResponse) {
25 | val msg = "${response.statusCode}\n${response.rawStatusCode}\n${response.statusText}"
26 | LOG.error(msg)
27 |
28 | when(response.statusCode.series()) {
29 | SERVER_ERROR -> {}
30 | CLIENT_ERROR -> {}
31 | else -> {
32 | LOG.error("알 수 없는 에러입니다.")
33 | throw Exception()
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/BizException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception
2 |
3 | import org.springframework.http.HttpStatus
4 |
5 | open class BizException(
6 | override val message: String,
7 | val httpStatus: HttpStatus
8 | ) : RuntimeException() {
9 |
10 | companion object {
11 | private const val serialVersionUID = 1L
12 | }
13 |
14 | constructor(message: String) : this(message, HttpStatus.INTERNAL_SERVER_ERROR)
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/InvalidInputException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception
2 |
3 | import org.springframework.http.HttpStatus
4 |
5 | class InvalidInputException(
6 | message: String,
7 | httpStatus: HttpStatus
8 | ) : BizException(message, httpStatus) {
9 | constructor(message: String): this(message, HttpStatus.BAD_REQUEST)
10 | constructor(): this("입력값이 올바르지않습니다.", HttpStatus.BAD_REQUEST)
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/ResourceNotFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class ResourceNotFoundException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 | constructor(message: String): this(message, HttpStatus.NO_CONTENT)
11 | constructor(): this("해당 자원이 존재하지 않습니다.", HttpStatus.NO_CONTENT)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/auth/AccessTokenExpiredException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.auth
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class AccessTokenExpiredException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus)
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/auth/InsufficientAuthException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.auth
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | open class InsufficientAuthException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 | constructor(): this(
11 | message = "권한이 충분하지 않습니다.",
12 | httpStatus = HttpStatus.FORBIDDEN
13 | )
14 |
15 | constructor(message: String): this(
16 | message = message,
17 | httpStatus = HttpStatus.FORBIDDEN
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/auth/OnlyWriterCanAccessException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.auth
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class OnlyWriterCanAccessException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 | constructor(message: String): this(message, HttpStatus.FORBIDDEN)
11 | constructor(): this("오직 해당 자원의 작성자만 자원에 접근할 수 있습니다.", HttpStatus.FORBIDDEN)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/auth/UserNotFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.auth
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class UserNotFoundException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("해당 유저를 찾을 수 없습니다.", HttpStatus.UNAUTHORIZED)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/auth/WithdrawClubUserNotAllowedException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.auth
2 |
3 | class WithdrawClubUserNotAllowedException(
4 | message: String,
5 | ): InsufficientAuthException(message) {
6 | constructor(): this(
7 | message = "탈퇴한 모임에서는 사용할 수 없는 기능입니다.",
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/CannotJoinClubException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class CannotJoinClubException(message: String,
7 | httpStatus: HttpStatus
8 | ) : BizException(message, httpStatus) {
9 |
10 | constructor(): this("모임에 가입하실 수 없습니다.", HttpStatus.FORBIDDEN)
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/ClubNotFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class ClubNotFoundException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("해당 모임은 존재하지 않습니다.", HttpStatus.BAD_REQUEST)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/UserIsNotClubMemberException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class UserIsNotClubMemberException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 | constructor(): this("해당 유저는 모임원이 아닙니다.", HttpStatus.FORBIDDEN)
11 |
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/album/ClubAlbumNotFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club.album
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class ClubAlbumNotFoundException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("해당 사진은 모임 사진첩에 존재하지 않습니다..", HttpStatus.BAD_REQUEST)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/album/NoAuthForClubAlbumException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club.album
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class NoAuthForClubAlbumException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("""
12 | |해당 모임 사진첩 사진에 대한 권한이 없습니다.
13 | |매니저, 마스터 그리고 사진 등록자만 요청할 수 있습니다.
14 | """.trimMargin(), HttpStatus.FORBIDDEN)
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/board/ClubBoardNotFoundException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club.board
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class ClubBoardNotFoundException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("해당 게시글은 존재하지 않습니다..", HttpStatus.BAD_REQUEST)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/meeting/MeetingAlreadyApplicationException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club.meeting
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class MeetingAlreadyApplicationException(message: String) : BizException(message, HttpStatus.CONFLICT) {
7 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/meeting/MeetingIsClosedException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club.meeting
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class MeetingIsClosedException(message: String) : BizException(message, HttpStatus.CONFLICT) {
7 | constructor(): this("이미 종료된 만남입니다")
8 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/club/meeting/MeetingMemberOverflowException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.club.meeting
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class MeetingMemberOverflowException(message: String) : BizException(message, HttpStatus.CONFLICT) {
7 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/common/ImplementationIsNotSupported.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.common
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class ImplementationIsNotSupported(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("해당 요청은 사용될 수 없습니다. (구현체 없음)", HttpStatus.BAD_REQUEST)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/exception/common/IsAlreadyDeletedException.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.exception.common
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import org.springframework.http.HttpStatus
5 |
6 | class IsAlreadyDeletedException(
7 | message: String,
8 | httpStatus: HttpStatus
9 | ) : BizException(message, httpStatus) {
10 |
11 | constructor(): this("해당 자원은 이미 삭제되었습니다.", HttpStatus.BAD_REQUEST)
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/util/aws/s3/S3Path.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.util.aws.s3
2 |
3 | data class S3Path (
4 | var absolutePath: String = "",
5 | var filePath : String = "",
6 | var fileName : String = ""
7 | ) {
8 | fun folderPath(): String {
9 | return filePath.replace("/${fileName}", "")
10 | }
11 | }
12 |
13 | fun S3Path.isValidPath(): Boolean {
14 | return this.absolutePath.isNotBlank() &&
15 | this.filePath.isNotBlank() &&
16 | this.fileName.isNotBlank()
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/util/extendFun/LocalDateExtension.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.util.extendFun
2 |
3 | import com.taskforce.superinvention.common.exception.BizException
4 | import java.time.DayOfWeek
5 | import java.time.LocalDate
6 | import java.time.LocalDateTime
7 | import java.time.LocalTime
8 | import java.time.format.DateTimeFormatter
9 |
10 | const val DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"
11 | const val DATE_FORMAT = "yyyy-MM-dd"
12 | const val DATE_FORMAT_KOR = "yyyy년 MM월 dd일"
13 | const val TIME_FORMAT = "HH:mm"
14 | const val YEAR_MONTH_KOR = "yyyy년 MM월"
15 |
16 | fun LocalDate.toBaseDate(): String {
17 |
18 | return this.format(DateTimeFormatter.ofPattern(DATE_FORMAT))
19 | }
20 |
21 | fun LocalDateTime.toBaseDateTime(): String {
22 | return this.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))
23 | }
24 |
25 | fun LocalDate.toKorDate(): String {
26 | return this.format(DateTimeFormatter.ofPattern(DATE_FORMAT_KOR))
27 | }
28 |
29 | fun LocalTime.toBaseTime(): String {
30 | return this.format(DateTimeFormatter.ofPattern(TIME_FORMAT))
31 | }
32 |
33 | fun DayOfWeek.getKorDisplayName(): String {
34 | return when(this.value) {
35 | 1 -> "월요일"
36 | 2 -> "화요일"
37 | 3 -> "수요일"
38 | 4 -> "목요일"
39 | 5 -> "금요일"
40 | 6 -> "토요일"
41 | 7 -> "일요일"
42 | else -> throw BizException("존재하지 않는 요일데이터입니다")
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/util/extendFun/StringExtension.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.util.extendFun
2 |
3 | fun String.sliceIfExceed(range: IntRange): String {
4 | return if(this.length > range.last) {
5 | this.slice(range)
6 | } else {
7 | this
8 | }
9 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/util/file/FileMo.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.util.file
2 |
3 | import org.apache.tomcat.util.http.fileupload.FileUtils
4 | import org.springframework.web.multipart.MultipartFile
5 | import java.io.File
6 | import java.io.FileOutputStream
7 | import java.time.LocalDateTime
8 | import java.time.format.DateTimeFormatter
9 | import java.util.*
10 |
11 | class FileMo {
12 | companion object {
13 |
14 | fun convertMultiPartToFile(file: MultipartFile): File {
15 | val convertedFile = File(file.originalFilename!!)
16 | val fos = FileOutputStream(convertedFile)
17 | fos.write(file.bytes)
18 | fos.close()
19 | return convertedFile
20 | }
21 |
22 | fun generateUUID(multiPart: MultipartFile): String {
23 | val datetimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss"))
24 |
25 | val uuid = "${datetimeStr}-${UUID.randomUUID()}"
26 | val fileName = multiPart.originalFilename!!.replace(" ".toRegex(), "-")
27 |
28 | return "${uuid}-${fileName}"
29 | }
30 |
31 | fun generateUUID(file: File): String {
32 | val datetimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss"))
33 |
34 | val uuid = "${datetimeStr}-${UUID.randomUUID()}"
35 | val fileName = file.name.replace(" ".toRegex(), "-")
36 |
37 | return "${uuid}-${fileName}"
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/taskforce/superinvention/common/util/file/image/gif/GifMo.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.util.file.image.gif
2 |
3 | import com.drew.imaging.ImageMetadataReader
4 | import com.drew.metadata.Metadata
5 | import com.drew.metadata.gif.GifControlDirectory
6 | import java.io.ByteArrayInputStream
7 |
8 | class GifMo {
9 | companion object {
10 | fun isAnimated(metadata: Metadata): Boolean {
11 | val controlDirectories = metadata.getDirectoriesOfType(GifControlDirectory::class.java) as List<*>
12 |
13 | return controlDirectories.size > 1
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/resources/application-dev.properties:
--------------------------------------------------------------------------------
1 | # MySQL
2 | spring.datasource.driverClassName=org.mariadb.jdbc.Driver
3 |
4 | # JPA
5 | spring.jpa.database-platform=org.hibernate.dialect.MariaDB103Dialect
6 | spring.jpa.properties.hibernate.show_sql=true
7 | spring.jpa.hibernate.ddl-auto=none
8 | spring.jpa.properties.hibernate.jdbc.batch_size=100
9 | spring.jpa.properties.hibernate.order_inserts=true
10 |
11 |
12 |
13 | # Security
14 | security.jwt.token.expireMinuit=5
15 |
16 | logging.level.root=info
17 |
18 | # AWS
19 | aws.s3.bucketName=super-invention-static
20 |
21 | # ETC
--------------------------------------------------------------------------------
/src/main/resources/application-prod.properties:
--------------------------------------------------------------------------------
1 | # MySQL
2 | spring.datasource.driverClassName=org.mariadb.jdbc.Driver
3 |
4 | # JPA
5 | spring.jpa.database-platform=org.hibernate.dialect.MariaDB103Dialect
6 | spring.jpa.properties.hibernate.show_sql=true
7 | spring.jpa.hibernate.ddl-auto=none
8 | spring.jpa.properties.hibernate.jdbc.batch_size=100
9 | spring.jpa.properties.hibernate.order_inserts=true
10 |
11 |
12 | logging.level.root=info
13 |
14 | # AWS
15 | aws.s3.bucketName=super-invention-static
16 |
17 | # ETC
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.profiles.active=dev,dev-secret
2 |
3 | spring.data.redis.repositories.enabled = false
4 | spring.servlet.multipart.max-file-size=50MB
5 | spring.servlet.multipart.max-request-size=50MB
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ███████╗██╗ ██╗██████╗ ███████╗██████╗ ██╗███╗ ██╗██╗ ██╗███████╗███╗ ██╗████████╗██╗ ██████╗ ███╗ ██╗
2 | ██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ██║████╗ ██║██║ ██║██╔════╝████╗ ██║╚══██╔══╝██║██╔═══██╗████╗ ██║
3 | ███████╗██║ ██║██████╔╝█████╗ ██████╔╝ ██║██╔██╗ ██║██║ ██║█████╗ ██╔██╗ ██║ ██║ ██║██║ ██║██╔██╗ ██║
4 | ╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗ ██║██║╚██╗██║╚██╗ ██╔╝██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██║██║╚██╗██║
5 | ███████║╚██████╔╝██║ ███████╗██║ ██║ ██║██║ ╚████║ ╚████╔╝ ███████╗██║ ╚████║ ██║ ██║╚██████╔╝██║ ╚████║
6 | ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═══╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
7 |
--------------------------------------------------------------------------------
/src/main/resources/db/data-interest-group.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO interest_group
2 | ( seq, created_at, updated_at, name)
3 | VALUES
4 | (1, now(), now(), '아웃도어/여행'),
5 | (2, now(), now(), '운동/스포츠'),
6 | (3, now(), now(), '인문학/책/글'),
7 | (4, now(), now(), '외국/언어'),
8 | (5, now(), now(), '문화/공연/축제');
9 |
--------------------------------------------------------------------------------
/src/main/resources/db/data-interest.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO interest
2 | ( seq, interest_group_seq, created_at, updated_at, name )
3 | VALUES
4 |
5 | # 아웃도어/ 여행
6 | (1, 1, now(), now(), '해외여행'),
7 | (2, 1, now(), now(), '국내여행'),
8 | (3, 1, now(), now(), '당일치기'),
9 |
10 | # 운동/스포츠
11 | (4, 2, now(), now(), '자전거'),
12 | (5, 2, now(), now(), '볼링'),
13 | (6, 2, now(), now(), '배드민'),
14 | (7, 2, now(), now(), '헬스'),
15 | (8, 2, now(), now(), '크로스핏'),
16 |
17 | # 인문학/책/글
18 | (9, 3, now(), now(), '책읽기'),
19 | (10, 3, now(), now(), '시 감상'),
20 |
21 | # 외국/언어
22 | (11, 4, now(), now(), '영어'),
23 | (12, 4, now(), now(), '독일'),
24 | (13, 4, now(), now(), '일본거'),
25 |
26 | # 문화/공연/축제
27 | (14, 5, now(), now(), '콘서트'),
28 | (15, 5, now(), now(), '클래식'),
29 | (16, 5, now(), now(), '오페라'),
30 | (17, 5, now(), now(), '재즈');
31 |
32 |
--------------------------------------------------------------------------------
/src/main/resources/dist_webp_binaries/cwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/dist_webp_binaries/cwebp
--------------------------------------------------------------------------------
/src/main/resources/dist_webp_binaries/dwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/dist_webp_binaries/dwebp
--------------------------------------------------------------------------------
/src/main/resources/dist_webp_binaries/gif2webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/dist_webp_binaries/gif2webp
--------------------------------------------------------------------------------
/src/main/resources/webp/linux/cwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/linux/cwebp
--------------------------------------------------------------------------------
/src/main/resources/webp/linux/dwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/linux/dwebp
--------------------------------------------------------------------------------
/src/main/resources/webp/linux/gif2webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/linux/gif2webp
--------------------------------------------------------------------------------
/src/main/resources/webp/mac/cwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/mac/cwebp
--------------------------------------------------------------------------------
/src/main/resources/webp/mac/dwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/mac/dwebp
--------------------------------------------------------------------------------
/src/main/resources/webp/mac/gif2webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/mac/gif2webp
--------------------------------------------------------------------------------
/src/main/resources/webp/window/cwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/window/cwebp
--------------------------------------------------------------------------------
/src/main/resources/webp/window/dwebp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/window/dwebp
--------------------------------------------------------------------------------
/src/main/resources/webp/window/gif2webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/main/resources/webp/window/gif2webp
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/app/domain/interest/interest/InterestRepoTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interest
2 |
3 | import com.taskforce.superinvention.config.test.DataJpaRepoTest
4 | import org.springframework.beans.factory.annotation.Autowired
5 |
6 | class InterestRepoTest: DataJpaRepoTest() {
7 |
8 | @Autowired
9 | lateinit var interestRepository: InterestRepository
10 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/app/domain/interest/interestGroup/InterestGroupRepoTestData.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.interest.interestGroup
2 |
3 | import com.taskforce.superinvention.config.test.DataJpaRepoTest
4 | import org.springframework.beans.factory.annotation.Autowired
5 |
6 | class InterestGroupRepoTestData : DataJpaRepoTest() {
7 |
8 | @Autowired
9 | lateinit var interestGroupRepo: InterestGroupRepository
10 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/app/domain/user/userRole/UserRoleDataTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.app.domain.user.userRole
2 |
3 | import com.taskforce.superinvention.config.test.DataJpaRepoTest
4 | import org.springframework.beans.factory.annotation.Autowired
5 |
6 |
7 | class UserRoleDataTest : DataJpaRepoTest() {
8 |
9 | @Autowired
10 | lateinit var userRoleRepository: UserRoleRepository
11 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/common/extendFun/StringExtensionTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.common.extendFun
2 |
3 | import com.taskforce.superinvention.common.util.extendFun.sliceIfExceed
4 | import com.taskforce.superinvention.config.test.MockkTest
5 | import org.junit.jupiter.api.Assertions
6 | import org.junit.jupiter.api.Test
7 |
8 | class StringExtensionTest: MockkTest() {
9 |
10 | @Test
11 | fun `sliceIfExceed - 범위를 넘어섯을 때만 문자열을 자름`() {
12 |
13 | val str = "문자열-10-글자-"
14 | val str2 = "3글자"
15 |
16 | Assertions.assertEquals("문자열", str.sliceIfExceed(0 until 3))
17 | Assertions.assertEquals("3글자" , str2.sliceIfExceed(0 until 3))
18 | }
19 |
20 | @Test
21 | fun `sliceIfExceed - 범위 내에 있을때는 문자열을 자르지 않음`() {
22 | val str = "문자열-10-글자-"
23 | Assertions.assertEquals(str, str.sliceIfExceed(0 until 100))
24 | }
25 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/MokitoHelper.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config
2 |
3 | import com.taskforce.superinvention.app.domain.role.Role
4 | import com.taskforce.superinvention.app.domain.role.RoleGroup
5 | import org.mockito.Mockito
6 |
7 | object MockitoHelper {
8 | fun anyObject(): T {
9 | Mockito.any()
10 | return uninitialized()
11 | }
12 |
13 | @Suppress("UNCHECKED_CAST")
14 | fun uninitialized(): T = null as T
15 |
16 | fun getRoleByRoleName(roleName: Role.RoleName, level: Int): Role {
17 | return Role(roleName, RoleGroup("MOCK_ROLE_GROUP", "MOCK_ROLE_TYPE"), level)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/jpa/CriteriaConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.jpa
2 |
3 | import com.blazebit.persistence.Criteria
4 | import com.blazebit.persistence.CriteriaBuilderFactory
5 | import org.springframework.boot.test.context.TestConfiguration
6 | import org.springframework.context.annotation.Bean
7 | import javax.persistence.EntityManager
8 |
9 | @TestConfiguration
10 | class CriteriaConfig(
11 | private val entityManager: EntityManager
12 | ) {
13 |
14 | @Bean
15 | fun createCriteriaBuilderFactory() : CriteriaBuilderFactory {
16 | val config = Criteria.getDefault()
17 | return config.createCriteriaBuilderFactory(entityManager.entityManagerFactory)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/jpa/JpaTestConfig.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.jpa
2 |
3 | import com.querydsl.jpa.impl.JPAQueryFactory
4 | import org.springframework.boot.test.context.TestConfiguration
5 | import org.springframework.context.annotation.Bean
6 | import javax.persistence.EntityManager
7 |
8 | @TestConfiguration
9 | class JpaTestConfig(
10 | private val entityManager: EntityManager
11 | ) {
12 |
13 | @Bean
14 | fun jpaQueryFactory(): JPAQueryFactory = JPAQueryFactory(entityManager)
15 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/ApiDocumentationTestV2.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper
4 | import com.ninjasquad.springmockk.MockkBean
5 | import com.taskforce.superinvention.app.domain.user.*
6 | import com.taskforce.superinvention.common.config.argument.resolver.auth.AuthorizeArgumentResolver
7 | import com.taskforce.superinvention.common.config.security.JwtTokenProvider
8 | import io.mockk.every
9 | import org.springframework.beans.factory.annotation.Autowired
10 | import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
11 | import org.springframework.test.web.servlet.MockMvc
12 |
13 | @AutoConfigureRestDocs
14 | abstract class ApiDocumentationTestV2: BaseTest {
15 |
16 | @Autowired
17 | lateinit var mockMvc: MockMvc
18 |
19 | @Autowired
20 | lateinit var objectMapper: ObjectMapper
21 |
22 | @MockkBean
23 | lateinit var authorizeArgumentResolver: AuthorizeArgumentResolver
24 |
25 | @MockkBean
26 | lateinit var userRepository: UserRepository
27 |
28 | @MockkBean(relaxed = true)
29 | lateinit var jwtTokenProvider: JwtTokenProvider
30 |
31 | @MockkBean
32 | lateinit var userDetailsProvider: UserDetailsProvider
33 |
34 | // @AuthUser - ArgumentResolver 모킹
35 | fun initMockAuthUser(user: User) {
36 | every { authorizeArgumentResolver.resolveArgument(any(), any(), any(), any()) }.returns(user)
37 | every { authorizeArgumentResolver.supportsParameter(any())}.returns(true)
38 | }
39 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/BaseTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | import org.apache.commons.io.IOUtils
4 | import java.io.InputStream
5 | import java.nio.file.Path
6 | import java.nio.file.Paths
7 |
8 | interface BaseTest {
9 |
10 | fun getResourcePath(): String {
11 | val resourceDirectory: Path = Paths.get("src", "test", "resources")
12 | return resourceDirectory.toFile().absolutePath
13 | }
14 |
15 | fun getResourceAsStream(path: String): InputStream {
16 | return this::class.java.getResourceAsStream(path)
17 | }
18 |
19 | fun getResourceByteArray(path: String): ByteArray {
20 | return IOUtils.toByteArray(this::class.java.getResourceAsStream(path))
21 | }
22 | }
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/DataJpaRepoTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | import com.taskforce.superinvention.config.jpa.CriteriaConfig
4 | import com.taskforce.superinvention.config.jpa.JpaTestConfig
5 | import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
6 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
7 | import org.springframework.context.annotation.Import
8 | import org.springframework.test.context.ActiveProfiles
9 | import org.springframework.transaction.annotation.Transactional
10 |
11 | @DataJpaTest
12 | @Transactional
13 | @ActiveProfiles(TestEnv.TEST)
14 | @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
15 | @Import(value = [JpaTestConfig::class, CriteriaConfig::class])
16 | abstract class DataJpaRepoTest: BaseTest
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/IntegrationTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
4 | import org.springframework.boot.test.context.SpringBootTest
5 | import org.springframework.test.context.ActiveProfiles
6 | import org.springframework.transaction.annotation.Transactional
7 |
8 | @SpringBootTest
9 | @ActiveProfiles(TestEnv.TEST)
10 | @Transactional
11 | @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
12 | abstract class IntegrationTest: BaseTest
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/MockTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | import org.junit.jupiter.api.extension.ExtendWith
4 | import org.mockito.junit.jupiter.MockitoExtension
5 | import org.springframework.test.context.ActiveProfiles
6 |
7 | @ExtendWith(MockitoExtension::class)
8 | @ActiveProfiles(TestEnv.TEST)
9 | abstract class MockTest: BaseTest
10 |
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/MockkTest.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | import io.mockk.junit5.MockKExtension
4 | import org.junit.jupiter.api.extension.ExtendWith
5 | import org.springframework.test.context.ActiveProfiles
6 | import org.springframework.test.context.junit.jupiter.SpringExtension
7 |
8 | @ExtendWith(SpringExtension::class)
9 | @ActiveProfiles(TestEnv.TEST)
10 | abstract class MockkTest: BaseTest
--------------------------------------------------------------------------------
/src/test/kotlin/com/taskforce/superinvention/config/test/TestEnv.kt:
--------------------------------------------------------------------------------
1 | package com.taskforce.superinvention.config.test
2 |
3 | object TestEnv {
4 | const val TEST = "test"
5 | }
--------------------------------------------------------------------------------
/src/test/resources/img/animated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/animated.gif
--------------------------------------------------------------------------------
/src/test/resources/img/animated.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/animated.webp
--------------------------------------------------------------------------------
/src/test/resources/img/big-animated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/big-animated.gif
--------------------------------------------------------------------------------
/src/test/resources/img/large-size.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/large-size.jpg
--------------------------------------------------------------------------------
/src/test/resources/img/large-size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/large-size.png
--------------------------------------------------------------------------------
/src/test/resources/img/not-animated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/not-animated.gif
--------------------------------------------------------------------------------
/src/test/resources/img/not-animated.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/not-animated.webp
--------------------------------------------------------------------------------
/src/test/resources/img/test-large.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/test-large.jpg
--------------------------------------------------------------------------------
/src/test/resources/img/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TASK-FORCE/mannalga-api/c4b5566e633bca6409ab5e7be17397531a72c434/src/test/resources/img/test.jpg
--------------------------------------------------------------------------------