Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tags #21

Merged
merged 8 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.wafflestudio.toyproject.memoWithTags.memo.persistence

import com.wafflestudio.toyproject.memoWithTags.tag.persistence.TagEntity
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne

@Entity(name = "memo_and_tag")
class MemoAndTag(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,

@ManyToOne
@JoinColumn(name = "memo_id")
var memo: MemoEntity,

@ManyToOne
@JoinColumn(name = "tag_id")
var tag: TagEntity
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.wafflestudio.toyproject.memoWithTags.tag

sealed class TagException : RuntimeException()

class TagNotFoundException : TagException()
class WrongUserException : TagException()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.wafflestudio.toyproject.memoWithTags.tag.controller

data class Tag(
val id: Long,
val name: String,
val color: String
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package com.wafflestudio.toyproject.memoWithTags.tag.controller

import com.wafflestudio.toyproject.memoWithTags.tag.TagNotFoundException
import com.wafflestudio.toyproject.memoWithTags.tag.WrongUserException
import com.wafflestudio.toyproject.memoWithTags.tag.service.TagService
import com.wafflestudio.toyproject.memoWithTags.user.AuthUser
import com.wafflestudio.toyproject.memoWithTags.user.AuthenticationFailedException
import com.wafflestudio.toyproject.memoWithTags.user.contoller.User
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 @@ -14,31 +21,38 @@ class TagController(
private val tagService: TagService
) {
@GetMapping("/api/v1/tag")
fun getTags(): List<TagDto> {
return emptyList() // 빈 리스트 반환
fun getTags(@AuthUser user: User): List<Tag> {
return tagService.getTags(user)
}

@PostMapping("/api/v1/tag")
fun createTag(@RequestBody request: CreateTagRequest): TagDto {
return TagDto(0L, "", "") // 기본값으로 TagDto 반환
fun createTag(@RequestBody request: CreateTagRequest, @AuthUser user: User): Tag {
val tag = tagService.createTag(request.name, request.color, user)
return tag
}

@PutMapping("/api/v1/tag/{tagId}")
fun updateTag(@PathVariable id: Long, @RequestBody request: UpdateTagRequest): TagDto {
return TagDto(0L, "", "") // 기본값으로 TagDto 반환
fun updateTag(@PathVariable tagId: Long, @RequestBody request: UpdateTagRequest, @AuthUser user: User): Tag {
return tagService.updateTag(tagId, request.name, request.color, user)
}

@DeleteMapping("/api/v1/tag/{tagId}")
fun deleteTag(@PathVariable id: Long) {
// 반환 타입이 Unit이므로 아무 작업 없이 비워 둬도 OK
fun deleteTag(@PathVariable tagId: Long, @AuthUser user: User): ResponseEntity<Unit> {
tagService.deleteTag(tagId, user)
return ResponseEntity.noContent().build()
}
}

data class TagDto(
val id: Long,
val name: String,
val color: String
)
@ExceptionHandler
fun handleTagNotFoundException(e: Exception): ResponseEntity<Unit> {
val status = when (e) {
is TagNotFoundException -> 404
is WrongUserException -> 403
is AuthenticationFailedException -> 401
else -> 404
}
return ResponseEntity.status(status).build()
}
}

data class CreateTagRequest(
val name: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
package com.wafflestudio.toyproject.memoWithTags.tag.persistence

class TagEntity
import com.wafflestudio.toyproject.memoWithTags.user.persistence.UserEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.ManyToOne
import java.time.Instant

@Entity(name = "tags")
class TagEntity(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,

@Column(name = "name", nullable = false)
var name: String,

@Column(name = "color", nullable = false)
var color: String,

@ManyToOne
var user: UserEntity,

@Column(name = "created_at", nullable = false)
val createdAt: Instant = Instant.now(),

@Column(name = "updated_at")
var updatedAt: Instant? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.wafflestudio.toyproject.memoWithTags.tag.persistence

import org.springframework.data.jpa.repository.JpaRepository

interface TagRepository : JpaRepository<TagEntity, Long> {
fun findByUserId(userId: Long): List<TagEntity>
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,49 @@
package com.wafflestudio.toyproject.memoWithTags.tag.service

import com.wafflestudio.toyproject.memoWithTags.tag.TagNotFoundException
import com.wafflestudio.toyproject.memoWithTags.tag.WrongUserException
import com.wafflestudio.toyproject.memoWithTags.tag.controller.Tag
import com.wafflestudio.toyproject.memoWithTags.tag.persistence.TagEntity
import com.wafflestudio.toyproject.memoWithTags.tag.persistence.TagRepository
import com.wafflestudio.toyproject.memoWithTags.user.AuthenticationFailedException
import com.wafflestudio.toyproject.memoWithTags.user.contoller.User
import com.wafflestudio.toyproject.memoWithTags.user.persistence.UserRepository
import org.springframework.stereotype.Service
import java.time.Instant

@Service
class TagService
class TagService(
private val tagRepository: TagRepository,
private val userRepository: UserRepository
) {
fun getTags(user: User): List<Tag> {
return tagRepository.findByUserId(user.id).map { Tag(it.id!!, it.name, it.color) }
}

fun createTag(name: String, color: String, user: User): Tag {
val userEntity = userRepository.findByEmail(user.email) ?: throw AuthenticationFailedException()
val tagEntity = TagEntity(name = name, color = color, user = userEntity)
val savedTagEntity = tagRepository.save(tagEntity)
return Tag(savedTagEntity.id!!, savedTagEntity.name, savedTagEntity.color)
}

fun updateTag(id: Long, name: String, color: String, user: User): Tag {
val tagEntity = tagRepository.findById(id).orElseThrow { throw TagNotFoundException() }
if (tagEntity.user.email != user.email) {
throw WrongUserException()
}
tagEntity.name = name
tagEntity.color = color
tagEntity.updatedAt = Instant.now()
val savedTagEntity = tagRepository.save(tagEntity)
return Tag(savedTagEntity.id!!, savedTagEntity.name, savedTagEntity.color)
}

fun deleteTag(tagId: Long, user: User) {
val tagEntity = tagRepository.findById(tagId).orElseThrow { throw TagNotFoundException() }
if (tagEntity.user.email != user.email) {
throw WrongUserException()
}
tagRepository.delete(tagEntity)
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading