22 Commits

Author SHA1 Message Date
Hanbin Lee
dbf8b046b0 [#33] test: 불필요한 요소 제거 테스트 2023-03-12 19:20:39 +09:00
Hanbin Lee
6f183e38ec [#33] fix: jenkinsfile 수정 2023-03-12 19:15:50 +09:00
Hanbin Lee
2c8b4c9a09 [#33] fix: jenkinsfile, flyway 설정내용 수정 2023-03-12 18:57:09 +09:00
Hanbin Lee
c0fcefa8c0 [#33] test: info만 실행 테스트 2023-03-12 18:23:58 +09:00
Hanbin Lee
6036bd63ad [#33] test: info, validate 진행 테스트(build 생략) 2023-03-12 18:11:31 +09:00
Hanbin Lee
cb5179abd7 [#33] test: info, validate 진행 테스트 2023-03-12 18:11:06 +09:00
Hanbin Lee
9e376bfefb [#33] fix: locations workspace 기준으로 변경 2023-03-12 18:06:58 +09:00
Hanbin Lee
f4b11c755c [#33] fix: flyway credentialsId 추가 2023-03-12 17:55:46 +09:00
Hanbin Lee
af1a95b1c7 [#33] fix: flyway runner commandLineArgs 수정 2023-03-12 17:48:19 +09:00
Hanbin Lee
8cc64c879f [#33] fix: flyway runner installation name setting 2023-03-12 17:46:21 +09:00
Hanbin Lee
e08c02a99a [#33] fix: flywayrunner plugin 문법 수정 2023-03-12 17:39:30 +09:00
Hanbin Lee
13566e1f86 [#33] test: jenkins flyway runner 테스트 2023-03-12 17:38:15 +09:00
Hanbin Lee
0210499e66 [#33] modify: migration shell script 수정 2023-03-04 00:31:14 +09:00
Hanbin Lee
42c8b3df14 [#33] test: migration > test > build 테스트 2023-03-03 01:28:34 +09:00
Hanbin Lee
54c4481031 [#33] test: DB Migration test 2023-03-03 00:58:50 +09:00
Hanbin Lee
2d142eb829 [#33] test: jenkins 출력 테스트 2023-03-03 00:19:30 +09:00
Hanbin Lee
09b6beee53 [#33] test: flyway migration 작업 테스트 2023-03-02 02:07:06 +09:00
Hanbin Lee
a39084a11a [#33] test: jenkins cloud server 구축 및 테스트2 2023-03-02 02:01:18 +09:00
Hanbin Lee
1beaaad422 [#33] test: jenkins cloud server 구축 및 테스트 2023-03-02 01:57:54 +09:00
Hanbin Lee
826cfb0eaa Merge branch 'main' into feature/33 2023-02-23 00:30:15 +09:00
Hanbin Lee
37169355da Merge pull request #35 from beaniejoy/feature/34
JPA Auditing 기능 수정
2023-02-23 00:28:28 +09:00
Hanbin Lee
3e7b928d8f [#34] feat: JPA Auditing 기능 수정
- auditor에 Security Authentication 적용(createdBy, updatedBy)
- BaseEntity, BaseTimeEntity 분리
- AuditingConfig 파일 common 모듈 내 공통화(including AuditorAware)
- DDL created_by, updated_by type 변경 (varchar(20) > varchar(320), email 최대크기로 설정)
2023-02-20 00:40:37 +09:00
30 changed files with 146 additions and 105 deletions

View File

@@ -1,24 +1,25 @@
pipeline { pipeline {
agent any agent any
tools {
jdk("openjdk-17")
}
stages { stages {
stage('Init') { stage('Init') {
steps { steps {
sh 'printenv' script {
sh 'whoami'
sh 'printenv'
migration_script = './script/db_migration.sh' FLYWAY_CONFIG = '/home/ec2-user/flyway/flyway.conf'
}
} }
} }
stage('DB Migrate') { stage('DB Migrate') {
steps { steps {
sh """ flywayrunner installationName: 'flywaytool-jenkins',
chmod 755 ${migration_script} flywayCommand: 'info migrate validate',
/bin/bash ${migration_script} commandLineArgs: "-configFiles=${FLYWAY_CONFIG}",
""" credentialsId: 'ecb29499-7272-4e8b-b3ab-a7a3ab7eafab',
locations: "filesystem:${WORKSPACE}/db/migration"
} }
} }

View File

@@ -6,10 +6,18 @@
<br> <br>
## Specification ## Specification
- java 17 - Lang
- kotlin 1.6.21 - java 17
- Spring Boot 2.7.0 - kotlin 1.6.21
- MySQL 8.0.21 - Framework
- Spring Boot 2.7.0
- DB
- MySQL 8.0.21
- Flyway(migration)
- CI/CD
- Jenkins
- Cloud Server
- AWS Lightsail(Amazon Linux2)
<br> <br>

View File

@@ -19,8 +19,7 @@ flyway {
baselineDescription = "Start Flyway Migration!" baselineDescription = "Start Flyway Migration!"
baselineOnMigrate = true baselineOnMigrate = true
baselineVersion = "000" baselineVersion = "000"
locations = arrayOf("filesystem:./migration", "filesystem:./seed") configFiles = arrayOf(System.getProperty("config") ?: "flyway.conf")
configFiles = arrayOf("conf/flyway.conf")
cleanDisabled = false // activate flywayClean cleanDisabled = false // activate flywayClean
ignoreMigrationPatterns = arrayOf("*:pending") // ignore validating pending(대기) state ignoreMigrationPatterns = arrayOf("*:pending") // ignore validating pending(대기) state
} }

View File

@@ -1,4 +0,0 @@
flyway.url=jdbc:mysql://localhost:3306/dongne?autoreconnect=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
flyway.user=root
flyway.password=beaniejoy
flyway.driver=com.mysql.cj.jdbc.Driver

10
db/flyway.conf Normal file
View File

@@ -0,0 +1,10 @@
flyway.url=jdbc:mysql://localhost:3306/dongne?autoreconnect=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
flyway.user=root
flyway.password=beaniejoy
flyway.driver=com.mysql.cj.jdbc.Driver
flyway.locations=filesystem:db/migration,db/seed
flyway.baselineOnMigrate=true
flyway.baselineVersion=000
# flyway.ignoreMigrationPatterns=*:pending
flyway.cleanDisabled=false

View File

@@ -6,8 +6,8 @@ CREATE TABLE `cafe` (
`total_rate` float NOT NULL COMMENT '카페 종합 평가 점수', `total_rate` float NOT NULL COMMENT '카페 종합 평가 점수',
`description` varchar(255) COMMENT '카페 상세설명', `description` varchar(255) COMMENT '카페 상세설명',
`created_at` datetime NOT NULL COMMENT '카페 등록날짜', `created_at` datetime NOT NULL COMMENT '카페 등록날짜',
`created_by` varchar(20) NOT NULL COMMENT '카페 등록자', `created_by` varchar(320) NOT NULL COMMENT '카페 등록자',
`updated_at` datetime NULL COMMENT '카페 변경날짜', `updated_at` datetime NULL COMMENT '카페 변경날짜',
`updated_by` varchar(20) NULL COMMENT '카페 변경자', `updated_by` varchar(320) NULL COMMENT '카페 변경자',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@@ -3,9 +3,9 @@ CREATE TABLE `cafe_menu` (
`name` varchar(50) NOT NULL COMMENT '카페 메뉴명', `name` varchar(50) NOT NULL COMMENT '카페 메뉴명',
`price` decimal(10, 2) NOT NULL COMMENT '메뉴 가격', `price` decimal(10, 2) NOT NULL COMMENT '메뉴 가격',
`created_at` datetime NOT NULL COMMENT '메뉴 등록날짜', `created_at` datetime NOT NULL COMMENT '메뉴 등록날짜',
`created_by` varchar(20) NOT NULL COMMENT '메뉴 등록자', `created_by` varchar(320) NOT NULL COMMENT '메뉴 등록자',
`updated_at` datetime COMMENT '메뉴 변경날짜', `updated_at` datetime COMMENT '메뉴 변경날짜',
`updated_by` varchar(20) NULL COMMENT '메뉴 변경자', `updated_by` varchar(320) NULL COMMENT '메뉴 변경자',
`cafe_id` bigint unsigned NOT NULL COMMENT '연관된 카페 ID', `cafe_id` bigint unsigned NOT NULL COMMENT '연관된 카페 ID',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `cafe_id` (`cafe_id`), KEY `cafe_id` (`cafe_id`),

View File

@@ -2,9 +2,9 @@ CREATE TABLE `cafe_image` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '카페 이미지 ID', `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '카페 이미지 ID',
`img_url` varchar(255) NOT NULL COMMENT '이미지 경로', `img_url` varchar(255) NOT NULL COMMENT '이미지 경로',
`created_at` datetime NOT NULL COMMENT '이미지 등록날짜', `created_at` datetime NOT NULL COMMENT '이미지 등록날짜',
`created_by` varchar(20) NOT NULL COMMENT '이미지 등록자', `created_by` varchar(320) NOT NULL COMMENT '이미지 등록자',
`updated_at` datetime COMMENT '이미지 변경날짜', `updated_at` datetime COMMENT '이미지 변경날짜',
`updated_by` varchar(20) NULL COMMENT '이미지 변경자', `updated_by` varchar(320) NULL COMMENT '이미지 변경자',
`cafe_id` bigint unsigned NOT NULL COMMENT '연관된 카페 ID', `cafe_id` bigint unsigned NOT NULL COMMENT '연관된 카페 ID',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `cafe_id` (`cafe_id`), KEY `cafe_id` (`cafe_id`),

View File

@@ -2,9 +2,9 @@ CREATE TABLE `menu_option`(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '옵션 ID', `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '옵션 ID',
`title` varchar(50) NOT NULL COMMENT '메뉴 옵션 이름', `title` varchar(50) NOT NULL COMMENT '메뉴 옵션 이름',
`created_at` datetime NOT NULL COMMENT '옵션 등록날짜', `created_at` datetime NOT NULL COMMENT '옵션 등록날짜',
`created_by` varchar(20) NOT NULL COMMENT '옵션 등록자', `created_by` varchar(320) NOT NULL COMMENT '옵션 등록자',
`updated_at` datetime COMMENT '옵션 변경날짜', `updated_at` datetime COMMENT '옵션 변경날짜',
`updated_by` varchar(20) NULL COMMENT '옵션 변경자', `updated_by` varchar(320) NULL COMMENT '옵션 변경자',
`menu_id` bigint unsigned NOT NULL COMMENT '연관된 카페 메뉴 ID', `menu_id` bigint unsigned NOT NULL COMMENT '연관된 카페 메뉴 ID',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `menu_id` (`menu_id`), KEY `menu_id` (`menu_id`),

View File

@@ -3,9 +3,9 @@ CREATE TABLE `option_detail` (
`name` varchar(50) NOT NULL COMMENT '옵션 상세명', `name` varchar(50) NOT NULL COMMENT '옵션 상세명',
`extra_price` decimal(10, 2) NOT NULL COMMENT '옵션 추가 요금', `extra_price` decimal(10, 2) NOT NULL COMMENT '옵션 추가 요금',
`created_at` datetime NOT NULL COMMENT '옵션 상세 등록날짜', `created_at` datetime NOT NULL COMMENT '옵션 상세 등록날짜',
`created_by` varchar(20) NOT NULL COMMENT '옵션 상세 등록자', `created_by` varchar(320) NOT NULL COMMENT '옵션 상세 등록자',
`updated_at` datetime COMMENT '옵션 상세 변경날짜', `updated_at` datetime COMMENT '옵션 상세 변경날짜',
`updated_by` varchar(20) NULL COMMENT '옵션 상세 변경자', `updated_by` varchar(320) NULL COMMENT '옵션 상세 변경자',
`option_id` bigint unsigned NOT NULL COMMENT '연관된 옵션 ID', `option_id` bigint unsigned NOT NULL COMMENT '연관된 옵션 ID',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `option_id` (`option_id`), KEY `option_id` (`option_id`),

View File

@@ -7,8 +7,8 @@ CREATE TABLE `member` (
`role_type` varchar(20) COMMENT '회원 권한', `role_type` varchar(20) COMMENT '회원 권한',
`activated` tinyint NOT NULL COMMENT '계정 활성화 여부', `activated` tinyint NOT NULL COMMENT '계정 활성화 여부',
`created_at` datetime NOT NULL COMMENT '회원 등록날짜', `created_at` datetime NOT NULL COMMENT '회원 등록날짜',
`created_by` varchar(20) NOT NULL COMMENT '회원 등록자', `created_by` varchar(320) NOT NULL COMMENT '회원 등록자',
`updated_at` datetime NULL COMMENT '회원 변경날짜', `updated_at` datetime NULL COMMENT '회원 변경날짜',
`updated_by` varchar(20) NULL COMMENT '회원 변경자', `updated_by` varchar(320) NULL COMMENT '회원 변경자',
PRIMARY KEY (`member_id`) PRIMARY KEY (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@@ -1,8 +0,0 @@
package io.beaniejoy.dongnecafe.common.config
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
@Configuration
@EnableJpaAuditing
class AuditingConfig

View File

@@ -1,12 +0,0 @@
package io.beaniejoy.dongnecafe.common.entity
import org.springframework.data.domain.AuditorAware
import org.springframework.stereotype.Component
import java.util.*
@Component
class BaseEntityAuditorAware: AuditorAware<String> {
override fun getCurrentAuditor(): Optional<String> {
return Optional.of("system")
}
}

View File

@@ -0,0 +1,25 @@
package io.beaniejoy.dongnecafe.common.config
import io.beaniejoy.dongnecafe.security.getAuthPrincipal
import mu.KLogging
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.domain.AuditorAware
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
import org.springframework.security.core.context.SecurityContextHolder
import java.util.*
@Configuration
@EnableJpaAuditing
class AuditingConfig {
companion object: KLogging() {
const val SYSTEM = "system"
}
@Bean
fun auditorProvider(): AuditorAware<String> {
return AuditorAware<String> {
Optional.of(SecurityContextHolder.getContext().authentication?.getAuthPrincipal() ?: SYSTEM)
}
}
}

View File

@@ -0,0 +1,21 @@
package io.beaniejoy.dongnecafe.common.entity
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.LastModifiedBy
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import javax.persistence.Column
import javax.persistence.EntityListeners
import javax.persistence.MappedSuperclass
@MappedSuperclass
@EntityListeners(AuditingEntityListener::class)
abstract class BaseEntity protected constructor() : BaseTimeEntity() {
@CreatedBy
@Column(updatable = false)
lateinit var createdBy: String
protected set
@LastModifiedBy
lateinit var updatedBy: String
protected set
}

View File

@@ -1,11 +1,10 @@
package io.beaniejoy.dongnecafe.common package io.beaniejoy.dongnecafe.common.entity
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedBy
import org.springframework.data.annotation.LastModifiedDate import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.persistence.Column
import javax.persistence.EntityListeners import javax.persistence.EntityListeners
import javax.persistence.MappedSuperclass import javax.persistence.MappedSuperclass
@@ -13,18 +12,11 @@ import javax.persistence.MappedSuperclass
@EntityListeners(AuditingEntityListener::class) @EntityListeners(AuditingEntityListener::class)
abstract class BaseTimeEntity protected constructor() { abstract class BaseTimeEntity protected constructor() {
@CreatedDate @CreatedDate
var createdAt: LocalDateTime = LocalDateTime.now() @Column(updatable = false)
protected set lateinit var createdAt: LocalDateTime
@CreatedBy
var createdBy: String = ""
protected set protected set
@LastModifiedDate @LastModifiedDate
var updatedAt: LocalDateTime? = null lateinit var updatedAt: LocalDateTime
protected set
@LastModifiedBy
var updatedBy: String? = null
protected set protected set
} }

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.domain.cafe.entity package io.beaniejoy.dongnecafe.domain.cafe.entity
import io.beaniejoy.dongnecafe.common.BaseTimeEntity import io.beaniejoy.dongnecafe.common.entity.BaseEntity
import io.beaniejoy.dongnecafe.domain.cafe.model.request.CafeMenuRegisterRequest import io.beaniejoy.dongnecafe.domain.cafe.model.request.CafeMenuRegisterRequest
import javax.persistence.* import javax.persistence.*
@@ -11,7 +11,7 @@ class Cafe protected constructor(
address: String, address: String,
phoneNumber: String, phoneNumber: String,
description: String, description: String,
) : BaseTimeEntity() { ) : BaseEntity() {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cafe_id", nullable = false) @Column(name = "cafe_id", nullable = false)

View File

@@ -1,11 +1,11 @@
package io.beaniejoy.dongnecafe.domain.cafe.entity package io.beaniejoy.dongnecafe.domain.cafe.entity
import io.beaniejoy.dongnecafe.common.BaseTimeEntity import io.beaniejoy.dongnecafe.common.entity.BaseEntity
import javax.persistence.* import javax.persistence.*
@Entity @Entity
@Table(name = "cafe_image") @Table(name = "cafe_image")
class CafeImage( class CafeImage protected constructor(
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cafe_image_id", nullable = false) @Column(name = "cafe_image_id", nullable = false)
@@ -17,4 +17,4 @@ class CafeImage(
@ManyToOne @ManyToOne
@JoinColumn(name = "cafe_id", nullable = false) @JoinColumn(name = "cafe_id", nullable = false)
val cafe: Cafe val cafe: Cafe
) : BaseTimeEntity() ) : BaseEntity()

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.domain.cafe.entity package io.beaniejoy.dongnecafe.domain.cafe.entity
import io.beaniejoy.dongnecafe.common.BaseTimeEntity import io.beaniejoy.dongnecafe.common.entity.BaseEntity
import io.beaniejoy.dongnecafe.domain.cafe.model.request.MenuOptionRegisterRequest import io.beaniejoy.dongnecafe.domain.cafe.model.request.MenuOptionRegisterRequest
import java.math.BigDecimal import java.math.BigDecimal
import javax.persistence.* import javax.persistence.*
@@ -10,7 +10,7 @@ import javax.persistence.*
class CafeMenu protected constructor( class CafeMenu protected constructor(
name: String, name: String,
price: BigDecimal, price: BigDecimal,
) : BaseTimeEntity() { ) : BaseEntity() {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cafe_menu_id", nullable = false) @Column(name = "cafe_menu_id", nullable = false)
@@ -33,7 +33,11 @@ class CafeMenu protected constructor(
val menuOptionList: MutableList<MenuOption> = arrayListOf() val menuOptionList: MutableList<MenuOption> = arrayListOf()
companion object { companion object {
fun createCafeMenu(name: String, price: BigDecimal, menuOptionRequestList: List<MenuOptionRegisterRequest>): CafeMenu { fun createCafeMenu(
name: String,
price: BigDecimal,
menuOptionRequestList: List<MenuOptionRegisterRequest>
): CafeMenu {
val menuOptionEntityList = menuOptionRequestList.map { menuOptionRequestDto -> val menuOptionEntityList = menuOptionRequestList.map { menuOptionRequestDto ->
MenuOption.createMenuOption( MenuOption.createMenuOption(
title = menuOptionRequestDto.title, title = menuOptionRequestDto.title,

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.domain.cafe.entity package io.beaniejoy.dongnecafe.domain.cafe.entity
import io.beaniejoy.dongnecafe.common.BaseTimeEntity import io.beaniejoy.dongnecafe.common.entity.BaseEntity
import io.beaniejoy.dongnecafe.domain.cafe.model.request.OptionDetailRegisterRequest import io.beaniejoy.dongnecafe.domain.cafe.model.request.OptionDetailRegisterRequest
import javax.persistence.* import javax.persistence.*
@@ -8,7 +8,7 @@ import javax.persistence.*
@Table(name = "menu_option") @Table(name = "menu_option")
class MenuOption protected constructor( class MenuOption protected constructor(
title: String title: String
) : BaseTimeEntity() { ) : BaseEntity() {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "menu_option_id", nullable = false) @Column(name = "menu_option_id", nullable = false)

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.domain.cafe.entity package io.beaniejoy.dongnecafe.domain.cafe.entity
import io.beaniejoy.dongnecafe.common.BaseTimeEntity import io.beaniejoy.dongnecafe.common.entity.BaseEntity
import java.math.BigDecimal import java.math.BigDecimal
import javax.persistence.* import javax.persistence.*
@@ -9,7 +9,7 @@ import javax.persistence.*
class OptionDetail protected constructor( class OptionDetail protected constructor(
name: String, name: String,
extraPrice: BigDecimal extraPrice: BigDecimal
) : BaseTimeEntity() { ) : BaseEntity() {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "option_detail_id", nullable = false) @Column(name = "option_detail_id", nullable = false)

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.domain.member.entity package io.beaniejoy.dongnecafe.domain.member.entity
import io.beaniejoy.dongnecafe.common.BaseTimeEntity import io.beaniejoy.dongnecafe.common.entity.BaseEntity
import io.beaniejoy.dongnecafe.domain.member.constant.RoleType import io.beaniejoy.dongnecafe.domain.member.constant.RoleType
import javax.persistence.* import javax.persistence.*
@@ -11,7 +11,7 @@ class Member(
password: String, password: String,
address: String, address: String,
phoneNumber: String phoneNumber: String
): BaseTimeEntity() { ) : BaseEntity() {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id", nullable = false) @Column(name = "member_id", nullable = false)

View File

@@ -0,0 +1,15 @@
package io.beaniejoy.dongnecafe.security
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.ANONYMOUS_USER
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.ROLE_ANONYMOUS
import org.springframework.security.core.Authentication
fun Authentication.getAuthPrincipal() : String? {
if (this.isAnonymous()) return null
return this.principal.toString()
}
fun Authentication.isAnonymous(): Boolean {
return this.principal == ANONYMOUS_USER || this.authorities.any { it.authority == ROLE_ANONYMOUS }
}

View File

@@ -3,4 +3,7 @@ package io.beaniejoy.dongnecafe.security.constant
object SecurityConstant { object SecurityConstant {
const val BEARER = "Bearer" const val BEARER = "Bearer"
const val WHITESPACE = " " const val WHITESPACE = " "
const val ANONYMOUS_USER = "anonymousUser"
const val ROLE_ANONYMOUS = "ROLE_ANONYMOUS"
} }

View File

@@ -1,8 +0,0 @@
package io.beaniejoy.dongnecafe.common.config
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
@Configuration
@EnableJpaAuditing
class AuditingConfig

View File

@@ -21,10 +21,10 @@ class SecurityConfig {
@Bean @Bean
fun filterChain(http: HttpSecurity): SecurityFilterChain { fun filterChain(http: HttpSecurity): SecurityFilterChain {
return http return http
// only api 방식 인증 & 인가 적용 위해 csrf & formLogin 비활성화
.csrf().disable() .csrf().disable()
.formLogin().disable() .formLogin().disable()
// FIXME 임시 permitAll 설정
.authorizeRequests() .authorizeRequests()
.anyRequest().authenticated() .anyRequest().authenticated()
@@ -43,6 +43,7 @@ class SecurityConfig {
.jwtTokenUtils(jwtTokenUtils) .jwtTokenUtils(jwtTokenUtils)
} }
// Security Filter 미적용 자원 설정
@Bean @Bean
fun webSecurityCustomizer(): WebSecurityCustomizer { fun webSecurityCustomizer(): WebSecurityCustomizer {
return WebSecurityCustomizer { web -> return WebSecurityCustomizer { web ->

View File

@@ -1,13 +0,0 @@
package io.beaniejoy.dongnecafe.common.entity
import org.springframework.data.domain.AuditorAware
import org.springframework.stereotype.Component
import java.util.*
@Component
class BaseEntityAuditorAware: AuditorAware<String> {
override fun getCurrentAuditor(): Optional<String> {
// TODO 추후 사용자 로그인 기능 추가되면 실제 등록한 사용자를 DB에 저장하는 방향으로 수정
return Optional.of("system")
}
}

View File

@@ -24,9 +24,11 @@ class JwtAuthenticationFilter(
val httpRequest = request as HttpServletRequest val httpRequest = request as HttpServletRequest
log.info { "[JwtAuthenticationFilter][${request.dispatcherType}] uri: ${request.requestURI}" } log.info { "[JwtAuthenticationFilter][${request.dispatcherType}] uri: ${request.requestURI}" }
// 인증 헤더에 토큰값 없는 경우 pass
getAccessToken(httpRequest)?.let { getAccessToken(httpRequest)?.let {
jwtTokenUtils.getAuthentication(it) jwtTokenUtils.getAuthentication(it)
}?.also { }?.also {
// 유효한 인증 토큰 존재하는 경우 SecurityContext 토큰값 저장
SecurityContextHolder.getContext().authentication = it SecurityContextHolder.getContext().authentication = it
log.info { "Valid Access Token [${it.name}]" } log.info { "Valid Access Token [${it.name}]" }
} }
@@ -34,6 +36,10 @@ class JwtAuthenticationFilter(
chain.doFilter(request, response) chain.doFilter(request, response)
} }
/**
* 인증 토큰 획득
* Authorization : Bearer [AUTH_TOKEN]
*/
private fun getAccessToken(request: HttpServletRequest): String? { private fun getAccessToken(request: HttpServletRequest): String? {
val bearer = request.getHeader(HttpHeaders.AUTHORIZATION) val bearer = request.getHeader(HttpHeaders.AUTHORIZATION)
?: return null ?: return null

View File

@@ -1,7 +1,6 @@
package io.beaniejoy.dongnecafe.domain.cafe.repository package io.beaniejoy.dongnecafe.domain.cafe.repository
import io.beaniejoy.dongnecafe.common.config.AuditingConfig import io.beaniejoy.dongnecafe.common.config.AuditingConfig
import io.beaniejoy.dongnecafe.common.entity.BaseEntityAuditorAware
import io.beaniejoy.dongnecafe.domain.cafe.entity.Cafe import io.beaniejoy.dongnecafe.domain.cafe.entity.Cafe
import io.beaniejoy.dongnecafe.domain.cafe.utils.CafeTestUtils import io.beaniejoy.dongnecafe.domain.cafe.utils.CafeTestUtils
import mu.KLogging import mu.KLogging
@@ -17,7 +16,6 @@ import org.springframework.data.repository.findByIdOrNull
@DataJpaTest( @DataJpaTest(
includeFilters = [ includeFilters = [
ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = [AuditingConfig::class]), ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = [AuditingConfig::class]),
ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = [BaseEntityAuditorAware::class])
] ]
) )
internal class CafeRepositoryTest { internal class CafeRepositoryTest {

View File

@@ -1,7 +1,10 @@
#!/bin/bash #!/bin/bash
cd .. echo "================ 1. Flyway Info ================"
./gradlew :db:flywayInfo -Dconfig=$1
./gradlew :db:flywayInfo echo "================ 2. Flyway Validate ============"
./gradlew :db:flywayValidate -Dconfig=$1
./gradlew :db:flywayValidate echo "================ 3. Flyway Migrate ============="
./gradlew :db:flywayMigrate -Dconfig=$1