Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…kend into feature/#10-북마크API

� Conflicts:
�	src/main/kotlin/com/yapp/web2/domain/account/controller/AccountController.kt
�	src/main/kotlin/com/yapp/web2/domain/account/entity/Account.kt
�	src/main/kotlin/com/yapp/web2/domain/account/service/AccountService.kt
�	src/main/kotlin/com/yapp/web2/domain/bookmark/service/BookmarkInterfaceService.kt
�	src/main/kotlin/com/yapp/web2/domain/folder/controller/FolderController.kt
�	src/main/kotlin/com/yapp/web2/util/ExceptionMessage.kt
�	src/test/kotlin/com/yapp/web2/domain/account/service/AccountServiceTest.kt
  • Loading branch information
Ji-Ha committed Jun 25, 2022
2 parents 557f4c0 + 6f67f00 commit fae6cab
Show file tree
Hide file tree
Showing 39 changed files with 1,844 additions and 230 deletions.
146 changes: 146 additions & 0 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@

# github repository Actions 페이지에 나타낼 이름
name: Dotoriham CI/CD

# event trigger
on:
push:
branches:
- main
- develop

permissions:
contents: read

jobs:
CI-CD:
runs-on: ubuntu-latest
steps:

## jdk setting
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin' # https://github.com/actions/setup-java

## gradle caching
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
## create application-prod.properties
- name: create application-prod.properties
if: contains(github.ref, 'main')
run: |
cd ./src/main/resources
touch ./application-prod.properties
echo "${{ secrets.PROPERTIES_PROD }}" > ./application-prod.properties
shell: bash

## create application-dev.properties
- name: create application-dev.properties
if: contains(github.ref, 'develop')
run: |
cd ./src/main/resources
touch ./application-dev.properties
echo "${{ secrets.PROPERTIES_DEV }}" > ./application-dev.properties
shell: bash

## create firebase-key.json
- name: create firebase key
run: |
cd ./src/main/resources
ls -a .
touch ./firebase-service-key.json
echo "${{ secrets.FIREBASE_KEY }}" > ./firebase-service-key.json
shell: bash

## gradle build
- name: Build with Gradle
run: ./gradlew build -x test -x ktlintCheck -x ktlintTestSourceSetCheck -x ktlintMainSourceSetCheck -x ktlintKotlinScriptCheck

