Skip to content

Event 구조 및 생성 기능 #38

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

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.example.attendanceapimono.adapter.infra.security.SecurityContextRepos
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.config.web.server.ServerHttpSecurity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ data class RoleAdapter(val role: UserRole): GrantedAuthority {

class UserPrincipal(
val id: UUID,
val roles: List<RoleAdapter>
private val roles: List<RoleAdapter>
) : UserDetails {
override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
return roles.toMutableList()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package com.example.attendanceapimono.adapter.present

import com.example.attendanceapimono.adapter.present.api.EventAPI
import com.example.attendanceapimono.application.EventService
import com.example.attendanceapimono.application.dto.event.CreateEventRequest
import com.example.attendanceapimono.application.dto.event.CreateEventResponse
import com.example.attendanceapimono.application.exception.handleValidationCatch
import kotlinx.coroutines.reactor.awaitSingle
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Mono

@RestController
class EventController: EventAPI {
class EventController (private val eventService: EventService): EventAPI {
override suspend fun createEvent(body: Mono<CreateEventRequest>): CreateEventResponse {
return body.handleValidationCatch()
.map(eventService::createEvent)
.awaitSingle()
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,47 @@
package com.example.attendanceapimono.adapter.present.api

import com.example.attendanceapimono.application.dto.event.CreateEventRequest
import com.example.attendanceapimono.application.dto.event.CreateEventResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.ExampleObject
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.ResponseStatus
import reactor.core.publisher.Mono
import javax.validation.Valid

@Tag(name = "Event 관련 API")
interface EventAPI {
@Operation(
summary = "이벤트 생성",
requestBody = io.swagger.v3.oas.annotations.parameters.RequestBody(
content = [
Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = Schema(implementation = CreateEventRequest::class),
)
]
)
)
@ApiResponse(
responseCode = "201",
description = "이벤트 생성",
content = [Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = Schema(implementation = CreateEventResponse::class),
examples = [ExampleObject(CreateEventResponse.Example)]
)],
)
@ResponseStatus(HttpStatus.CREATED)
@JWTTokenV1
@PreAuthorize("hasRole('MASTER') or hasRole('STAFF')")
@PostMapping("/event")
suspend fun createEvent(@Valid @RequestBody body: Mono<CreateEventRequest>): CreateEventResponse
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
package com.example.attendanceapimono.application

import com.example.attendanceapimono.application.dto.event.CreateEventRequest
import com.example.attendanceapimono.application.dto.event.CreateEventResponse
import com.example.attendanceapimono.domain.event.EventRepository
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class EventService {
fun createEvent() {
class EventService (
private val eventRepository: EventRepository
) {
@Transactional
fun createEvent(dto: CreateEventRequest): CreateEventResponse = runBlocking {
val event = dto.entity()

eventRepository.save(event)

CreateEventResponse(eventId = event.id)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.example.attendanceapimono.application.dto.event

import com.example.attendanceapimono.domain.event.Event
import io.swagger.v3.oas.annotations.media.Schema
import org.hibernate.validator.constraints.Length
import org.springframework.beans.factory.annotation.Value
import org.springframework.format.annotation.DateTimeFormat
import java.time.LocalDateTime
import java.util.*

@Schema(
title = "이벤트 등록 요청",
Expand All @@ -26,12 +29,27 @@ class CreateEventRequest(
@field:DateTimeFormat
val expectedAt: String,

@Value("\${event.late-diff-minute}")
@Schema(description = "지각 기준 시간 (분)")
val lateDiffMinute: Int,

@Value("\${event.absent-diff-minute}")
@Schema(description = "결석 기준 시간 (분)")
val absentDiffMinute: Int
) {
fun entity() = Event (
id = UUID.randomUUID(),
generationID = this.generationID,
title = this.title,
description = this.description,
expectedAt = LocalDateTime.parse(this.expectedAt),
startAt = LocalDateTime.parse(this.expectedAt),
lateDiffMinutes = this.lateDiffMinute,
absentDiffMinutes = this.absentDiffMinute,
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now()
)

companion object {
const val Example = """
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.example.attendanceapimono.application.dto.event

import com.example.attendanceapimono.domain.event.Event
import io.swagger.v3.oas.annotations.media.Schema
import java.util.*

@Schema(
title = "이벤트 등록 후 반환",
Expand All @@ -10,22 +10,12 @@ import io.swagger.v3.oas.annotations.media.Schema
)
data class CreateEventResponse (
@Schema(description = "생성된 event")
val event: Event,
val eventId: UUID,
) {
companion object {
const val Example = """
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"generationID": 6,
"title": "오리엔테이션",
"description": "함께 모여 앞으로의 방향에 대해 이야기 나눠 보아요.",
"isDone": false,
"expectedAt": "2021-08-21T14:00:00.000",
"lateDiffMinute": 10,
"absentDiffMinute": 60,
"startAt": null,
"createdAt": "2021-08-12T22:13:47.245",
"updatedAt": "2021-08-12T22:13:47.245"
"id": "123e4567-e89b-12d3-a456-426614174000"
}
"""
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/application-local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ spring:
format_sql: true
jwt:
secret: test_QiPScSmMJnGrGCwTm*Xi0m1yAHe3KfAkhH&VpsENjwqfGP%grBdmv4Ee%GYZhNj2S4y6@$8KORZE9dsiw%v*ugKcba9x8CN18!Pl
expires: 31536000000000
expires: 31536000000000
event:
late-diff-minute: 10
absent-diff-minute: 50
5 changes: 4 additions & 1 deletion src/main/resources/application-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ spring:
format_sql: true
jwt:
secret: ${JWT_SECRET}
expires: ${JWT_EXPIRES}
expires: ${JWT_EXPIRES}
event:
late-diff-minute: ${DDD_LATE_DIFF_MINUTE}
absent-diff-minute: ${DDD_ABSENT_DIFF_MINUTE}