Skip to content

Commit

Permalink
Github Webhook Controller 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
gidskql6671 committed May 28, 2024
1 parent 37f2c7a commit a0e7844
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package knu.dong.onedayonebaek.github.controller

import knu.dong.onedayonebaek.common.exception.NotFoundException
import knu.dong.onedayonebaek.github.dto.CommitWebhookRequest
import knu.dong.onedayonebaek.problem.service.ProblemService
import knu.dong.onedayonebaek.user.service.UserService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/github/webhook")
class GithubWebhookController(
private val userService: UserService,
private val problemService: ProblemService
) {

@PostMapping("/push")
fun push(
@RequestHeader(value = "X-GitHub-Event") githubEvent: String,
@RequestBody request: CommitWebhookRequest
): ResponseEntity<String> {
if (githubEvent == "ping") {
return ResponseEntity.ok().body("valid webhook")
} else if (githubEvent != "push") {
return ResponseEntity.badRequest().body("Only allowed if 'X-Github-Event' is 'push'.")
}

val loginId: String = request.pusher.name

val commits: List<CommitWebhookRequest.Commit> = request.commits
val user = userService.findUserByLoginId(loginId).orElseThrow { NotFoundException() }

problemService.addProblems(user, commits)

return ResponseEntity.ok().build()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package knu.dong.onedayonebaek.github.dto

import java.time.LocalDateTime

data class CommitWebhookRequest(
val pusher: Pusher,
val commits: List<Commit> = ArrayList()
) {
data class Commit (val url: String, val message: String, val timestamp: LocalDateTime)
data class Pusher (val name: String, val email: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import jakarta.servlet.ServletRequest
import jakarta.servlet.ServletResponse
import jakarta.servlet.http.HttpServletRequest
import knu.dong.onedayonebaek.common.exception.AccessTokenExpiredException
import knu.dong.onedayonebaek.common.exception.NotFoundException
import knu.dong.onedayonebaek.oauth.service.TokenService
import knu.dong.onedayonebaek.user.repository.UserRepository
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
Expand Down Expand Up @@ -43,7 +44,7 @@ class JwtAuthFilter(
if (accessToken != null && tokenService.verifyToken(accessToken)) {
val loginId = tokenService.getUid(accessToken)

val user = userRepository.findByLoginId(loginId)
val user = userRepository.findByLoginId(loginId).orElseThrow { NotFoundException() }

SecurityContextHolder.getContext().authentication =
UsernamePasswordAuthenticationToken(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ interface ProblemRepository: JpaRepository<Problem, Long> {
@EntityGraph(attributePaths = ["user"])
fun findAllBySolvedDateAndUserIsIn(date: LocalDate, users: List<User>): List<Problem>

fun existsByCommitUrl(commitUrl: String): Boolean

}
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
package knu.dong.onedayonebaek.problem.service

import io.github.oshai.kotlinlogging.KotlinLogging
import knu.dong.onedayonebaek.user.domain.User
import knu.dong.onedayonebaek.github.dto.CommitWebhookRequest
import knu.dong.onedayonebaek.problem.domain.Problem
import knu.dong.onedayonebaek.problem.dto.ProblemDto
import knu.dong.onedayonebaek.problem.dto.toProblemDto
import knu.dong.onedayonebaek.problem.repository.ProblemRepository
import knu.dong.onedayonebaek.user.domain.User
import knu.dong.onedayonebaek.user.repository.UserRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
import java.time.YearMonth
import java.util.regex.Pattern
import java.util.stream.Collectors

private val myLogger = KotlinLogging.logger {}

@Service
@Transactional(readOnly = true)
class ProblemService(
private val problemRepository: ProblemRepository,
private val userRepository: UserRepository
) {
private val pattern = Pattern.compile("^\\[(?<rank>.*)] Title: (?<title>.*), Time:.*")

fun getProblems(user: User, yearMonth: YearMonth): List<ProblemDto> {
val start = yearMonth.atDay(1)
Expand Down Expand Up @@ -45,4 +51,34 @@ class ProblemService(
.map { it.toProblemDto() }
.collect(Collectors.toList())
}

@Transactional
fun addProblems(user: User, commitRequests: List<CommitWebhookRequest.Commit>) {
val commits = commitRequests
.stream()
.filter { !problemRepository.existsByCommitUrl(it.url) }
.filter { pattern.matcher(it.message).matches() }
.map {
var rank = ""
var title = ""

val matcher = pattern.matcher(it.message)
if (matcher.matches()) {
rank = matcher.group("rank")
title = matcher.group("title")
}

Problem(
user = user,
solvedDate = it.timestamp.plusHours(9).toLocalDate(),
commitUrl = it.url,
title = title,
problemRank = rank
)
}
.toList()

problemRepository.saveAll(commits)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package knu.dong.onedayonebaek.user.repository

import knu.dong.onedayonebaek.user.domain.User
import org.springframework.data.jpa.repository.JpaRepository
import java.util.*

interface UserRepository: JpaRepository<User, Long> {

fun findByLoginId(loginId: String): User
fun findByLoginId(loginId: String): Optional<User>
fun getByLoginId(loginId: String): User
fun existsByLoginId(loginId: String): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package knu.dong.onedayonebaek.user.service

import knu.dong.onedayonebaek.user.domain.User
import knu.dong.onedayonebaek.user.repository.UserRepository
import org.springframework.stereotype.Service
import java.util.*

@Service
class UserService(
private val userRepository: UserRepository
) {

fun findUserByLoginId(loginId: String): Optional<User> = userRepository.findByLoginId(loginId)
}

0 comments on commit a0e7844

Please sign in to comment.