diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/auth/domain/Authority.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/auth/domain/Authority.kt index 8738c84b..520a46c8 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/auth/domain/Authority.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/auth/domain/Authority.kt @@ -10,7 +10,8 @@ enum class Authority( UNAUTHENTICATED("ROLE_UNAUTHENTICATED"), TEMP_USER("ROLE_TEMP_USER"), USER("ROLE_USER"), - ADMIN("ROLE_ADMIN") + ADMIN("ROLE_ADMIN"), + TEACHER("ROLE_TEACHER") ; } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/domain/Board.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/domain/Board.kt index ddbeb52e..16077938 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/domain/Board.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/domain/Board.kt @@ -2,6 +2,7 @@ package team.themoment.gsmNetworking.domain.board.domain import team.themoment.gsmNetworking.common.domain.BaseIdTimestampEntity import team.themoment.gsmNetworking.domain.comment.domain.Comment +import team.themoment.gsmNetworking.domain.like.domain.Like import team.themoment.gsmNetworking.domain.user.domain.User import javax.persistence.* import javax.persistence.FetchType.* @@ -24,5 +25,8 @@ class Board ( val author: User, @OneToMany(mappedBy = "board", fetch = LAZY, cascade = [CascadeType.ALL], orphanRemoval = true) - val comments: MutableList = ArrayList() + val comments: MutableList = ArrayList(), + + @OneToMany(mappedBy = "board", fetch = LAZY, cascade = [CascadeType.ALL], orphanRemoval = true) + val likes: MutableList = ArrayList() ): BaseIdTimestampEntity(); diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardInfoDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardInfoDto.kt index 1b45327f..4076d5ea 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardInfoDto.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardInfoDto.kt @@ -14,5 +14,6 @@ data class BoardInfoDto ( val author: AuthorDto, @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") val createdAt: LocalDateTime, - val comments: List + val comments: List, + val likeCount: Int ) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardListDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardListDto.kt index 22b9c575..c6c5ec55 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardListDto.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/dto/BoardListDto.kt @@ -2,13 +2,16 @@ package team.themoment.gsmNetworking.domain.board.dto import com.fasterxml.jackson.annotation.JsonFormat import team.themoment.gsmNetworking.domain.board.domain.BoardCategory +import team.themoment.gsmNetworking.domain.comment.dto.AuthorDto import java.time.LocalDateTime data class BoardListDto ( val id: Long, val title: String, val boardCategory: BoardCategory, - val authorName: String, + val author: AuthorDto, @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - val createdAt: LocalDateTime + val createdAt: LocalDateTime, + val commentCount: Int, + val likeCount: Int ) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/repository/BoardCustomRepositoryImpl.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/repository/BoardCustomRepositoryImpl.kt index 35d16261..650f6261 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/repository/BoardCustomRepositoryImpl.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/repository/BoardCustomRepositoryImpl.kt @@ -6,6 +6,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory import team.themoment.gsmNetworking.domain.board.domain.BoardCategory import team.themoment.gsmNetworking.domain.board.domain.QBoard.board import team.themoment.gsmNetworking.domain.board.dto.BoardListDto +import team.themoment.gsmNetworking.domain.comment.dto.AuthorDto class BoardCustomRepositoryImpl ( private val queryFactory: JPAQueryFactory @@ -15,11 +16,19 @@ class BoardCustomRepositoryImpl ( return queryFactory.select( Projections.constructor( BoardListDto::class.java, - board.id, - board.title, - board.boardCategory, - board.author.name, - board.createdAt + board.id, + board.title, + board.boardCategory, + Projections.constructor( + AuthorDto::class.java, + board.author.name, + board.author.generation, + board.author.profileUrl, + board.author.defaultImgNumber + ), + board.createdAt, + board.comments.size(), + board.likes.size() ) ) .from(board) @@ -31,13 +40,21 @@ class BoardCustomRepositoryImpl ( override fun findPageWithRecentBoard(pageSize: Long, boardCategory: BoardCategory?): List { return queryFactory.select( - Projections.constructor( - BoardListDto::class.java, - board.id, - board.title, - board.boardCategory, - board.author.name, - board.createdAt + Projections.constructor( + BoardListDto::class.java, + board.id, + board.title, + board.boardCategory, + Projections.constructor( + AuthorDto::class.java, + board.author.name, + board.author.generation, + board.author.profileUrl, + board.author.defaultImgNumber + ), + board.createdAt, + board.comments.size(), + board.likes.size() ) ) .from(board) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/service/impl/BoardService.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/service/impl/BoardService.kt index 80588c94..1954ab33 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/board/service/impl/BoardService.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/board/service/impl/BoardService.kt @@ -4,6 +4,8 @@ import org.springframework.http.HttpStatus import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import team.themoment.gsmNetworking.common.exception.ExpectedException +import team.themoment.gsmNetworking.domain.auth.domain.Authority +import team.themoment.gsmNetworking.domain.auth.repository.AuthenticationRepository import team.themoment.gsmNetworking.domain.board.domain.BoardCategory import team.themoment.gsmNetworking.domain.board.domain.Board import team.themoment.gsmNetworking.domain.board.dto.BoardInfoDto @@ -25,7 +27,8 @@ import team.themoment.gsmNetworking.domain.user.repository.UserRepository class BoardService ( private val boardRepository: BoardRepository, private val userRepository: UserRepository, - private val commentRepository: CommentRepository + private val commentRepository: CommentRepository, + private val authenticationRepository: AuthenticationRepository ) : SaveBoardUseCase, QueryBoardListUseCase, QueryBoardInfoUseCase { @@ -35,6 +38,14 @@ class BoardService ( val currentUser = userRepository.findByAuthenticationId(authenticationId) ?: throw ExpectedException("유저를 찾을 수 없습니다.", HttpStatus.NOT_FOUND) + val authentication = authenticationRepository.findById(authenticationId) + .orElseThrow { throw ExpectedException("유저의 권한 정보를 찾을 수 없습니다.", HttpStatus.NOT_FOUND) } + + if (boardSaveDto.boardCategory == BoardCategory.TEACHER + && authentication.authority != Authority.TEACHER) { + throw ExpectedException("선생님이 아닌 유저는 선생님 카테고리를 이용할 수 없습니다.", HttpStatus.NOT_FOUND) + } + val newBoard = Board( title = boardSaveDto.title, content = boardSaveDto.content, @@ -48,8 +59,15 @@ class BoardService ( id = savedBoard.id, title = savedBoard.title, boardCategory = savedBoard.boardCategory, - authorName = savedBoard.author.name, - createdAt = savedBoard.createdAt + author = AuthorDto( + name = savedBoard.author.name, + generation = savedBoard.author.generation, + profileUrl = savedBoard.author.profileUrl, + defaultImgNumber = savedBoard.author.defaultImgNumber + ), + createdAt = savedBoard.createdAt, + commentCount = 0, + likeCount = 0 ) } @@ -80,7 +98,8 @@ class BoardService ( defaultImgNumber = currentBoard.author.defaultImgNumber ), createdAt = currentBoard.createdAt, - comments = getFindComments(findComments) + comments = getFindComments(findComments), + likeCount = currentBoard.likes.size ) } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/like/controller/LikeController.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/controller/LikeController.kt new file mode 100644 index 00000000..4c729196 --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/controller/LikeController.kt @@ -0,0 +1,21 @@ +package team.themoment.gsmNetworking.domain.like.controller + +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import team.themoment.gsmNetworking.common.manager.AuthenticatedUserManager +import team.themoment.gsmNetworking.domain.like.dto.LikeStatusDto +import team.themoment.gsmNetworking.domain.like.service.ToggleLikeUseCase +import javax.validation.Valid + +@RestController +@RequestMapping("/api/v1/like") +class LikeController ( + private val toggleLikeUseCase: ToggleLikeUseCase, + private val authenticatedUserManager: AuthenticatedUserManager +) { + @PostMapping("/{boardId}") + fun toggleLike(@PathVariable boardId: Long): ResponseEntity { + val authenticationId = authenticatedUserManager.getName() + return ResponseEntity.ok(toggleLikeUseCase.likeToggle(boardId, authenticationId)) + } +} diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/like/domain/Like.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/domain/Like.kt new file mode 100644 index 00000000..d669738a --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/domain/Like.kt @@ -0,0 +1,19 @@ +package team.themoment.gsmNetworking.domain.like.domain + +import team.themoment.gsmNetworking.common.domain.BaseIdTimestampEntity +import team.themoment.gsmNetworking.domain.board.domain.Board +import team.themoment.gsmNetworking.domain.user.domain.User +import javax.persistence.* + + +@Entity +@Table(name = "board_like") +class Like ( + @ManyToOne + @JoinColumn(name = "user_id") + val user: User, + + @ManyToOne + @JoinColumn(name = "feed_id") + val board: Board, +): BaseIdTimestampEntity() diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/like/dto/LikeStatusDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/dto/LikeStatusDto.kt new file mode 100644 index 00000000..3c22d10e --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/dto/LikeStatusDto.kt @@ -0,0 +1,5 @@ +package team.themoment.gsmNetworking.domain.like.dto + +data class LikeStatusDto ( + val currentStatus: Boolean +) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/like/repository/LikeRepository.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/repository/LikeRepository.kt new file mode 100644 index 00000000..3aa1339e --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/repository/LikeRepository.kt @@ -0,0 +1,10 @@ +package team.themoment.gsmNetworking.domain.like.repository + +import org.springframework.data.jpa.repository.JpaRepository +import team.themoment.gsmNetworking.domain.board.domain.Board +import team.themoment.gsmNetworking.domain.like.domain.Like +import team.themoment.gsmNetworking.domain.user.domain.User + +interface LikeRepository : JpaRepository { + fun findByUserAndBoard(user: User, board: Board): Like? +} diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/like/service/ToggleLikeUseCase.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/service/ToggleLikeUseCase.kt new file mode 100644 index 00000000..6700cb2d --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/service/ToggleLikeUseCase.kt @@ -0,0 +1,7 @@ +package team.themoment.gsmNetworking.domain.like.service + +import team.themoment.gsmNetworking.domain.like.dto.LikeStatusDto + +interface ToggleLikeUseCase { + fun likeToggle(boardId: Long, authenticationId: Long): LikeStatusDto +} diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/like/service/impl/ToggleLikeUseCaseImpl.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/service/impl/ToggleLikeUseCaseImpl.kt new file mode 100644 index 00000000..6b686ad6 --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/like/service/impl/ToggleLikeUseCaseImpl.kt @@ -0,0 +1,42 @@ +package team.themoment.gsmNetworking.domain.like.service.impl + +import org.springframework.http.HttpStatus +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import team.themoment.gsmNetworking.common.exception.ExpectedException +import team.themoment.gsmNetworking.domain.board.repository.BoardRepository +import team.themoment.gsmNetworking.domain.like.domain.Like +import team.themoment.gsmNetworking.domain.like.dto.LikeStatusDto +import team.themoment.gsmNetworking.domain.like.repository.LikeRepository +import team.themoment.gsmNetworking.domain.like.service.ToggleLikeUseCase +import team.themoment.gsmNetworking.domain.user.repository.UserRepository + +@Service +class ToggleLikeUseCaseImpl ( + private val likeRepository: LikeRepository, + private val boardRepository: BoardRepository, + private val userRepository: UserRepository +) : ToggleLikeUseCase { + + @Transactional + override fun likeToggle(boardId: Long, authenticationId: Long): LikeStatusDto { + val currentUser = userRepository.findByAuthenticationId(authenticationId) + ?: throw ExpectedException("유저를 찾을 수 없습니다.", HttpStatus.NOT_FOUND) + + val board = boardRepository.findById(boardId) + .orElseThrow { ExpectedException("게시글을 찾을 수 없습니다.", HttpStatus.NOT_FOUND) } + + val like = likeRepository.findByUserAndBoard( + user = currentUser, + board = board + ) + + if (like != null) { + likeRepository.delete(like) + return LikeStatusDto(currentStatus = false) + } else { + likeRepository.save(Like(user = currentUser, board = board)) + return LikeStatusDto(currentStatus = true) + } + } +} diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/dto/MenteeInfoDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/dto/MenteeInfoDto.kt index 41f0d38d..87042aff 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/dto/MenteeInfoDto.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/dto/MenteeInfoDto.kt @@ -9,5 +9,9 @@ data class MenteeInfoDto ( val phoneNumber: String, - val generation: Int + val generation: Int, + + val defaultImgNumber: Int, + + val profileUrl: String? ) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/service/impl/MenteeService.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/service/impl/MenteeService.kt index 4888e3ca..be70a0e8 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/service/impl/MenteeService.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/mentee/service/impl/MenteeService.kt @@ -55,7 +55,9 @@ class MenteeService( name = userInfoDto.name, email = userInfoDto.email, phoneNumber = userInfoDto.phoneNumber, - generation = userInfoDto.generation + generation = userInfoDto.generation, + defaultImgNumber = userInfoDto.defaultImgNumber, + profileUrl = userInfoDto.profileUrl ) } } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/controller/UserController.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/controller/UserController.kt index cec00c98..5af5be05 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/controller/UserController.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/controller/UserController.kt @@ -3,18 +3,16 @@ package team.themoment.gsmNetworking.domain.user.controller import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PatchMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController import team.themoment.gsmNetworking.common.manager.AuthenticatedUserManager -import team.themoment.gsmNetworking.domain.user.dto.ProfileUrlRegistrationDto -import team.themoment.gsmNetworking.domain.user.dto.UserIdDto -import team.themoment.gsmNetworking.domain.user.dto.UserSimpleInfoDto -import team.themoment.gsmNetworking.domain.user.service.GenerateProfileUrlUseCase -import team.themoment.gsmNetworking.domain.user.service.QueryEmailByUserIdUseCase -import team.themoment.gsmNetworking.domain.user.service.QueryUserInfoByUserIdUseCase +import team.themoment.gsmNetworking.domain.user.dto.* +import team.themoment.gsmNetworking.domain.user.service.* +import javax.validation.Valid @RestController @RequestMapping("/api/v1/user") @@ -22,7 +20,9 @@ class UserController( private val authenticatedUserManager: AuthenticatedUserManager, private val generateProfileUrlUseCase: GenerateProfileUrlUseCase, private val queryUserInfoByUserIdUseCase: QueryUserInfoByUserIdUseCase, - private val queryEmailByUserIdUseCase: QueryEmailByUserIdUseCase + private val queryEmailByUserIdUseCase: QueryEmailByUserIdUseCase, + private val queryUserIsTeacherUsecase: QueryUserIsTeacherUsecase, + private val updateUserProfileNumberUseCase: UpdateUserProfileNumberUseCase ) { @PostMapping("/profile-url") @@ -42,4 +42,17 @@ class UserController( return ResponseEntity.ok(queryEmailByUserIdUseCase.queryEmailByUserId(email)) } + @GetMapping("/is-teacher") + fun queryIsTeacher(): ResponseEntity { + val authenticationId = authenticatedUserManager.getName() + return ResponseEntity.ok(queryUserIsTeacherUsecase.queryUserIsTeacher(authenticationId)) + } + + @PatchMapping("/profile-number") + fun updateProfileNumber(@RequestBody @Valid userProfileNumberDto: UserProfileNumberDto): ResponseEntity { + val authenticationId = authenticatedUserManager.getName() + updateUserProfileNumberUseCase.updateUserProfileNumber(userProfileNumberDto, authenticationId) + return ResponseEntity.ok().build() + } + } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/domain/User.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/domain/User.kt index 4394831d..d8f93ac7 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/domain/User.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/domain/User.kt @@ -3,6 +3,7 @@ package team.themoment.gsmNetworking.domain.user.domain import team.themoment.gsmNetworking.common.domain.BaseIdTimestampEntity import team.themoment.gsmNetworking.domain.board.domain.Board import team.themoment.gsmNetworking.domain.comment.domain.Comment +import team.themoment.gsmNetworking.domain.like.domain.Like import team.themoment.gsmNetworking.domain.mentor.domain.Mentor import team.themoment.gsmNetworking.domain.user.converter.EncryptConverter import javax.persistence.* @@ -45,7 +46,10 @@ class User( val boards: MutableList = ArrayList(), @OneToMany(mappedBy = "author", cascade = [CascadeType.ALL], orphanRemoval = true) - val comments: MutableList = ArrayList() + val comments: MutableList = ArrayList(), + + @OneToMany(mappedBy = "user", cascade = [CascadeType.ALL], orphanRemoval = true) + val likes: MutableList = ArrayList() ) : BaseIdTimestampEntity() { @@ -55,7 +59,12 @@ class User( companion object { private fun generateRandomNumber(): Int { - return Random.nextInt(0, 5) + return Random.nextInt(0, 6) } } + + fun updateProfileNumber(defaultImgNumber: Int) { + this.defaultImgNumber = defaultImgNumber + } + } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserInfoDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserInfoDto.kt index bcb1f53b..9e0654cb 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserInfoDto.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserInfoDto.kt @@ -14,5 +14,7 @@ data class UserInfoDto( val snsUrl: String?, - val profileUrl: String? + val profileUrl: String?, + + val defaultImgNumber: Int ) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserIsTeacherDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserIsTeacherDto.kt new file mode 100644 index 00000000..4a9cf841 --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserIsTeacherDto.kt @@ -0,0 +1,5 @@ +package team.themoment.gsmNetworking.domain.user.dto + +data class UserIsTeacherDto ( + val isTeacher: Boolean +) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserProfileNumberDto.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserProfileNumberDto.kt new file mode 100644 index 00000000..86cfa42b --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/dto/UserProfileNumberDto.kt @@ -0,0 +1,10 @@ +package team.themoment.gsmNetworking.domain.user.dto + +import javax.validation.constraints.NotNull +import javax.validation.constraints.Size + +data class UserProfileNumberDto ( + @NotNull + @Size(min = 0, max = 6) + val profileNumber: Int +) diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/QueryUserIsTeacherUsecase.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/QueryUserIsTeacherUsecase.kt new file mode 100644 index 00000000..4c54d2d2 --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/QueryUserIsTeacherUsecase.kt @@ -0,0 +1,7 @@ +package team.themoment.gsmNetworking.domain.user.service + +import team.themoment.gsmNetworking.domain.user.dto.UserIsTeacherDto + +interface QueryUserIsTeacherUsecase { + fun queryUserIsTeacher(authenticationId: Long): UserIsTeacherDto +} diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/UpdateUserProfileNumberUseCase.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/UpdateUserProfileNumberUseCase.kt new file mode 100644 index 00000000..60a1835d --- /dev/null +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/UpdateUserProfileNumberUseCase.kt @@ -0,0 +1,7 @@ +package team.themoment.gsmNetworking.domain.user.service + +import team.themoment.gsmNetworking.domain.user.dto.UserProfileNumberDto + +interface UpdateUserProfileNumberUseCase { + fun updateUserProfileNumber(userProfileNumberDto: UserProfileNumberDto, authenticationId: Long) +} diff --git a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/impl/UserService.kt b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/impl/UserService.kt index 37c52eee..611f29ea 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/impl/UserService.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/domain/user/service/impl/UserService.kt @@ -4,6 +4,8 @@ import org.springframework.http.HttpStatus import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import team.themoment.gsmNetworking.common.exception.ExpectedException +import team.themoment.gsmNetworking.domain.auth.domain.Authority +import team.themoment.gsmNetworking.domain.auth.repository.AuthenticationRepository import team.themoment.gsmNetworking.domain.mentee.repository.MenteeRepository import team.themoment.gsmNetworking.domain.user.domain.User import team.themoment.gsmNetworking.domain.user.dto.* @@ -13,14 +15,17 @@ import team.themoment.gsmNetworking.domain.user.service.* @Service class UserService( private val userRepository: UserRepository, - private val menteeRepository: MenteeRepository + private val menteeRepository: MenteeRepository, + private val authenticationRepository: AuthenticationRepository ) : GenerateUserUseCase, ModifyUserInfoByIdUseCase, GenerateProfileUrlUseCase, DeleteUserInfoByIdUseCase, QueryUserInfoByIdUseCase, QueryUserInfoByUserIdUseCase, - QueryEmailByUserIdUseCase { + QueryEmailByUserIdUseCase, + QueryUserIsTeacherUsecase, + UpdateUserProfileNumberUseCase { @Transactional override fun generateUser(userSaveInfoDto: UserSaveInfoDto, authenticationId: Long): User { @@ -141,7 +146,8 @@ class UserService( email = user.email, phoneNumber = user.phoneNumber, snsUrl = user.snsUrl, - profileUrl = user.profileUrl + profileUrl = user.profileUrl, + defaultImgNumber = user.defaultImgNumber ) } @@ -167,4 +173,22 @@ class UserService( userId = user.id ) } + + @Transactional(readOnly = true) + override fun queryUserIsTeacher(authenticationId: Long): UserIsTeacherDto { + val authentication = authenticationRepository.findById(authenticationId) + .orElseThrow { throw ExpectedException("유저의 권한 정보를 찾을 수 없습니다.", HttpStatus.NOT_FOUND) } + + return UserIsTeacherDto(isTeacher = authentication.authority == Authority.TEACHER) + + } + + @Transactional + override fun updateUserProfileNumber(userProfileNumberDto: UserProfileNumberDto, authenticationId: Long) { + val user = userRepository.findByAuthenticationId(authenticationId) + ?: throw ExpectedException("유저를 찾을 수 없습니다.", HttpStatus.NOT_FOUND) + + user.updateProfileNumber(userProfileNumberDto.profileNumber) + userRepository.save(user) + } } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/global/security/SecurityConfig.kt b/src/main/kotlin/team/themoment/gsmNetworking/global/security/SecurityConfig.kt index 3a6a86f7..e4ccc1a6 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/global/security/SecurityConfig.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/global/security/SecurityConfig.kt @@ -62,19 +62,22 @@ class SecurityConfig( http.authorizeHttpRequests() // /mentor .mvcMatchers("/api/v1/mentor/*").hasAnyRole( - Authority.USER.name + Authority.USER.name, + Authority.TEACHER.name ) .mvcMatchers(HttpMethod.GET, "/api/v1/mentor").hasAnyRole( Authority.TEMP_USER.name, Authority.USER.name, - Authority.ADMIN.name + Authority.ADMIN.name, + Authority.TEACHER.name ) .mvcMatchers(HttpMethod.POST, "/api/v1/mentor").hasAnyRole( Authority.UNAUTHENTICATED.name, Authority.TEMP_USER.name ) .mvcMatchers("/api/v1/mentor/my").hasAnyRole( - Authority.USER.name + Authority.USER.name, + Authority.TEACHER.name ) // /tempMentor .mvcMatchers(HttpMethod.GET, "api/v1/temp-mentor/search/*").hasAnyRole( @@ -107,20 +110,36 @@ class SecurityConfig( Authority.USER.name, Authority.TEMP_USER.name ) + // /user/is-teacher + .mvcMatchers("/api/v1/user/is-teacher").hasAnyRole( + Authority.TEACHER.name, + Authority.TEMP_USER.name, + Authority.USER.name + ) + // /user/profile-url + .mvcMatchers("/api/v1/user/profile-url").hasAnyRole( + Authority.TEMP_USER.name, + Authority.USER.name, + Authority.TEACHER.name + ) // /user .mvcMatchers("/api/v1/user/**").hasAnyRole( - Authority.USER.name + Authority.USER.name, + Authority.TEACHER.name ) // /file .mvcMatchers("/api/v1/file").hasAnyRole( - Authority.USER.name + Authority.USER.name, + Authority.TEMP_USER.name, + Authority.TEACHER.name ) // /gwangya .mvcMatchers(HttpMethod.GET, "/api/v1/gwangya/token").hasAnyRole( Authority.UNAUTHENTICATED.name, Authority.TEMP_USER.name, Authority.USER.name, - Authority.ADMIN.name + Authority.ADMIN.name, + Authority.TEACHER.name, ) .mvcMatchers(HttpMethod.DELETE, "/api/v1/gwangya/*").hasAnyRole( Authority.ADMIN.name diff --git a/src/main/kotlin/team/themoment/gsmNetworking/global/security/oauth/CustomOauth2UserService.kt b/src/main/kotlin/team/themoment/gsmNetworking/global/security/oauth/CustomOauth2UserService.kt index 3ef3ec57..91fa33a4 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/global/security/oauth/CustomOauth2UserService.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/global/security/oauth/CustomOauth2UserService.kt @@ -1,5 +1,6 @@ package team.themoment.gsmNetworking.global.security.oauth +import org.springframework.beans.factory.annotation.Value import team.themoment.gsmNetworking.domain.auth.domain.Authentication import team.themoment.gsmNetworking.domain.auth.domain.Authority import team.themoment.gsmNetworking.domain.auth.repository.AuthenticationRepository @@ -21,6 +22,9 @@ class CustomOauth2UserService( private val authenticationRepository: AuthenticationRepository, ) : OAuth2UserService { + @Value("\${gsm.teacher.email}") + private val GSM_TEACHER_EMAIL: String = "" + override fun loadUser(userRequest: OAuth2UserRequest): OAuth2User { val delegateOauth2UserService = DefaultOAuth2UserService() val oauth2User = delegateOauth2UserService.loadUser(userRequest) @@ -50,6 +54,10 @@ class CustomOauth2UserService( */ private fun validateEmailDomain(email: String): String { val regex = Regex("^[A-Za-z0-9._%+-]+@gsm\\.hs\\.kr$") + + + if (email == GSM_TEACHER_EMAIL) return email + if (!regex.matches(email)) { throw OAuth2AuthenticationException( OAuth2Error( @@ -58,6 +66,7 @@ class CustomOauth2UserService( "요청한 이메일이 GSM 학생용 이메일이 아닙니다." ) } + return email } diff --git a/src/main/kotlin/team/themoment/gsmNetworking/global/socket/interceptor/StompInterceptor.kt b/src/main/kotlin/team/themoment/gsmNetworking/global/socket/interceptor/StompInterceptor.kt index e6c8f07e..cd49c1cc 100644 --- a/src/main/kotlin/team/themoment/gsmNetworking/global/socket/interceptor/StompInterceptor.kt +++ b/src/main/kotlin/team/themoment/gsmNetworking/global/socket/interceptor/StompInterceptor.kt @@ -31,17 +31,15 @@ class StompInterceptor( override fun preSend(message: Message<*>, channel: MessageChannel): Message<*>? { val accessor: StompHeaderAccessor = StompHeaderAccessor.wrap(message) - if (StompCommand.CONNECT == accessor.command) { - handleConnect(accessor) - } else if (StompCommand.DISCONNECT == accessor.command) { - handleDisconnect(accessor) - } else if (StompCommand.SUBSCRIBE == accessor.command) { - handleSubscribe(accessor) - } else if (StompCommand.UNSUBSCRIBE == accessor.command) { - handleUnsubscribe(accessor) - } else if (StompCommand.SEND == accessor.command) { - handleSend(accessor) + when (accessor.command) { + StompCommand.CONNECT -> handleConnect(accessor) + StompCommand.DISCONNECT -> handleDisconnect(accessor) + StompCommand.SUBSCRIBE -> handleSubscribe(accessor) + StompCommand.UNSUBSCRIBE -> handleUnsubscribe(accessor) + StompCommand.SEND -> handleSend(accessor) + else -> {} } + return MessageBuilder.createMessage(message.payload, accessor.messageHeaders) } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index f228fff1..5b097a09 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -109,3 +109,5 @@ gsm: student: account: otherwise-redirect: http://localhost:8080/signup + teacher: + email: gsmnetworking@gsm.hs.kr \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index d3936479..c1ec7a56 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -105,3 +105,5 @@ gsm: student: account: otherwise-redirect: ${REDIRECT_FOR_NON_GSM_STUDENT_ACCOUNT} + teacher: + email: gsmnetworking@gsm.hs.kr