Skip to content

Commit

Permalink
인가수정 대응 추가 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
jinia91 committed Aug 17, 2024
1 parent 0991b00 commit cdc92c5
Show file tree
Hide file tree
Showing 18 changed files with 96 additions and 22 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Deploy to Cloud Server

on:
push:
branches:
- main # 또는 배포하고자 하는 특정 브랜치 이름

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Build
uses: docker/setup-buildx-action@v2

- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push Docker image
run: |
docker build -t your-dockerhub-username/your-image-name:latest .
docker push your-dockerhub-username/your-image-name:latest
- name: SSH to server and deploy
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: ${{ secrets.SERVER_PORT }}
script: |
docker pull your-dockerhub-username/your-image-name:latest
docker stop your-container-name || true
docker rm your-container-name || true
docker run -d --name your-container-name -p 80:80 your-dockerhub-username/your-image-name:latest
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ src/main/resources/application-dev.yml
/logs/
/src/logback.xml
**/application.yml
**/application-otel.yml

### h2 db ###
/h2/
Expand Down
1 change: 1 addition & 0 deletions mains/monolith-main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ val bootLib = mutableListOf(
libs.spring.boot.starter.security,
libs.spring.boot.starter.web,
libs.spring.boot.starter.data.neo4j,
libs.spring.boot.starter.actuator,
libs.h2,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import kr.co.jiniaslog.TestContainerAbstractSkeleton
import kr.co.jiniaslog.memo.domain.FolderTestFixtures
import kr.co.jiniaslog.memo.domain.exception.NotOwnershipException
import kr.co.jiniaslog.memo.domain.folder.Folder
import kr.co.jiniaslog.memo.domain.folder.FolderId
import kr.co.jiniaslog.memo.domain.folder.FolderName
Expand Down Expand Up @@ -142,7 +143,7 @@ class FolderUseCaseTests : TestContainerAbstractSkeleton() {
requesterId = AuthorId(2),
)
// when & then
shouldThrow<IllegalArgumentException> {
shouldThrow<NotOwnershipException> {
sut.handle(command)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ class MemoQueriesTests : TestContainerAbstractSkeleton() {
)

// when
val result = sut.handle(IRecommendRelatedMemo.Query(thisMemoId = memo.entityId, rawKeyword = "test"))
val result = sut.handle(
IRecommendRelatedMemo.Query(thisMemoId = memo.entityId, rawKeyword = "test", requesterId = memo.authorId)
)

// then
result.relatedMemoCandidates.size shouldBe 5
Expand Down Expand Up @@ -88,7 +90,7 @@ class MemoQueriesTests : TestContainerAbstractSkeleton() {
}

// when
val result = sut.handle(IGetAllReferencesByMemo.Query(memoId = target.entityId))
val result = sut.handle(IGetAllReferencesByMemo.Query(memoId = target.entityId, requesterId = target.authorId))

// then
result.references.size shouldBe 10
Expand All @@ -107,7 +109,7 @@ class MemoQueriesTests : TestContainerAbstractSkeleton() {
}

// when
val result = sut.handle(IGetAllReferencedByMemo.Query(memoId = target.entityId))
val result = sut.handle(IGetAllReferencedByMemo.Query(memoId = target.entityId, requesterId = target.authorId))

// then
result.referenceds.size shouldBe 10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import kr.co.jiniaslog.memo.adapter.inbound.http.dto.MakeFolderRelationshipReque
import kr.co.jiniaslog.memo.adapter.inbound.http.dto.MakeFolderRelationshipResponse
import kr.co.jiniaslog.memo.adapter.inbound.http.dto.toResponse
import kr.co.jiniaslog.memo.adapter.inbound.http.viewmodel.FolderViewModel
import kr.co.jiniaslog.memo.domain.exception.NotOwnershipException
import kr.co.jiniaslog.memo.domain.folder.FolderId
import kr.co.jiniaslog.memo.domain.memo.AuthorId
import kr.co.jiniaslog.memo.queries.FolderQueriesFacade
Expand All @@ -21,6 +22,7 @@ import kr.cojiniaslog.shared.adapter.inbound.http.AuthUserId
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
Expand All @@ -38,6 +40,11 @@ class FolderResources(
private val folderUseCases: FolderUseCasesFacade,
private val folderQueries: FolderQueriesFacade,
) {
@ExceptionHandler(value = [NotOwnershipException::class])
fun notOwnershipExceptionHandler(e: NotOwnershipException): ResponseEntity<Any> {
return ResponseEntity.status(403).body(e.message)
}

@PostMapping()
@CrossOrigin(origins = ["http://localhost:3000"])
fun createNewFolder(
Expand Down Expand Up @@ -105,7 +112,6 @@ class FolderResources(
@RequestParam(required = false) query: String?,
@AuthUserId userId: Long?,
): ResponseEntity<GetFolderAndMemoResponse> {
log.info { "query: $query" }
return ResponseEntity.ok(
folderQueries.handle(IGetFoldersAllInHierirchyByAuthorId.Query(query, AuthorId(userId!!))).toResponse()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import kr.co.jiniaslog.memo.adapter.inbound.http.dto.GetMemoByIdResponse
import kr.co.jiniaslog.memo.adapter.inbound.http.dto.InitMemoRequest
import kr.co.jiniaslog.memo.adapter.inbound.http.dto.RecommendRelatedMemoResponse
import kr.co.jiniaslog.memo.adapter.inbound.http.dto.toResponse
import kr.co.jiniaslog.memo.domain.exception.NotOwnershipException
import kr.co.jiniaslog.memo.domain.folder.FolderId
import kr.co.jiniaslog.memo.domain.memo.AuthorId
import kr.co.jiniaslog.memo.domain.memo.MemoId
Expand All @@ -24,6 +25,7 @@ import kr.co.jiniaslog.memo.usecase.MemoUseCasesFacade
import kr.cojiniaslog.shared.adapter.inbound.http.AuthUserId
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
Expand All @@ -32,6 +34,7 @@ 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 java.awt.SystemColor.info
import java.net.URI

@RestController
Expand All @@ -40,6 +43,11 @@ class MemoResources(
private val memoUseCases: MemoUseCasesFacade,
private val memoQueries: MemoQueriesFacade,
) {
@ExceptionHandler(value = [NotOwnershipException::class])
fun notOwnershipExceptionHandler(e: NotOwnershipException): ResponseEntity<Any> {
return ResponseEntity.status(403).body(e.message)
}

@PostMapping
fun createEmptyMemo(
@AuthUserId userId: Long?,
Expand Down Expand Up @@ -98,7 +106,7 @@ class MemoResources(
@RequestParam keyword: String,
@AuthUserId userId: Long?,
): ResponseEntity<RecommendRelatedMemoResponse> {
val query = IRecommendRelatedMemo.Query(keyword, MemoId(id))
val query = IRecommendRelatedMemo.Query(keyword, MemoId(id), AuthorId(userId!!))
val info = memoQueries.handle(query)
return ResponseEntity.ok(info.toResponse())
}
Expand All @@ -108,7 +116,7 @@ class MemoResources(
@PathVariable id: Long,
@AuthUserId userId: Long?,
): ResponseEntity<GetAllReferencesByMemoResponse> {
val query = IGetAllReferencesByMemo.Query(MemoId(id))
val query = IGetAllReferencesByMemo.Query(MemoId(id), AuthorId(userId!!))
val info = memoQueries.handle(query)
return ResponseEntity.ok(info.toResponse())
}
Expand All @@ -118,7 +126,7 @@ class MemoResources(
@PathVariable id: Long,
@AuthUserId userId: Long?,
): ResponseEntity<GetAllReferencedByMemoResponse> {
val query = IGetAllReferencedByMemo.Query(MemoId(id))
val query = IGetAllReferencedByMemo.Query(MemoId(id), AuthorId(userId!!))
val info = memoQueries.handle(query)
return ResponseEntity.ok(info.toResponse())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ internal interface MemoNeo4jRepository : Neo4jRepository<MemoNeo4jEntity, Long>
"""
CALL db.index.fulltext.queryNodes("memo_full_text_index", ${'$'}keyword)
YIELD node, score
WHERE node.authorId = ${'$'}authorId
OPTIONAL MATCH (node)-[:REFERENCE]->(other)
WITH node, score, count(other) AS referencesCount
ORDER BY referencesCount DESC, score DESC
Expand All @@ -23,14 +24,16 @@ internal interface MemoNeo4jRepository : Neo4jRepository<MemoNeo4jEntity, Long>
LIMIT 6
""",
)
fun findByKeywordFullTextSearchingLimit6(
fun findByKeywordFullTextSearchingLimit6ByAuthorId(
@Param("keyword") keyword: String,
@Param("authorId") authorId: Long,
): List<MemoNeo4jEntity>

@Query(
"""
CALL db.index.fulltext.queryNodes("memo_full_text_index", ${'$'}keyword)
YIELD node, score
WHERE node.authorId = ${'$'}authorId
OPTIONAL MATCH (node)-[:REFERENCE]->(other)
WITH node, score, count(other) AS referencesCount
ORDER BY referencesCount DESC, score DESC
Expand All @@ -46,6 +49,7 @@ internal interface MemoNeo4jRepository : Neo4jRepository<MemoNeo4jEntity, Long>
)
fun findByKeywordFullTextSearching(
@Param("keyword") keyword: String,
@Param("authorId") authorId: Long,
): List<MemoNeo4jEntity>

@Query("MATCH (parent:memo)-[r:REFERENCE]->(child:memo) WHERE child.id = ${'$'}memoId detach DELETE r")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ internal open class MemoRepositoryAdapter(
private val memoNeo4jRepository: MemoNeo4jRepository,
private val folderNeo4jRepository: FolderNeo4jRepository,
) : MemoRepository {
@Transactional(readOnly = true)
override fun findByRelatedMemo(keyword: String): List<Memo> {
return memoNeo4jRepository.findByKeywordFullTextSearchingLimit6(keyword).map { it.toDomain() }
}

override fun findById(id: MemoId): Memo? {
return memoNeo4jRepository.findById(id.value).orElse(null)?.toDomain()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kr.co.jiniaslog.memo.adapter.out.neo4j.folder.FolderNeo4jEntity
import kr.co.jiniaslog.memo.adapter.out.neo4j.folder.FolderNeo4jRepository
import kr.co.jiniaslog.memo.adapter.out.neo4j.memo.MemoNeo4jEntity
import kr.co.jiniaslog.memo.adapter.out.neo4j.memo.MemoNeo4jRepository
import kr.co.jiniaslog.memo.domain.exception.NotOwnershipException
import kr.co.jiniaslog.memo.domain.folder.FolderId
import kr.co.jiniaslog.memo.domain.folder.FolderName
import kr.co.jiniaslog.memo.domain.memo.AuthorId
Expand Down Expand Up @@ -31,7 +32,7 @@ internal open class MemoFolderImplQueries(

override fun handle(query: IRecommendRelatedMemo.Query): IRecommendRelatedMemo.Info {
val relatedMemoCandidates =
memoNeo4jRepository.findByKeywordFullTextSearchingLimit6(query.keyword)
memoNeo4jRepository.findByKeywordFullTextSearchingLimit6ByAuthorId(query.keyword, query.requesterId.value)
.filterNot { it.id == query.thisMemoId.value }
.take(5)
.map { Triple(it.id, it.title, it.content) }
Expand All @@ -52,7 +53,7 @@ internal open class MemoFolderImplQueries(
val memo =
memoNeo4jRepository.findById(query.memoId.value).getOrNull()
?: throw IllegalArgumentException("memo not found")
require(memo.authorId == query.requesterId.value)
require(memo.authorId == query.requesterId.value) { throw NotOwnershipException() }
return IGetMemoById.Info(
memoId = MemoId(memo.id),
title = MemoTitle(memo.title),
Expand All @@ -72,6 +73,7 @@ internal open class MemoFolderImplQueries(
val memo =
memoNeo4jRepository.findById(query.memoId.value).getOrNull()
?: throw IllegalArgumentException("memo not found")
require(memo.authorId == query.requesterId.value) { throw NotOwnershipException() }
return IGetAllReferencesByMemo.Info(
references =
memo.references.map {
Expand All @@ -85,6 +87,9 @@ internal open class MemoFolderImplQueries(

override fun handle(query: IGetAllReferencedByMemo.Query): IGetAllReferencedByMemo.Info {
val result = memoNeo4jRepository.findReferencingMemos(query.memoId.value)
result.forEach {
require(it.authorId == query.requesterId.value) { throw NotOwnershipException() }
}
return IGetAllReferencedByMemo.Info(
referenceds =
result.map {
Expand Down Expand Up @@ -131,7 +136,7 @@ internal open class MemoFolderImplQueries(
}

private fun findByKeyword(query: IGetFoldersAllInHierirchyByAuthorId.Query): IGetFoldersAllInHierirchyByAuthorId.Info {
val memos = memoNeo4jRepository.findByKeywordFullTextSearching(query.value!!)
val memos = memoNeo4jRepository.findByKeywordFullTextSearching(query.value!!, query.requesterId.value)
return IGetFoldersAllInHierirchyByAuthorId.Info(
listOf(
IGetFoldersAllInHierirchyByAuthorId.FolderInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ import kr.co.jiniaslog.memo.domain.memo.Memo
import kr.co.jiniaslog.memo.domain.memo.MemoId
import kr.co.jiniaslog.shared.core.domain.Repository

interface MemoRepository : Repository<Memo, MemoId> {
fun findByRelatedMemo(keyword: String): List<Memo>
}
interface MemoRepository : Repository<Memo, MemoId>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.co.jiniaslog.memo.queries

import kr.co.jiniaslog.memo.domain.memo.AuthorId
import kr.co.jiniaslog.memo.domain.memo.MemoId
import kr.co.jiniaslog.memo.domain.memo.MemoTitle

Expand All @@ -8,6 +9,7 @@ interface IGetAllReferencedByMemo {

data class Query(
val memoId: MemoId,
val requesterId: AuthorId,
)

data class Info(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.co.jiniaslog.memo.queries

import kr.co.jiniaslog.memo.domain.memo.AuthorId
import kr.co.jiniaslog.memo.domain.memo.MemoId
import kr.co.jiniaslog.memo.domain.memo.MemoTitle

Expand All @@ -8,6 +9,7 @@ interface IGetAllReferencesByMemo {

data class Query(
val memoId: MemoId,
val requesterId: AuthorId,
)

data class Info(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.co.jiniaslog.memo.queries

import kr.co.jiniaslog.memo.domain.memo.AuthorId
import kr.co.jiniaslog.memo.domain.memo.MemoContent
import kr.co.jiniaslog.memo.domain.memo.MemoId
import kr.co.jiniaslog.memo.domain.memo.MemoTitle
Expand All @@ -10,6 +11,7 @@ interface IRecommendRelatedMemo {
class Query(
rawKeyword: String,
val thisMemoId: MemoId,
val requesterId: AuthorId,
) {
val keyword: String = rawKeyword.also {
require(it.isNotBlank()) { "keyword should not be blank" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package kr.co.jiniaslog.memo.domain.exception

class NotOwnershipException : RuntimeException()
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.co.jiniaslog.memo.domain.folder

import kr.co.jiniaslog.memo.domain.exception.NotOwnershipException
import kr.co.jiniaslog.memo.domain.memo.AuthorId
import kr.co.jiniaslog.shared.core.domain.AggregateRoot
import kr.co.jiniaslog.shared.core.domain.IdUtils
Expand All @@ -22,7 +23,7 @@ class Folder private constructor(
private set

fun validateOwnership(authorId: AuthorId) {
require(this.authorId == authorId) { "폴더의 소유자가 아닙니다." }
require(this.authorId == authorId) { throw NotOwnershipException() }
}

fun changeName(name: FolderName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.co.jiniaslog.memo.domain.memo

import kr.co.jiniaslog.memo.domain.exception.NotOwnershipException
import kr.co.jiniaslog.memo.domain.folder.FolderId
import kr.co.jiniaslog.shared.core.domain.AggregateRoot
import kr.co.jiniaslog.shared.core.domain.IdUtils
Expand Down Expand Up @@ -32,7 +33,7 @@ class Memo private constructor(
private set

fun validateOwnership(requesterId: AuthorId) {
require(this.authorId == requesterId) { "요청자가 작성자가 아닙니다." }
require(this.authorId == requesterId) { throw NotOwnershipException() }
}

fun update(
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ include(
"libs:websocket-kernel",
"libs:messaging-kernel",
"libs:snowflake-id-generator",
"libs:global-logging",

// blog
"service:blog:blog-core",
Expand Down

0 comments on commit cdc92c5

Please sign in to comment.