Link Search Menu Expand Document

Custom routes

KDone lets to add custom routes, giving developers some helper function to interact easily with KDone structure, such as authentication or database.

Adding custom routes

The most simple thing that can be done is add a route with a custom code. KDone is on top of Ktor, so routes are implemented using Ktor DSL. They can be added inside module closure or outside it, inside startKDone closure.

startKDone(
        port = 23146
        mongoURL = "mongodb://localhost:27017/games",
        databaseName = "games",
        jwtConfig = JWTConfig(JWT.secret)) {
  
          get("ciao") {
            call.respond(HttpStatusCode.OK, mapOf("response" to "Ciao!")
          }
                           
          module<Game>("games") {
            ...
  
            get("hello") {
              call.respond(HttpStatus.OK, mapOf("response" to "Hello!")
            }
          }
        }

Using authentication

Custom routes can be authenticated using authenticateJWT function. Inside that the authenticated data of a user can be retrieved with userAuth function.

authenticateJWT {
  get("user/games") {
    val userAuth = call.userAuth.userId
    call.respond(HttpStatusCode.OK, mapOf("response" to userAuth)
  }

Authentication could be optional.

authenticateJWT(optional = true) {
  get("user/games") {
    val userAuth = call.userAuthOrNull.userId
    call.respond(HttpStatusCode.OK, mapOf("response" to userAuth)
  }
}

Using repositories

In order to access the database, KDone offers a couple of ways to use repositories connected to MongoDB.
Each model has a repository that lets to access MongoDB query on its collection, through KMongo API. To access the repository in module closure, just use repository instance available in configuration closure.

module<Game>("games") {
  get("user/games") {
    val result = repository.findAll() // Games list
    call.respond(HttpStatusCode.OK, mapOf("games" to result))
  }
}

To access the repository outside module closure, KDone has a Route extension that can be used inside startKDone function or inside every Ktor routing.

startKDone(
        port = 23146
        mongoURL = "mongodb://localhost:27017/games",
        databaseName = "games",
        jwtConfig = JWTConfig(JWT.secret)) {
  val gamesRepository = mongoRepository<Game>("games")
  
  get("user/games") {
    val result = gamesRepository.findAll() // Games list
    call.respond(HttpStatusCode.OK, mapOf("games" to result))
  }
}
routing {
  val gamesRepository = mongoRepository<Game>("games")
  
  get("user/games") {
    val result = gamesRepository.findAll() // Games list
    call.respond(HttpStatusCode.OK, mapOf("games" to result))
  }
}

Converting data

In KDone, models represent the documents saved in MongoDB. It can be useful to convert them easily into another model to deal with permission or different views.
KDone has the transfer function, that can turn a model into another.
Let’s take a User model.

data class User(override var username: String,
                val name: String,
                val surname: String,
                val nickname: String,
                val image: ResourceFile?,
                val active: Boolean?,
                val score: Double?,
                val gameId: Id<Game>?,
                val date: Date?,
                val location: GeoLocation?) : KDoneUser(

Then a public version of it.

data class PublicUser(val username: String,
                val name: String,
                val surname: String,
                val nickname: String,
                val image: ResourceFile?)

Using transfer function it’s possible to convert the first into the second.

val user = usersRepository.findAll().first()

// New model created manually
val publicUser = user.transfer<User, PublicUser> {
        _, currentUser ->
                PublicUser(currentUser.username,
                        currentUser.name,
                        currentUser.surname,
                        currentUser.nickname,
                        currentUser.image)
      }

// New model created automatically, resolving attributes with the same names
val publicUser: PublicUser = user.transfer()

Copyright © 2021 Dario Pellegrini