## docker build & push to production
- name: Docker build & push to prod
if: contains(github.ref, 'main')
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile-prod -t ${{ secrets.DOCKER_REPO }}/dotoriham-prod .
docker push ${{ secrets.DOCKER_REPO }}/dotoriham-prod
## docker build & push to develop
- name: Docker build & push to dev
if: contains(github.ref, 'develop')
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile-dev -t ${{ secrets.DOCKER_REPO }}/dotoriham-dev .
docker push ${{ secrets.DOCKER_REPO }}/dotoriham-dev
## deploy to production
- name: Deploy to prod
uses: appleboy/ssh-action@master
id: deploy-prod
if: contains(github.ref, 'main')
with:
host: ${{ secrets.HOST_PROD }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
port: 22
script: |
sudo docker pull ${{ secrets.DOCKER_REPO }}/dotoriham-prod
docker-compose up -d
docker image prune -f
## deploy to develop
- name: Deploy to dev
uses: appleboy/ssh-action@master
id: deploy-dev
if: contains(github.ref, 'develop')
with:
host: ${{ secrets.HOST_DEV }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
port: 22
#key: ${{ secrets.PRIVATE_KEY }}
script: |
sudo docker pull ${{ secrets.DOCKER_REPO }}/dotoriham-dev
docker-compose up -d
docker image prune -f
## time
current-time:
needs: CI-CD
runs-on: ubuntu-latest
steps:
- name: Get Current Time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYY-MM-DDTHH:mm:ss
utcOffset: "+09:00" # 기준이 UTC이기 때문에 한국시간인 KST를 맞추기 위해 +9시간 추가

- name: Print Current Time
run: echo "Current Time=${{steps.current-time.outputs.formattedTime}}" # current-time 에서 지정한 포맷대로 현재 시간 출력
shell: bash

## slack
action-slack:
needs: CI-CD
runs-on: ubuntu-latest
steps:
- name: Slack Alarm
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
author_name: GitHub-Actions CI/CD
fields: repo,message,commit,author,ref,job,took
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required
if: always() # Pick up events even if the job fails or is canceled.
34 changes: 0 additions & 34 deletions .github/workflows/gradle.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Dockerfile → Dockerfile-dev
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM openjdk:11-jdk-slim
EXPOSE 8080
ARG JAR_FILE=/build/libs/Web-Team-2-Backend-0.0.1-SNAPSHOT.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=dev","/app.jar"]
5 changes: 5 additions & 0 deletions Dockerfile-prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM openjdk:14-jdk-slim
EXPOSE 8080
ARG JAR_FILE=/build/libs/Web-Team-2-Backend-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
7 changes: 6 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,15 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.boot:spring-boot-starter-batch")
implementation("org.springframework.boot:spring-boot-starter-mail")
implementation("io.jsonwebtoken:jjwt:0.9.1")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("io.springfox:springfox-boot-starter:3.0.0")

// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
implementation("org.apache.commons:commons-lang3:3.12.0")

// https://mvnrepository.com/artifact/com.slack.api/slack-api-client
implementation("com.slack.api:slack-api-client:1.20.2")

Expand Down Expand Up @@ -147,7 +151,8 @@ fun excludedClassFilesForReport(classDirectories: ConfigurableFileCollection) {
"**/exception/**",
"**/config/**",
"**/Bookmarkers*",
"**/BaseTimeEntity*"
"**/BaseTimeEntity*",
"**/infra/**"
)
}
})
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/com/yapp/web2/batch/job/NotificationJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class NotificationJob(

private val log = LoggerFactory.getLogger(javaClass)

@Bean(name = ["bookmarkNotificationJob"])
@Bean("bookmarkNotificationJob")
fun bookmarkNotificationJob(): Job {
return jobBuilderFactory.get("bookmarkNotificationJob")
.start(bookmarkNotificationStep())
Expand Down Expand Up @@ -62,6 +62,7 @@ class NotificationJob(
}
}

@Bean
fun remindBookmarkWriter(): ItemWriter<Bookmark> {
return ItemWriter {
it.stream().forEach { bookmark ->
Expand Down
69 changes: 69 additions & 0 deletions src/main/kotlin/com/yapp/web2/batch/job/TrashRefreshJob.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.yapp.web2.batch.job

import com.yapp.web2.domain.bookmark.entity.Bookmark
import com.yapp.web2.domain.bookmark.repository.BookmarkRepository
import org.springframework.batch.core.Job
import org.springframework.batch.core.Step
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory
import org.springframework.batch.core.launch.support.RunIdIncrementer
import org.springframework.batch.item.ItemProcessor
import org.springframework.batch.item.ItemWriter
import org.springframework.batch.item.support.ListItemReader
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.time.LocalDateTime

@Configuration
@EnableBatchProcessing
class TrashRefreshJob(
private val jobBuilderFactory: JobBuilderFactory,
private val stepBuilderFactory: StepBuilderFactory,
private val bookmarkRepository: BookmarkRepository,
private val jobCompletionListener: JobCompletionListener
) {

@Bean("bookmarkTrashRefreshJob")
fun bookmarkTrashRefreshJob(): Job {
return jobBuilderFactory.get("bookmarkTrashRefreshJob")
.start(trashRefreshStep())
.incrementer(RunIdIncrementer())
.listener(jobCompletionListener)
.build()
}

@Bean
fun trashRefreshStep(): Step {
return stepBuilderFactory.get("trashRefreshStep")
.chunk<Bookmark, Bookmark>(10)
.reader(deleteBookmarkReader())
.processor(deleteBookmarkProcessor())
.writer(NoOperationItemWriter())
.build()
}

@Bean
fun deleteBookmarkReader(): ListItemReader<Bookmark> {
val deleteBookmarkList = bookmarkRepository.findAllByDeletedIsTrueAndDeleteTimeIsAfter(
LocalDateTime.now().minusDays(30)
)

return ListItemReader(deleteBookmarkList)
}

@Bean
fun deleteBookmarkProcessor(): ItemProcessor<Bookmark, Bookmark> {
return ItemProcessor {
bookmarkRepository.delete(it)
it
}
}
}

class NoOperationItemWriter : ItemWriter<Bookmark> {
override fun write(items: MutableList<out Bookmark>) {
// no-operation
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.yapp.web2.batch.scheduler

import com.yapp.web2.batch.job.TrashRefreshJob
import org.springframework.batch.core.JobParameter
import org.springframework.batch.core.JobParameters
import org.springframework.batch.core.launch.JobLauncher
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
import java.text.SimpleDateFormat

@Component
class TrashRefreshScheduler(
private val jobLauncher: JobLauncher,
private val trashRefreshJob: TrashRefreshJob
) {
private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")

@Scheduled(cron = "0 0 2 * * *")
fun trashRefreshSchedule() {
val jobConf = hashMapOf<String, JobParameter>()
jobConf["time"] = JobParameter(dateFormat.format(System.currentTimeMillis()))
val jobParameters = JobParameters(jobConf)

jobLauncher.run(trashRefreshJob.bookmarkTrashRefreshJob(), jobParameters)
}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/com/yapp/web2/common/CustomPassword.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.yapp.web2.common

import javax.validation.Constraint
import javax.validation.Payload
import kotlin.annotation.AnnotationTarget.*
import kotlin.reflect.KClass

@MustBeDocumented
@Constraint(validatedBy = [PasswordValidator::class])
@Target(ANNOTATION_CLASS, CLASS, CONSTRUCTOR, FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class CustomPassword(

// TODO: 2022/05/08 필드 별 정확한 의미 파악
val message: String = "영문 대소문자, 숫자, 특수문자 중 2종류 이상을 조합하여 8~16자의 비밀번호를 생성해주세요.",
val groups: Array<KClass<*>> = [],
val payload: Array<KClass<out Payload>> = [],
)
22 changes: 22 additions & 0 deletions src/main/kotlin/com/yapp/web2/common/PasswordValidator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.yapp.web2.common

import com.yapp.web2.util.Message
import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext

class PasswordValidator : ConstraintValidator<CustomPassword, String> {

override fun isValid(password: String, context: ConstraintValidatorContext?): Boolean {
// 특수문자 + (영문자 or 숫자) 조합으로 8~16자 사이
val passwordRegex = "^(?=.*[0-9a-zA-Z])(?=.*[!@#\$%^&*])(?=\\S+\$).{8,16}\$"
val regex = Regex(passwordRegex)
val isValidPassword = password.matches(regex)

if (!isValidPassword) {
context?.disableDefaultConstraintViolation()
context?.buildConstraintViolationWithTemplate(Message.PASSWORD_VALID_MESSAGE)
?.addConstraintViolation()
}
return isValidPassword
}
}
Loading

0 comments on commit fae6cab

Please sign in to comment.