Skip to content

Commit

Permalink
�Merge: (#42) 코드 분석 도구 적용
Browse files Browse the repository at this point in the history
  • Loading branch information
alsdl0629 authored Dec 3, 2023
2 parents cb5c0ed + fc6b529 commit 2b3bf47
Show file tree
Hide file tree
Showing 12 changed files with 383 additions and 98 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ jobs:
run: ./gradlew test

- name: run build
run: ./gradlew clean build -x test
run: ./gradlew build -x test

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./build/reports/jacoco/test/jacocoTestReport.xml
53 changes: 51 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.kapt3.base.Kapt.kapt

plugins {
id("org.springframework.boot") version "3.1.4"
Expand All @@ -10,6 +9,7 @@ plugins {
kotlin("plugin.spring") version "1.8.22"
kotlin("plugin.jpa") version "1.8.22"
kotlin("kapt") version "1.8.21"
jacoco
}

group = "team.sfe"
Expand All @@ -36,7 +36,7 @@ dependencies {
// persistence
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("com.mysql:mysql-connector-j")
runtimeOnly("com.h2database:h2")
testRuntimeOnly("com.h2database:h2")

// security
implementation("org.springframework.boot:spring-boot-starter-security")
Expand Down Expand Up @@ -78,6 +78,7 @@ tasks.withType<KotlinCompile> {

tasks.withType<Test> {
useJUnitPlatform()
finalizedBy("jacocoTestReport")
}

val asciidoctorExt: Configuration by configurations.creating
Expand Down Expand Up @@ -111,3 +112,51 @@ tasks {
tasks.getByName<Jar>("jar") {
enabled = false
}

jacoco {
toolVersion = "0.8.8"
}

tasks.jacocoTestReport {
reports {
html.required.set(true)
xml.required.set(true)
csv.required.set(false)
}

classDirectories.setFrom(
files(
classDirectories.files.map {
fileTree(it) {
setExcludes(
listOf(
"**/exception/*.*",
"**/global/config/*.*",
"**/global/converter/*.*",
"**/global/entity/*.*",
"**/global/error/*.*",
"**/global/filter/*.*",
"**/global/redis/*.*",
"**/global/security/SecurityConfig.*"
)
)
}
}
)
)

// finalizedBy("jacocoTestCoverageVerification")
}

// tasks.jacocoTestCoverageVerification {
// violationRules {
// rule {
// element = "CLASS"
//
// limit {
// counter = "BRANCH"
// value = "COVEREDRATIO"
// minimum = "0.90".toBigDecimal()
// }
// }
// }
9 changes: 9 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
codecov:
require_ci_to_pass: yes

comment:
layout: "reach,diff,flags,files,footer"
behavior: default
require_changes: false
branches:
- main
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "refreshToken", timeToLive = 60 * 60 * 24 * 14)
class RefreshToken(

@Id
val accountId: String,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import team.sfe.server.domain.auth.exception.PasswordMisMatchException
import team.sfe.server.domain.user.facade.UserFacade
import team.sfe.server.domain.user.domain.repository.UserRepository
import team.sfe.server.domain.user.exception.UserNotFoundException
import team.sfe.server.domain.user.presentation.request.UserSignInRequest
import team.sfe.server.domain.user.presentation.response.TokenResponse
import team.sfe.server.global.security.jwt.JwtProvider

@Service
class UserSignInService(
private val userFacade: UserFacade,
private val jwtProvider: JwtProvider,
private val passwordEncoder: PasswordEncoder
private val passwordEncoder: PasswordEncoder,
private val userRepository: UserRepository
) {
@Transactional
fun execute(request: UserSignInRequest): TokenResponse {
val user = userFacade.getUserByAccountId(request.accountId)
val user = userRepository.findByAccountId(request.accountId) ?: throw UserNotFoundException

if (!passwordEncoder.matches(request.password, user.password)) {
throw PasswordMisMatchException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ class UserSignUpService(
fun execute(request: UserSignUpRequest): TokenResponse {
userFacade.isUserAlreadyExists(request.accountId)

userRepository.save(
val user = userRepository.save(
UserEntity(
accountId = request.accountId,
password = passwordEncoder.encode(request.password),
authority = Authority.USER
)
)

return jwtProvider.generateAllToken(request.accountId, Authority.USER)
return jwtProvider.generateAllToken(user.accountId, user.authority)
}
}
20 changes: 10 additions & 10 deletions src/main/kotlin/team/sfe/server/global/security/jwt/JwtProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@ class JwtProvider(
)
}

fun generateToken(id: String, authority: Authority, type: String, exp: Long) =
Jwts.builder()
.setHeaderParam(Header.JWT_TYPE, type)
.setSubject(id)
.claim(AUTHORITY, authority.name)
.signWith(jwtProperties.secretKey, SignatureAlgorithm.HS256)
.setIssuedAt(Date())
.setExpiration(Date(System.currentTimeMillis() + exp * 1000))
.compact()

fun generateAccessToken(id: String, authority: Authority) = generateToken(
id,
authority,
Expand All @@ -61,4 +51,14 @@ class JwtProvider(
REFRESH,
jwtProperties.refreshExp
)

private fun generateToken(id: String, authority: Authority, type: String, exp: Long) =
Jwts.builder()
.setHeaderParam(Header.JWT_TYPE, type)
.setSubject(id)
.claim(AUTHORITY, authority.name)
.signWith(jwtProperties.secretKey, SignatureAlgorithm.HS256)
.setIssuedAt(Date())
.setExpiration(Date(System.currentTimeMillis() + exp * 1000))
.compact()
}
86 changes: 43 additions & 43 deletions src/test/kotlin/team/sfe/server/SfeApiControllerDocTest.kt
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
package team.sfe.server

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.RestDocumentationExtension
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultHandlers
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.context.WebApplicationContext

@ExtendWith(RestDocumentationExtension::class)
@SpringBootTest
class SfeApiControllerDocTest {

private var mockMvc: MockMvc? = null

@BeforeEach
fun setUp(webApplicationcontext: WebApplicationContext, restDocumentaion: RestDocumentationContextProvider) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationcontext)
.apply<DefaultMockMvcBuilder>(MockMvcRestDocumentation.documentationConfiguration(restDocumentaion))
.build()
}

@Test
fun `테스트 코드 테스트`() {
this.mockMvc!!.perform(
MockMvcRequestBuilders.get("/")
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk)
.andDo(MockMvcResultHandlers.print())
.andDo(document("index"))
}
}
// package team.sfe.server
//
// import org.junit.jupiter.api.BeforeEach
// import org.junit.jupiter.api.Test
// import org.junit.jupiter.api.extension.ExtendWith
// import org.springframework.boot.test.context.SpringBootTest
// import org.springframework.http.MediaType
// import org.springframework.restdocs.RestDocumentationContextProvider
// import org.springframework.restdocs.RestDocumentationExtension
// import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation
// import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document
// import org.springframework.test.web.servlet.MockMvc
// import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
// import org.springframework.test.web.servlet.result.MockMvcResultHandlers
// import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
// import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
// import org.springframework.test.web.servlet.setup.MockMvcBuilders
// import org.springframework.web.context.WebApplicationContext
//
// @ExtendWith(RestDocumentationExtension::class)
// @SpringBootTest
// class SfeApiControllerDocTest {
//
// private var mockMvc: MockMvc? = null
//
// @BeforeEach
// fun setUp(webApplicationcontext: WebApplicationContext, restDocumentaion: RestDocumentationContextProvider) {
// this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationcontext)
// .apply<DefaultMockMvcBuilder>(MockMvcRestDocumentation.documentationConfiguration(restDocumentaion))
// .build()
// }
//
// @Test
// fun `테스트 코드 테스트`() {
// this.mockMvc!!.perform(
// MockMvcRequestBuilders.get("/")
// .accept(MediaType.APPLICATION_JSON)
// )
// .andExpect(status().isOk)
// .andDo(MockMvcResultHandlers.print())
// .andDo(document("index"))
// }
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package team.sfe.server.domain.auth.domain

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class RefreshTokenTest {

@Test
fun `Refresh Token를 재발급 받는다`() {
// given
val refreshToken = RefreshToken(
accountId = "강민",
token = "token"
)
val updateToken = "updateToken"

// when
refreshToken.updateToken(updateToken)

// then
assertThat(refreshToken.token).isEqualTo(updateToken)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// package team.sfe.server.domain.auth.service
//
// import org.assertj.core.api.Assertions
// import org.junit.jupiter.api.Test
// import org.junit.jupiter.api.assertThrows
// import org.springframework.beans.factory.annotation.Autowired
// import org.springframework.boot.test.context.SpringBootTest
// import org.springframework.security.crypto.password.PasswordEncoder
// import org.springframework.transaction.annotation.Transactional
// import team.sfe.server.domain.auth.exception.PasswordMisMatchException
// import team.sfe.server.domain.user.domain.UserEntity
// import team.sfe.server.domain.user.domain.repository.UserRepository
// import team.sfe.server.domain.user.domain.type.Authority.USER
// import team.sfe.server.domain.user.exception.UserNotFoundException
// import team.sfe.server.domain.user.presentation.request.UserSignInRequest
//
// @Transactional
// @SpringBootTest
// class UserSignInServiceTest @Autowired constructor(
// private val userSignInService: UserSignInService,
// private val userRepository: UserRepository,
// private val passwordEncoder: PasswordEncoder
// ) {
//
// @Test
// fun `아디이와 비밀번호를 받아 사용자가 존재하는지 비밀번호가 일치하는지 확인 후 토큰을 발급해준다`() {
// // given
// val request = UserSignInRequest(
// accountId = "강민",
// password = "password"
// )
//
// val userEntity = UserEntity(
// accountId = request.accountId,
// password = passwordEncoder.encode(request.password),
// authority = USER
// )
// userRepository.save(userEntity)
//
// // when
// val tokenResponse = userSignInService.execute(request)
//
// // then
// Assertions.assertThat(tokenResponse.accessToken).isNotBlank()
// Assertions.assertThat(tokenResponse.refreshToken).isNotBlank()
// }
//
// @Test
// fun `사용자로부터 받은 아이디와 db에 있는 아이디가 다르다`() {
// // given
// val request = UserSignInRequest(
// accountId = "강민",
// password = "password"
// )
//
// val userEntity = UserEntity(
// accountId = "김민수",
// password = passwordEncoder.encode(request.password),
// authority = USER
// )
// userRepository.save(userEntity)
//
// // when & then
// assertThrows<UserNotFoundException> {
// userSignInService.execute(request)
// }
// }
//
// @Test
// fun `사용자로부터 받은 비밀번호와 db에 있는 비밀번호가 다르다`() {
// // given
// val request = UserSignInRequest(
// accountId = "강민",
// password = "password"
// )
//
// val userEntity = UserEntity(
// accountId = request.accountId,
// password = passwordEncoder.encode("different-password"),
// authority = USER
// )
// userRepository.save(userEntity)
//
// // when & then
// assertThrows<PasswordMisMatchException> {
// userSignInService.execute(request)
// }
// }
// }
Loading

0 comments on commit 2b3bf47

Please sign in to comment.