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

merge: (#1) Student Login API #4

Merged
merged 23 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
07b8bd7
Merge branch 'main' into develop
khcho0125 Mar 21, 2023
0560620
add: (#1) suspend transaction funtion
khcho0125 Mar 21, 2023
04d716d
add: (#1) Student Query Extend
khcho0125 Mar 21, 2023
4392682
chore: (#1) Change Import
khcho0125 Mar 21, 2023
922d859
add: (#1) Student Login UseCase
khcho0125 Mar 21, 2023
570465a
chore: (#1) Naming Mistake - SecurityApi → StudentApi
khcho0125 Mar 22, 2023
c007b1d
docs: (#1) Add Comment
khcho0125 Mar 22, 2023
dc4a552
add: (#1) Jwt Validation
khcho0125 Mar 22, 2023
a8ef9cb
add: (#1) Constant Prefix
khcho0125 Mar 22, 2023
40c0612
add: (#1) Student QueryFactory
khcho0125 Mar 22, 2023
50d7410
refactor: (#1) Entity → Data Class
khcho0125 Mar 22, 2023
22d17bd
add: (#1) Login - Find Student
khcho0125 Mar 22, 2023
b330979
chore: (#1) Clean Code Rule - Return Value
khcho0125 Mar 22, 2023
3808ae3
chore: (#1) Import Class Cleaning
khcho0125 Mar 22, 2023
a0b11ae
add: (#1) QueryFactory Injecting
khcho0125 Mar 22, 2023
a8ad3b3
add: (#1) Negotiating Configure
khcho0125 Mar 23, 2023
635da9d
add: (#1) Additional Student Query
khcho0125 Mar 23, 2023
26693a1
add: (#1) BCrypt Password Formatter
khcho0125 Mar 23, 2023
32f7590
build: (#1) Introduce Code Analysis Detekt
khcho0125 Mar 23, 2023
53a1e9b
refactor: (#1) Detekt Rules Violeted Code Change
khcho0125 Mar 23, 2023
c1724f5
refactor: (#1) BCrypt → Password Replace Name
khcho0125 Mar 30, 2023
3313a9b
refactor: (#1) Using Non-Label Pattern
khcho0125 Mar 30, 2023
8d21525
refactor: (#1) Naming Replace TokenContainer
khcho0125 Mar 30, 2023
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
15 changes: 15 additions & 0 deletions src/main/kotlin/com/dsm_delivery/api/Api.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.dsm_delivery.api

import io.ktor.server.application.*
import io.ktor.server.routing.*

/**
*
* Routing을 도와주는 Api
*
* @author Chokyunghyeon
* @date 2023/03/22
**/
abstract class Api(private val route: Routing.() -> Unit) {
operator fun invoke(app: Application): Routing = app.routing(route)
}
31 changes: 31 additions & 0 deletions src/main/kotlin/com/dsm_delivery/api/StudentApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.dsm_delivery.api

import com.dsm_delivery.domain.auth.usecase.StudentLogin
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

/**
*
* 학생의 API를 관리하는 StudentApi
*
* @author Chokyunghyeon
* @date 2023/03/22
**/
class StudentApi(
studentLogin: StudentLogin
) : Api({
route("/student") {
post("/login") {
val request: StudentLogin.Request = call.receive()
call.respond(
status = HttpStatusCode.OK,
message = studentLogin(request)
)
}


}
})
8 changes: 0 additions & 8 deletions src/main/kotlin/com/dsm_delivery/domain/Api.kt

This file was deleted.

18 changes: 0 additions & 18 deletions src/main/kotlin/com/dsm_delivery/domain/auth/AuthApi.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.dsm_delivery.domain.auth.token
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.dsm_delivery.plugins.SecurityProperties
import io.ktor.server.application.*
import java.time.LocalDateTime
import java.util.Date
import java.util.UUID
Expand All @@ -25,7 +24,7 @@ class JwtGenerator(
private val securityProperties: SecurityProperties
) : TokenProvider {

private fun generateRefreshToken() : String {
private fun generateRefreshToken(): String {
return JWT.create()
.withSubject(JWT_SUBJECT)
.withKeyId(JWT_REFRESH)
Expand All @@ -36,7 +35,7 @@ class JwtGenerator(

}

private fun generateAccessToken(studentId: UUID) : String {
private fun generateAccessToken(studentId: UUID): String {
return JWT.create()
.withSubject(JWT_SUBJECT)
.withKeyId(JWT_ACCESS)
Expand All @@ -47,15 +46,15 @@ class JwtGenerator(
.sign(Algorithm.HMAC256(securityProperties.secret))
}

override suspend fun generateToken(studentId: UUID) : TokenCarton {
override suspend fun generateToken(studentId: UUID): TokenCarton {
return TokenCarton(
accessToken = generateAccessToken(studentId),
refreshToken = generateRefreshToken(),
accessTokenExpired = LocalDateTime.now().plusSeconds(securityProperties.accessExpired)
)
}

private companion object {
companion object {
const val JWT_SUBJECT = "Authentication"
const val JWT_REFRESH = "Refresh"
const val JWT_ACCESS = "Access"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.dsm_delivery.domain.auth.usecase

import com.dsm_delivery.domain.auth.token.TokenCarton
import com.dsm_delivery.domain.auth.token.TokenProvider
import com.dsm_delivery.persistence.entity.Student
import com.dsm_delivery.persistence.repository.StudentRepository

/**
*
Expand All @@ -10,9 +13,20 @@ import com.dsm_delivery.domain.auth.token.TokenProvider
* @date 2023/03/20
**/
class StudentLogin(
private val tokenProvider: TokenProvider
private val tokenProvider: TokenProvider,
private val studentRepository: StudentRepository
) {
operator fun invoke() {
suspend operator fun invoke(request: Request): TokenCarton {
khcho0125 marked this conversation as resolved.
Show resolved Hide resolved
val student: Student = studentRepository.findByNumber(request.number)
?: TODO()

// TODO: Password Authentication

return tokenProvider.generateToken(student.id)
}

data class Request(
val number: Int,
val password: String
)
}
19 changes: 8 additions & 11 deletions src/main/kotlin/com/dsm_delivery/persistence/entity/Mission.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.dsm_delivery.persistence.entity

import org.jetbrains.exposed.dao.UUIDEntity
import org.jetbrains.exposed.dao.UUIDEntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.UUIDTable
import org.jetbrains.exposed.sql.Column
Expand All @@ -28,12 +26,11 @@ enum class DeliveryState {
POSTING, DELIVERING, COMPLETED, MISSED
}

class Mission(id: EntityID<UUID>) : UUIDEntity(id) {
companion object : UUIDEntityClass<Mission>(MissionTable)

val student: Student by Student referencedOn MissionTable.student
var state: DeliveryState by MissionTable.state
var stuff: String by MissionTable.stuff
var deadline: LocalDateTime by MissionTable.deadline
var deliveryState: Student? by Student optionalReferencedOn MissionTable.deliveryman
}
data class Mission(
val id: UUID,
val studentId: UUID,
val deliverymanId: UUID,
val stuff: String,
val deadline: LocalDateTime,
val state: DeliveryState
)
18 changes: 8 additions & 10 deletions src/main/kotlin/com/dsm_delivery/persistence/entity/Student.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.dsm_delivery.persistence.entity

import org.jetbrains.exposed.dao.UUIDEntity
import org.jetbrains.exposed.dao.UUIDEntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.UUIDTable
import org.jetbrains.exposed.sql.Column
import java.util.UUID
Expand All @@ -18,16 +15,17 @@ object StudentTable : UUIDTable("tbl_student") {
val name: Column<String> = varchar("name", 20)
val number: Column<Int> = integer("school_number")
val sex: Column<Sex> = enumerationByName("sex", 6, Sex::class)
val password: Column<String> = char("password", 60)
}

enum class Sex {
FEMALE, MALE
}

class Student(id: EntityID<UUID>) : UUIDEntity(id) {
companion object : UUIDEntityClass<Student>(StudentTable)

var name: String by StudentTable.name
var number: Int by StudentTable.number
val sex: Sex by StudentTable.sex
}
data class Student(
val id: UUID,
val name: String,
val number: Int,
val sex: Sex,
val password: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.dsm_delivery.persistence.factory

import com.dsm_delivery.persistence.entity.Student
import com.dsm_delivery.persistence.entity.StudentTable
import com.dsm_delivery.persistence.repository.StudentRepository
import com.dsm_delivery.plugins.DataBaseFactory.dbQuery
import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.select
import java.util.UUID

/**
*
* 학생에 관한 질의를 요청하는 StudentQuery
*
* @author Chokyunghyeon
* @date 2023/03/22
**/
class StudentQueryFactory : StudentRepository {

private fun toEntity(row: ResultRow): Student = Student(
id = row[StudentTable.id].value,
name = row[StudentTable.name],
number = row[StudentTable.number],
password = row[StudentTable.password],
sex = row[StudentTable.sex]
)

override suspend fun findById(id: UUID): Student? = dbQuery {
StudentTable
.select { StudentTable.id eq id }
.singleOrNull()
?.let(::toEntity)
}

override suspend fun findByNumber(number: Int): Student? = dbQuery {
StudentTable
.select { StudentTable.number eq number }
.singleOrNull()
?.let(::toEntity)
}

override suspend fun findByName(name: String): Student? = dbQuery {
StudentTable
.select { StudentTable.name eq name }
.singleOrNull()
?.let(::toEntity)
}

override suspend fun findBy(where: () -> Op<Boolean>): Student? = dbQuery {
StudentTable
.select(where())
.singleOrNull()
?.let(::toEntity)
}

override suspend fun existsById(id: UUID): Boolean = dbQuery {
StudentTable
.select { StudentTable.id eq id }
.empty()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.dsm_delivery.persistence.repository

import com.dsm_delivery.persistence.entity.Student
import org.jetbrains.exposed.sql.Op
import java.util.UUID

/**
*
* 학생을 관리하는 StudentRepository
*
* @author Chokyunghyeon
* @date 2023/03/22
**/
interface StudentRepository {
suspend fun findById(id: UUID): Student?

suspend fun findByNumber(number: Int): Student?

suspend fun findByName(name: String): Student?

suspend fun findBy(where: () -> Op<Boolean>): Student?

suspend fun existsById(id: UUID): Boolean
}
18 changes: 14 additions & 4 deletions src/main/kotlin/com/dsm_delivery/plugins/DataBaseFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import com.dsm_delivery.persistence.entity.StudentTable
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import io.ktor.server.config.*
import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.StdOutSqlLogger
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction

/**
Expand All @@ -21,10 +23,11 @@ import org.jetbrains.exposed.sql.transactions.transaction
**/
object DataBaseFactory {

private const val DB_URL = "database.url"
private const val DB_DRIVER = "database.driver"
private const val DB_USER = "database.user"
private const val DB_PASSWD = "database.password"
private const val DB_PREFIX = "database"
private const val DB_URL = "$DB_PREFIX.url"
private const val DB_DRIVER = "$DB_PREFIX.driver"
private const val DB_USER = "$DB_PREFIX.user"
private const val DB_PASSWD = "$DB_PREFIX.password"

operator fun invoke(config: ApplicationConfig) {
val database = Database.connect(
Expand All @@ -47,4 +50,11 @@ object DataBaseFactory {
}
}

suspend fun <T> dbQuery(database: Database? = null, block: () -> T) : T = newSuspendedTransaction(
db = database, context = Dispatchers.IO
) {
addLogger(StdOutSqlLogger)
block()
}

}
Loading