code dump
This commit is contained in:
parent
f8165fccbd
commit
562fef9d92
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
.gradle
|
||||
build/
|
||||
gen/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
@ -1,6 +1,8 @@
|
||||
val ktor_version: String by project
|
||||
val kotlin_version: String by project
|
||||
val logback_version: String by project
|
||||
val ktorm_version: String by project
|
||||
val postgresql_driver_version: String by project
|
||||
|
||||
plugins {
|
||||
application
|
||||
@ -27,10 +29,13 @@ dependencies {
|
||||
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:$ktor_version")
|
||||
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
|
||||
implementation("org.ktorm:ktorm-core:3.4.1")
|
||||
implementation("org.ktorm:ktorm-support-postgresql:3.4.1")
|
||||
implementation("org.postgresql:postgresql:42.2.2")
|
||||
implementation("io.ktor:ktor-server-auth:$ktor_version")
|
||||
implementation("io.ktor:ktor-server-auth-jwt:$ktor_version")
|
||||
implementation("org.ktorm:ktorm-core:$ktorm_version")
|
||||
implementation("org.ktorm:ktorm-support-postgresql:$ktorm_version")
|
||||
implementation("org.postgresql:postgresql:$postgresql_driver_version")
|
||||
implementation("ch.qos.logback:logback-classic:$logback_version")
|
||||
implementation("org.mindrot:jbcrypt:0.4")
|
||||
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
|
||||
}
|
@ -2,8 +2,9 @@ package com.wyattjmiller
|
||||
|
||||
import io.ktor.server.application.*
|
||||
import com.wyattjmiller.plugins.*
|
||||
import com.wyattjmiller.routes.AuthorRoute.Companion.authorRoutes
|
||||
import com.wyattjmiller.routes.RecipeRoute.Companion.recipeRoutes
|
||||
import io.ktor.server.config.*
|
||||
import com.wyattjmiller.routes.UserRoute.Companion.userRoutes
|
||||
|
||||
fun main(args: Array<String>): Unit =
|
||||
io.ktor.server.netty.EngineMain.main(args)
|
||||
@ -12,8 +13,7 @@ fun main(args: Array<String>): Unit =
|
||||
fun Application.module() {
|
||||
//val config = this.environment.config
|
||||
|
||||
configureRouting()
|
||||
configureAuthentication()
|
||||
configureSerialization()
|
||||
|
||||
recipeRoutes()
|
||||
configureRouting()
|
||||
}
|
||||
|
31
src/main/kotlin/com/wyattjmiller/auth/JwtConfig.kt
Normal file
31
src/main/kotlin/com/wyattjmiller/auth/JwtConfig.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package com.wyattjmiller.auth
|
||||
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.JWTVerifier
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import com.wyattjmiller.entities.UserLogin
|
||||
import io.ktor.server.config.*
|
||||
import java.util.*
|
||||
|
||||
class JwtConfig(config: HoconApplicationConfig) {
|
||||
private val audience = config.property("audience").getString()
|
||||
private val secret = config.property("secret").getString()
|
||||
private val issuer = config.property("issuer").getString()
|
||||
private val expirationDate = System.currentTimeMillis() + 60000
|
||||
|
||||
fun generateJwtToken(user: UserLogin): String {
|
||||
return JWT.create()
|
||||
.withAudience(audience)
|
||||
.withIssuer(issuer)
|
||||
.withClaim("username", user.username)
|
||||
.withExpiresAt(Date(expirationDate))
|
||||
.sign(Algorithm.HMAC256(secret))
|
||||
}
|
||||
|
||||
fun verifyJwtToken() : JWTVerifier {
|
||||
return JWT.require(Algorithm.HMAC256(secret))
|
||||
.withAudience(audience)
|
||||
.withIssuer(issuer)
|
||||
.build()
|
||||
}
|
||||
}
|
@ -1,16 +1,11 @@
|
||||
package com.wyattjmiller.data
|
||||
|
||||
import io.ktor.server.config.*
|
||||
import org.ktorm.database.Database
|
||||
|
||||
class DatabaseManager() {
|
||||
var database: Database
|
||||
|
||||
init {
|
||||
database = Database.connect("jdbc:postgresql://10.10.10.21:5432/recipefolio",
|
||||
var database: Database = Database.connect("jdbc:postgresql://10.10.10.21:5432/recipefolio",
|
||||
"org.postgresql.Driver",
|
||||
user = "wyatt",
|
||||
password = "wjm"
|
||||
)
|
||||
}
|
||||
}
|
@ -1,22 +1,42 @@
|
||||
package com.wyattjmiller.data
|
||||
|
||||
import org.ktorm.entity.Entity
|
||||
import org.ktorm.schema.Table
|
||||
import org.ktorm.schema.int
|
||||
import org.ktorm.schema.varchar
|
||||
import org.ktorm.schema.*
|
||||
import java.time.LocalDateTime
|
||||
|
||||
object DbRecipeTable : Table<DbRecipeEntity>("recipe") {
|
||||
object DbRecipeTable : Table<Recipes>("recipe") {
|
||||
val id = int("id").primaryKey().bindTo { it.id }
|
||||
val name = varchar("name").bindTo { it.name }
|
||||
val desc = varchar("description").bindTo { it.desc }
|
||||
val ingredients = varchar("ingredients").bindTo { it.ingredients }
|
||||
val author = int("author_id").references(DbAuthorTable) { it.author }
|
||||
val createdTimestamp = datetime("created_timestamp").bindTo { it.createdTimestamp }
|
||||
}
|
||||
|
||||
interface DbRecipeEntity : Entity<DbRecipeEntity> {
|
||||
companion object : Entity.Factory<DbRecipeEntity>()
|
||||
object DbAuthorTable : Table<Authors>("author") {
|
||||
val id = int("id").primaryKey().bindTo { it.id }
|
||||
val authorName = varchar("author_name").bindTo { it.authorName }
|
||||
val user = int("user_id").references(DbUserTable) { it.user }
|
||||
val createdTimestamp = datetime("created_timestamp").bindTo { it.createdTimestamp }
|
||||
}
|
||||
|
||||
val id: Int
|
||||
interface Recipes : Entity<Recipes> {
|
||||
companion object : Entity.Factory<Recipes>()
|
||||
|
||||
val id: Int?
|
||||
val name: String
|
||||
val desc: String
|
||||
val ingredients: String
|
||||
val author: Authors
|
||||
val createdTimestamp: LocalDateTime
|
||||
}
|
||||
|
||||
interface Authors : Entity<Authors> {
|
||||
companion object : Entity.Factory<Authors>()
|
||||
|
||||
val id: Int
|
||||
val authorName: String
|
||||
val user: Users?
|
||||
val createdTimestamp: LocalDateTime
|
||||
}
|
||||
|
||||
|
33
src/main/kotlin/com/wyattjmiller/data/UserEntities.kt
Normal file
33
src/main/kotlin/com/wyattjmiller/data/UserEntities.kt
Normal file
@ -0,0 +1,33 @@
|
||||
package com.wyattjmiller.data
|
||||
|
||||
import io.ktor.server.auth.*
|
||||
import org.ktorm.entity.Entity
|
||||
import org.ktorm.schema.Table
|
||||
import org.ktorm.schema.datetime
|
||||
import org.ktorm.schema.int
|
||||
import org.ktorm.schema.varchar
|
||||
import java.time.LocalDateTime
|
||||
|
||||
object DbUserTable : Table<Users>("user") {
|
||||
val id = int("id").primaryKey().bindTo { it.id }
|
||||
val firstName = varchar("first_name").bindTo { it.firstName }
|
||||
val lastName = varchar("last_name").bindTo { it.lastName }
|
||||
val username = varchar("username").bindTo { it.username }
|
||||
val password = varchar("password").bindTo { it.password }
|
||||
val emailAddress = varchar("email_address").bindTo { it.emailAddress }
|
||||
val createdTimestamp = datetime("created_timestamp").bindTo { it.createdTimestamp }
|
||||
//val createdAuthors = int("created_authors").references(DbAuthorTable) { it.createdAuthors }
|
||||
}
|
||||
|
||||
interface Users : Entity<Users> {
|
||||
companion object : Entity.Factory<Users>()
|
||||
|
||||
val id: Int
|
||||
val firstName: String
|
||||
val lastName: String
|
||||
val username: String
|
||||
val password: String
|
||||
val emailAddress: String
|
||||
val createdTimestamp: LocalDateTime
|
||||
//val createdAuthors get() = listOf(DbAuthorTable.id)
|
||||
}
|
21
src/main/kotlin/com/wyattjmiller/entities/Author.kt
Normal file
21
src/main/kotlin/com/wyattjmiller/entities/Author.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.wyattjmiller.entities
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
|
||||
@Serializable
|
||||
@SerialName("Author")
|
||||
data class Author(
|
||||
val id: Int?,
|
||||
val authorName: String,
|
||||
val user: Int,
|
||||
var createdTimestamp: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@SerialName("AuthorDraft")
|
||||
data class AuthorDraft(
|
||||
val authorName: String,
|
||||
val user: Int? = null,
|
||||
)
|
@ -1,11 +1,24 @@
|
||||
package com.wyattjmiller.entities
|
||||
|
||||
import com.wyattjmiller.data.Authors
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("Recipe")
|
||||
data class Recipe(
|
||||
val id: Int,
|
||||
val id: Int?,
|
||||
val name: String,
|
||||
val desc: String,
|
||||
val ingredients: String,
|
||||
var createdTimestamp: String,
|
||||
val author: Int,
|
||||
)
|
||||
@Serializable
|
||||
@SerialName("RecipeDraft")
|
||||
data class RecipeDraft(
|
||||
val name: String,
|
||||
val desc: String,
|
||||
val ingredients: String,
|
||||
val author: Int,
|
||||
)
|
||||
|
@ -1,12 +1,32 @@
|
||||
package com.wyattjmiller.entities
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.sql.Timestamp
|
||||
|
||||
@Serializable
|
||||
data class User(
|
||||
val id: Int,
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
val username: String,
|
||||
val emailAddress: String,
|
||||
val password: String,
|
||||
val createdTimestamp: String,
|
||||
val createdAuthors: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class UserLogin(
|
||||
val username: String,
|
||||
val password: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class UserDraft(
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
val username: String,
|
||||
val emailAddress: String,
|
||||
val password: String,
|
||||
val createdTimestamp: String
|
||||
)
|
15
src/main/kotlin/com/wyattjmiller/openapi.json
Normal file
15
src/main/kotlin/com/wyattjmiller/openapi.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "RecipeFolio RESTful API",
|
||||
"description": "Just a reference! Nothing to see here! **Wyatt proceeds to smuggle servers into a closet**",
|
||||
"version": "0.0.3 SE-B012"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
}
|
||||
}
|
30
src/main/kotlin/com/wyattjmiller/plugins/Authentication.kt
Normal file
30
src/main/kotlin/com/wyattjmiller/plugins/Authentication.kt
Normal file
@ -0,0 +1,30 @@
|
||||
package com.wyattjmiller.plugins
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.wyattjmiller.auth.JwtConfig
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import io.ktor.server.config.*
|
||||
|
||||
fun Application.configureAuthentication() {
|
||||
val config = HoconApplicationConfig(ConfigFactory.load())
|
||||
val tokenManager = JwtConfig(config)
|
||||
|
||||
install(Authentication) {
|
||||
jwt {
|
||||
verifier(tokenManager.verifyJwtToken())
|
||||
realm = config.property("realm").getString()
|
||||
|
||||
validate { jwt ->
|
||||
if (jwt.payload.getClaim("username").asString().isNotEmpty()) {
|
||||
JWTPrincipal(jwt.payload)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,10 +1,15 @@
|
||||
package com.wyattjmiller.plugins
|
||||
|
||||
import com.wyattjmiller.routes.AuthorRoute.Companion.authorRoutes
|
||||
import com.wyattjmiller.routes.RecipeRoute.Companion.recipeRoutes
|
||||
import com.wyattjmiller.routes.UserRoute.Companion.userRoutes
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.application.*
|
||||
|
||||
fun Application.configureRouting() {
|
||||
routing {
|
||||
|
||||
this@configureRouting.recipeRoutes()
|
||||
this@configureRouting.authorRoutes()
|
||||
this@configureRouting.userRoutes()
|
||||
}
|
||||
}
|
||||
|
@ -3,17 +3,13 @@ package com.wyattjmiller.plugins
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
fun Application.configureSerialization() {
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
|
||||
routing {
|
||||
get("/json/kotlinx-serialization") {
|
||||
call.respond(mapOf("hello" to "world"))
|
||||
}
|
||||
json( Json {
|
||||
explicitNulls = true
|
||||
prettyPrint = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
66
src/main/kotlin/com/wyattjmiller/repositories/AuthorDao.kt
Normal file
66
src/main/kotlin/com/wyattjmiller/repositories/AuthorDao.kt
Normal file
@ -0,0 +1,66 @@
|
||||
package com.wyattjmiller.repositories
|
||||
|
||||
import com.wyattjmiller.data.DatabaseManager
|
||||
import com.wyattjmiller.data.DbAuthorTable
|
||||
import com.wyattjmiller.entities.Author
|
||||
import com.wyattjmiller.entities.AuthorDraft
|
||||
import org.ktorm.dsl.delete
|
||||
import org.ktorm.dsl.eq
|
||||
import org.ktorm.dsl.insertAndGenerateKey
|
||||
import org.ktorm.dsl.update
|
||||
import org.ktorm.entity.firstOrNull
|
||||
import org.ktorm.entity.sequenceOf
|
||||
import org.ktorm.entity.toList
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class AuthorDao : AuthorRepository {
|
||||
private val db = DatabaseManager().database
|
||||
|
||||
override fun getAllAuthors() : List<Author> {
|
||||
return db
|
||||
.sequenceOf(DbAuthorTable)
|
||||
.toList()
|
||||
.map {
|
||||
Author(it.id, it.authorName, it.user!!.id, it.createdTimestamp.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAuthor(id: Int) : Author {
|
||||
return db
|
||||
.sequenceOf(DbAuthorTable)
|
||||
.firstOrNull {
|
||||
it.id eq id
|
||||
}
|
||||
.let {
|
||||
Author(it!!.id, it.authorName, it.user!!.id, it.createdTimestamp.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun createAuthor(author: AuthorDraft) {
|
||||
db.insertAndGenerateKey(DbAuthorTable) {
|
||||
set(DbAuthorTable.authorName, author.authorName)
|
||||
set(DbAuthorTable.user, author.user)
|
||||
set(DbAuthorTable.createdTimestamp, LocalDateTime.now())
|
||||
} as Int
|
||||
}
|
||||
|
||||
override fun updateAuthor(id: Int, author: AuthorDraft) : Boolean {
|
||||
val updatedRows = db.update(DbAuthorTable) {
|
||||
set(DbAuthorTable.authorName, author.authorName)
|
||||
set(DbAuthorTable.user, author.user)
|
||||
where {
|
||||
it.id eq id
|
||||
}
|
||||
}
|
||||
|
||||
return updatedRows > 0
|
||||
}
|
||||
|
||||
override fun deleteAuthor(id: Int) : Boolean {
|
||||
val deletedRows = db.delete(DbAuthorTable) {
|
||||
it.id eq id
|
||||
}
|
||||
|
||||
return deletedRows > 0
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.wyattjmiller.repositories
|
||||
|
||||
import com.wyattjmiller.entities.Author
|
||||
import com.wyattjmiller.entities.AuthorDraft
|
||||
|
||||
interface AuthorRepository {
|
||||
fun getAllAuthors() : List<Author>
|
||||
fun getAuthor(id: Int) : Author?
|
||||
fun createAuthor(author: AuthorDraft)
|
||||
fun updateAuthor(id: Int, author: AuthorDraft) : Boolean
|
||||
fun deleteAuthor(id: Int) : Boolean
|
||||
}
|
@ -3,8 +3,13 @@ package com.wyattjmiller.repositories
|
||||
import com.wyattjmiller.data.DatabaseManager
|
||||
import com.wyattjmiller.data.DbRecipeTable
|
||||
import com.wyattjmiller.entities.Recipe
|
||||
import com.wyattjmiller.entities.RecipeDraft
|
||||
import org.ktorm.dsl.delete
|
||||
import org.ktorm.dsl.eq
|
||||
import org.ktorm.dsl.insertAndGenerateKey
|
||||
import org.ktorm.dsl.update
|
||||
import org.ktorm.entity.*
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class RecipeDao : RecipeRepository {
|
||||
private val db = DatabaseManager()
|
||||
@ -13,25 +18,52 @@ class RecipeDao : RecipeRepository {
|
||||
return db.database
|
||||
.sequenceOf(DbRecipeTable)
|
||||
.toList()
|
||||
.map { Recipe(it.id, it.name, it.desc, it.ingredients) }
|
||||
.map {
|
||||
Recipe(it.id, it.name, it.desc, it.ingredients, it.createdTimestamp.toString(), it.author.id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRecipe(id: Int) : Recipe {
|
||||
return db.database
|
||||
.sequenceOf(DbRecipeTable)
|
||||
.firstOrNull { it.id eq id }
|
||||
.let { Recipe(it!!.id, it.name, it.desc, it.ingredients) }
|
||||
.firstOrNull {
|
||||
it.id eq id
|
||||
}
|
||||
.let {
|
||||
Recipe(it!!.id, it.name, it.desc, it.ingredients, it.createdTimestamp.toString(), it.author.id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createRecipe(recipe: Recipe) {
|
||||
TODO("Not yet implemented")
|
||||
override fun createRecipe(recipe: RecipeDraft) : Recipe {
|
||||
val key = db.database.insertAndGenerateKey(DbRecipeTable) {
|
||||
set(DbRecipeTable.name, recipe.name)
|
||||
set(DbRecipeTable.desc, recipe.desc)
|
||||
set(DbRecipeTable.ingredients, recipe.ingredients)
|
||||
set(DbRecipeTable.createdTimestamp, LocalDateTime.now())
|
||||
set(DbRecipeTable.author, recipe.author)
|
||||
} as Int
|
||||
|
||||
return Recipe(key, recipe.name, recipe.desc, recipe.ingredients, LocalDateTime.now().toString(), recipe.author)
|
||||
}
|
||||
|
||||
override fun updateRecipe(id: Int, recipe: Recipe): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
override fun updateRecipe(id: Int, recipe: RecipeDraft) : Boolean {
|
||||
val updatedRows = db.database.update(DbRecipeTable) {
|
||||
set(DbRecipeTable.name, recipe!!.name)
|
||||
set(DbRecipeTable.desc, recipe!!.desc)
|
||||
set(DbRecipeTable.ingredients, recipe!!.ingredients)
|
||||
where {
|
||||
it.id eq id
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteRecipe(id: Int) {
|
||||
TODO("Not yet implemented")
|
||||
return updatedRows > 0
|
||||
}
|
||||
|
||||
override fun deleteRecipe(id: Int) : Boolean {
|
||||
val deletedRows = db.database.delete(DbRecipeTable) {
|
||||
it.id eq id
|
||||
}
|
||||
|
||||
return deletedRows > 0
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
package com.wyattjmiller.repositories
|
||||
|
||||
import com.wyattjmiller.entities.Recipe
|
||||
import com.wyattjmiller.entities.RecipeDraft
|
||||
|
||||
interface RecipeRepository {
|
||||
fun getAllRecipies() : List<Recipe>
|
||||
fun getRecipe(id: Int) : Recipe?
|
||||
fun createRecipe(recipe: Recipe)
|
||||
fun updateRecipe(id: Int, recipe: Recipe): Boolean
|
||||
fun deleteRecipe(id: Int)
|
||||
fun createRecipe(recipe: RecipeDraft) : Recipe
|
||||
fun updateRecipe(id: Int, recipe: RecipeDraft) : Boolean
|
||||
fun deleteRecipe(id: Int) : Boolean
|
||||
}
|
75
src/main/kotlin/com/wyattjmiller/repositories/UserDao.kt
Normal file
75
src/main/kotlin/com/wyattjmiller/repositories/UserDao.kt
Normal file
@ -0,0 +1,75 @@
|
||||
package com.wyattjmiller.repositories
|
||||
|
||||
import com.wyattjmiller.data.DatabaseManager
|
||||
import com.wyattjmiller.data.DbAuthorTable
|
||||
import com.wyattjmiller.data.DbUserTable
|
||||
import com.wyattjmiller.data.DbUserTable.password
|
||||
import com.wyattjmiller.data.DbUserTable.username
|
||||
import com.wyattjmiller.entities.Author
|
||||
import com.wyattjmiller.entities.User
|
||||
import com.wyattjmiller.entities.UserDraft
|
||||
import com.wyattjmiller.entities.UserLogin
|
||||
import org.ktorm.dsl.*
|
||||
import org.ktorm.entity.firstOrNull
|
||||
import org.ktorm.entity.sequenceOf
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class UserDao : UserRepository {
|
||||
private val db = DatabaseManager().database
|
||||
|
||||
fun usernameCheck(user: UserLogin) : UserLogin? {
|
||||
return db.from(DbUserTable)
|
||||
.select()
|
||||
.where { username eq user.username }
|
||||
.map {
|
||||
// don't know what to do here
|
||||
UserLogin(user.username, user.password)
|
||||
}.firstOrNull()
|
||||
}
|
||||
|
||||
fun passwordCheck(user: UserLogin) : UserLogin? {
|
||||
return db.from(DbUserTable)
|
||||
.select()
|
||||
.where { password eq user.password }
|
||||
.map {
|
||||
// don't know what to do here
|
||||
UserLogin(user.username, user.password)
|
||||
}.firstOrNull()
|
||||
}
|
||||
|
||||
fun getAllUsers() {
|
||||
TODO("Joke's on you! This function is not implemented yet. -Wyatt")
|
||||
}
|
||||
|
||||
override fun getUser(id: Int): User? {
|
||||
return db
|
||||
.sequenceOf(DbUserTable)
|
||||
.firstOrNull {
|
||||
it.id eq id
|
||||
}
|
||||
.let {
|
||||
User(it!!.id, it.firstName, it.lastName, it.username, it.password, it.emailAddress, it.createdTimestamp.toString(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createUser(user: UserDraft): User {
|
||||
val key = db.insertAndGenerateKey(DbUserTable) {
|
||||
set(DbUserTable.firstName, user.firstName)
|
||||
set(DbUserTable.lastName, user.lastName)
|
||||
set(DbUserTable.username, user.username)
|
||||
set(DbUserTable.password, user.password)
|
||||
set(DbUserTable.emailAddress, user.emailAddress)
|
||||
set(DbUserTable.createdTimestamp, LocalDateTime.now())
|
||||
} as Int
|
||||
|
||||
return User(key, user.firstName, user.lastName, user.username, user.password, user.emailAddress, LocalDateTime.now().toString(), 0)
|
||||
}
|
||||
|
||||
override fun updateUser(id: Int, user: UserDraft): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun deleteUser(id: Int): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.wyattjmiller.repositories
|
||||
|
||||
import com.wyattjmiller.entities.User
|
||||
import com.wyattjmiller.entities.UserDraft
|
||||
|
||||
interface UserRepository {
|
||||
fun getUser(id: Int) : User?
|
||||
fun createUser(user: UserDraft) : User
|
||||
fun updateUser(id: Int, user: UserDraft) : Boolean
|
||||
fun deleteUser(id: Int) : Boolean
|
||||
}
|
69
src/main/kotlin/com/wyattjmiller/routes/AuthorRoute.kt
Normal file
69
src/main/kotlin/com/wyattjmiller/routes/AuthorRoute.kt
Normal file
@ -0,0 +1,69 @@
|
||||
package com.wyattjmiller.routes
|
||||
|
||||
import com.wyattjmiller.entities.AuthorDraft
|
||||
import com.wyattjmiller.repositories.AuthorDao
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
class AuthorRoute {
|
||||
companion object {
|
||||
private val author = AuthorDao()
|
||||
|
||||
private fun Route.getAllAuthors() {
|
||||
get("/author") {
|
||||
call.respond(author.getAllAuthors())
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.getAuthor() {
|
||||
get("/author/{id?}") {
|
||||
val id = call.parameters["id"]?.toInt() ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest, "Missing author identifier :("
|
||||
)
|
||||
|
||||
val res = author.getAuthor(id) ?: return@get call.respond(
|
||||
HttpStatusCode.NotFound, "No recipe found :("
|
||||
)
|
||||
|
||||
call.respond(res)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.createAuthor() {
|
||||
post("/author") {
|
||||
val req = call.receive<AuthorDraft>()
|
||||
val res = author.createAuthor(req)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.updateAuthor() {
|
||||
put("/author/{id?}") {
|
||||
val req = call.receive<AuthorDraft>()
|
||||
val id = call.parameters["id"]?.toIntOrNull() ?: return@put call.respond(
|
||||
HttpStatusCode.BadRequest, "Missing author identifier :("
|
||||
)
|
||||
|
||||
if (author.updateAuthor(id, req)) {
|
||||
call.respond(HttpStatusCode.Created)
|
||||
} else {
|
||||
call.respond(
|
||||
HttpStatusCode.NotFound, "No author found :("
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.authorRoutes() {
|
||||
routing {
|
||||
getAllAuthors()
|
||||
getAuthor()
|
||||
createAuthor()
|
||||
updateAuthor()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
package com.wyattjmiller.routes
|
||||
|
||||
import com.wyattjmiller.entities.RecipeDraft
|
||||
import com.wyattjmiller.repositories.RecipeDao
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
@ -30,10 +32,36 @@ class RecipeRoute {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.createRecipe() {
|
||||
post("/recipe") {
|
||||
val req = call.receive<RecipeDraft>()
|
||||
val res = rec.createRecipe(req)
|
||||
call.respond(res)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.updateRecipe() {
|
||||
put("/recipe/{id?}") {
|
||||
val req = call.receive<RecipeDraft>()
|
||||
val id = call.parameters["id"]?.toIntOrNull() ?: return@put call.respond(
|
||||
HttpStatusCode.BadRequest,"Missing recipe identifier :("
|
||||
)
|
||||
|
||||
if (rec.updateRecipe(id, req)) {
|
||||
call.respond(HttpStatusCode.OK)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound,
|
||||
"No recipe found :(")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.recipeRoutes() {
|
||||
routing {
|
||||
getAllRecipes()
|
||||
getRecipe()
|
||||
createRecipe()
|
||||
updateRecipe()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
99
src/main/kotlin/com/wyattjmiller/routes/UserRoute.kt
Normal file
99
src/main/kotlin/com/wyattjmiller/routes/UserRoute.kt
Normal file
@ -0,0 +1,99 @@
|
||||
package com.wyattjmiller.routes
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.wyattjmiller.auth.JwtConfig
|
||||
import com.wyattjmiller.entities.UserDraft
|
||||
import com.wyattjmiller.entities.UserLogin
|
||||
import com.wyattjmiller.repositories.UserDao
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.config.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
class UserRoute {
|
||||
companion object {
|
||||
private val user = UserDao()
|
||||
private val tokenManager = JwtConfig(HoconApplicationConfig(ConfigFactory.load()))
|
||||
|
||||
private fun Route.login() {
|
||||
post("/login") {
|
||||
val userCreds = call.receive<UserLogin>()
|
||||
val usernameResult = user.usernameCheck(userCreds)
|
||||
val passwordResult = user.passwordCheck(userCreds)
|
||||
|
||||
if (usernameResult == null || passwordResult == null) {
|
||||
call.respond(HttpStatusCode.BadRequest)
|
||||
}
|
||||
|
||||
//if (!BCrypt.checkpw(password, res?.password)) {
|
||||
// call.respond(HttpStatusCode.BadRequest)
|
||||
// return@post
|
||||
//}
|
||||
|
||||
val token = tokenManager.generateJwtToken(userCreds)
|
||||
call.respond(HttpStatusCode.OK, token)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.getAllUsers() {
|
||||
get("/user") {
|
||||
call.respond(user.getAllUsers())
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.getUser() {
|
||||
authenticate {
|
||||
get("/user/{id?}") {
|
||||
val id = call.parameters["id"]?.toInt() ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest, "Missing user identifier :("
|
||||
)
|
||||
|
||||
val res = user.getUser(id) ?: return@get call.respond(
|
||||
HttpStatusCode.NotFound, "No recipe found :("
|
||||
)
|
||||
|
||||
call.respond(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.createUser() {
|
||||
post("/user") {
|
||||
val req = call.receive<UserDraft>()
|
||||
val res = user.createUser(req)
|
||||
call.respond(res)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.updateUser() {
|
||||
authenticate {
|
||||
put("/user/{id?}") {
|
||||
val req = call.receive<UserDraft>()
|
||||
val id = call.parameters["id"]?.toIntOrNull() ?: return@put call.respond(
|
||||
HttpStatusCode.BadRequest, "Missing author identifier :("
|
||||
)
|
||||
|
||||
if (user.updateUser(id, req)) {
|
||||
call.respond(HttpStatusCode.Accepted)
|
||||
} else {
|
||||
call.respond(
|
||||
HttpStatusCode.NotFound, "No author found :("
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.userRoutes() {
|
||||
routing {
|
||||
login()
|
||||
getUser()
|
||||
createUser()
|
||||
updateUser()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,3 +17,8 @@ storage {
|
||||
dbUser = "wyatt"
|
||||
dbPasswd = "wjm"
|
||||
}
|
||||
|
||||
secret = "!$#terces!$#"
|
||||
issuer = "http://0.0.0.0:8080/"
|
||||
audience = "http://0.0.0.0:8080/hello"
|
||||
realm = "Access to 'hello'"
|
||||
|
25
src/test/kotlin/com/wyattjmiller/author.http
Normal file
25
src/test/kotlin/com/wyattjmiller/author.http
Normal file
@ -0,0 +1,25 @@
|
||||
// Get all authors
|
||||
GET http://localhost:8080/author
|
||||
|
||||
###
|
||||
// Get one author
|
||||
GET http://localhost:8080/author/3
|
||||
|
||||
###
|
||||
// Create author
|
||||
POST http://localhost:8080/author
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"authorName": "Aidan Tiernan",
|
||||
"user": 1
|
||||
}
|
||||
|
||||
###
|
||||
// Create author without a user
|
||||
POST http://localhost:8080/author
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"authorName": "Cayde Alpers"
|
||||
}
|
26
src/test/kotlin/com/wyattjmiller/login.http
Normal file
26
src/test/kotlin/com/wyattjmiller/login.http
Normal file
@ -0,0 +1,26 @@
|
||||
### Valid login
|
||||
POST http://localhost:8080/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "wymiller",
|
||||
"password": "wjm192837465"
|
||||
}
|
||||
|
||||
### Incorrect username
|
||||
POST http://localhost:8080/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "denthead",
|
||||
"password": "wjm192837465"
|
||||
}
|
||||
|
||||
### Incorrect password
|
||||
POST http://localhost:8080/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "wymiller",
|
||||
"password": "averyisgay"
|
||||
}
|
10
src/test/kotlin/com/wyattjmiller/recipe.http
Normal file
10
src/test/kotlin/com/wyattjmiller/recipe.http
Normal file
@ -0,0 +1,10 @@
|
||||
// Get all of the recipes
|
||||
GET http://localhost:8080/recipe
|
||||
|
||||
###
|
||||
// Get one recipe
|
||||
GET http://localhost:8080/recipe/2
|
||||
|
||||
###
|
||||
// ANIME NOOOOOODLE
|
||||
GET http://localhost:8080/recipe/4
|
2
src/test/kotlin/com/wyattjmiller/user.http
Normal file
2
src/test/kotlin/com/wyattjmiller/user.http
Normal file
@ -0,0 +1,2 @@
|
||||
// Get user
|
||||
GET http://localhost:8080/user/1
|
Reference in New Issue
Block a user