Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Commit

Permalink
Restructured web controllers, updated paths, updated Swagger docs, pe…
Browse files Browse the repository at this point in the history
…rmissions
  • Loading branch information
waltkb committed Nov 27, 2023
1 parent 3134725 commit dee7775
Show file tree
Hide file tree
Showing 47 changed files with 167 additions and 119 deletions.
7 changes: 2 additions & 5 deletions src/main/kotlin/id/walt/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package id.walt

import id.walt.config.ConfigManager
import id.walt.db.Db
import id.walt.push.PushController.push
import id.walt.web.Administration.configureAdministration
import id.walt.web.Notifications.notifications
import id.walt.web.auth
import id.walt.web.configureSecurity
import id.walt.web.controllers.*
import id.walt.web.controllers.NotificationController.notifications
import id.walt.web.controllers.PushController.push
import id.walt.web.plugins.*
import io.github.oshai.kotlinlogging.KotlinLogging
import io.ktor.server.application.*
Expand Down Expand Up @@ -66,7 +64,6 @@ fun Application.module() {
keys()
exchange()
history()
wallets()
web3accounts()
accounts()
nfts()
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/id/walt/db/Db.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ object Db {

runBlocking {
AccountsService.register(EmailAccountRequest("Max Mustermann", "[email protected]", "string"))
AccountsService.register(EmailAccountRequest("Max Mustermann", "[email protected]", "password"))
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/main/kotlin/id/walt/db/models/AccountWalletMappings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import kotlinx.uuid.UUID
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp

enum class AccountWalletPermissions {
ADMINISTRATE,
USE,
READ_ONLY
@Serializable
enum class AccountWalletPermissions(val power: Int) {
ADMINISTRATE(9999),
USE(100),
READ_ONLY(10)
}

object AccountWalletMappings : Table("account_wallet_mapping") {
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/id/walt/service/account/AccountsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import id.walt.db.models.*
import id.walt.db.models.todo.AccountIssuers
import id.walt.db.models.todo.Issuers
import id.walt.service.WalletServiceManager
import id.walt.web.generateToken
import id.walt.web.controllers.generateToken
import id.walt.web.model.AccountRequest
import id.walt.web.model.AddressAccountRequest
import id.walt.web.model.EmailAccountRequest
Expand Down Expand Up @@ -34,7 +34,8 @@ object AccountsService {
val walletService = WalletServiceManager.getWalletService(registeredUserId, createdInitialWalletId)

// Add default data:
walletService.createDid("key", mapOf("alias" to JsonPrimitive("Onboarding")))
val createdDid = walletService.createDid("key", mapOf("alias" to JsonPrimitive("Onboarding")))
walletService.setDefault(createdDid)

transaction {
queryDefaultIssuer("walt.id")?.let { defaultIssuer ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package id.walt.service.account

import de.mkammerer.argon2.Argon2Factory
import id.walt.db.models.Accounts
import id.walt.web.ByteLoginRequest
import id.walt.web.controllers.ByteLoginRequest
import id.walt.web.UnauthorizedException
import id.walt.web.model.EmailAccountRequest
import kotlinx.datetime.Clock
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package id.walt.push
package id.walt.service.push

import id.walt.config.ConfigManager
import id.walt.config.PushConfig
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package id.walt.push
package id.walt.service.push

import id.walt.crypto.utils.Base64Utils.base64Decode
import kotlinx.serialization.Serializable
Expand Down
10 changes: 9 additions & 1 deletion src/main/kotlin/id/walt/web/Exceptions.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package id.walt.web

import id.walt.db.models.AccountWalletPermissions
import io.ktor.http.*
import kotlinx.serialization.SerialName

open class WebException(val status: HttpStatusCode, message: String) : Exception(message)
sealed class WebException(val status: HttpStatusCode, message: String) : Exception(message)

class UnauthorizedException(message: String) : WebException(HttpStatusCode.Unauthorized, message)

@SerialName("InsufficientPermissions")
class InsufficientPermissionsException(
minimumRequired: AccountWalletPermissions,
current: AccountWalletPermissions,
) : WebException(HttpStatusCode.Unauthorized, "You do not have enough permissions to access this action. Minimum required permissions: $minimumRequired, your current permissions: $current")
28 changes: 28 additions & 0 deletions src/main/kotlin/id/walt/web/WebBaseRoutes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package id.walt.web

import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.routing.*

object WebBaseRoutes {

private fun Route.routedWebWalletRoute(block: Route.() -> Unit) =
route("wallet-api", {

}) {
block.invoke(this)
}

fun Application.webWalletRoute(block: Route.() -> Unit) = routing {
routedWebWalletRoute(block)
}

fun Application.authenticatedWebWalletRoute(block: Route.() -> Unit) = routing {
authenticate("authenticated-session", "authenticated-bearer") {
routedWebWalletRoute(block)
}
}
}


25 changes: 10 additions & 15 deletions src/main/kotlin/id/walt/web/controllers/AccountController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,25 @@ package id.walt.web.controllers

import id.walt.db.models.AccountWalletListing
import id.walt.service.account.AccountsService
import id.walt.web.getUserUUID
import id.walt.web.WebBaseRoutes.authenticatedWebWalletRoute
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun Application.accounts() {
routing {
authenticate("authenticated-session", "authenticated-bearer") {
route("r/wallet", {
authenticatedWebWalletRoute {
route("wallet") {
route("accounts", {
tags = listOf("Accounts")
}) {
route("accounts", {
tags = listOf("Accounts")
get("wallets", {
summary = "Get wallets associated with account"
response { HttpStatusCode.OK to { body<AccountWalletListing>() } }
}) {
get("wallets", {
summary = "Get wallets associated with account"
response { HttpStatusCode.OK to { body<AccountWalletListing>() } }
}) {
val user = getUserUUID()
context.respond(AccountsService.getAccountWalletMappings(user))
}
val user = getUserUUID()
context.respond(AccountsService.getAccountWalletMappings(user))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package id.walt.web
package id.walt.web.controllers

//import id.walt.web.model.LoginRequestJson
import id.walt.db.models.AccountWalletMappings
import id.walt.db.models.AccountWalletPermissions
import id.walt.service.WalletServiceManager
import id.walt.service.account.AccountsService
import id.walt.utils.RandomUtils
import id.walt.web.InsufficientPermissionsException
import id.walt.web.UnauthorizedException
import id.walt.web.WebBaseRoutes.webWalletRoute
import id.walt.web.model.AccountRequest
import id.walt.web.model.EmailAccountRequest
import id.walt.web.model.LoginRequestJson
Expand All @@ -16,12 +21,15 @@ import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import io.ktor.util.pipeline.*
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlinx.uuid.UUID
import kotlinx.uuid.toJavaUUID
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import kotlin.collections.set
import kotlin.time.Duration.Companion.days

Expand Down Expand Up @@ -93,8 +101,8 @@ val securityUserTokenMapping = HashMap<String, UUID>() // Token -> UUID


fun Application.auth() {
routing {
route("r/auth", {
webWalletRoute {
route("auth", {
tags = listOf("Authentication")
}) {
post("login", {
Expand Down Expand Up @@ -227,3 +235,24 @@ fun PipelineContext<Unit, ApplicationCall>.getUsersSessionToken(): String? =
?.removePrefix("Bearer ")

fun getNftService() = WalletServiceManager.getNftService()

fun PipelineContext<Unit, ApplicationCall>.ensurePermissionsForWallet(required: AccountWalletPermissions): Boolean {
val userId = getUserUUID().toJavaUUID()
val walletId = getWalletId().toJavaUUID()

val permissions = transaction {
(AccountWalletMappings.select { (AccountWalletMappings.account eq userId) and (AccountWalletMappings.wallet eq walletId) }
.firstOrNull()
?: throw UnauthorizedException("This account does not have access to the specified wallet.")
)[AccountWalletMappings.permissions]
}

if (permissions.power >= required.power) {
return true
} else {
throw InsufficientPermissionsException(
minimumRequired = required,
current = permissions
)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package id.walt.web.controllers

import id.walt.db.models.WalletCredential
import id.walt.web.getWalletService
import io.github.smiley4.ktorswaggerui.dsl.delete
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.put
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/id/walt/web/controllers/DidController.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package id.walt.web.controllers

import id.walt.web.DidCreation.didCreate
import id.walt.web.getWalletService
import id.walt.web.controllers.DidCreation.didCreate
import io.github.smiley4.ktorswaggerui.dsl.delete
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.post
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package id.walt.web
package id.walt.web.controllers

import io.github.smiley4.ktorswaggerui.dsl.post
import io.ktor.http.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.json.JsonPrimitive

private const val DidKeyMethodName = "key"
private const val DidJwkMethodName = "jwk"
private const val DidWebMethodName = "web"
private const val DidEbsiMethodName = "ebsi"
private const val DidCheqdMethodName = "cheqd"
private const val DidIotaMethodName = "iota"

object DidCreation {

private const val DidKeyMethodName = "key"
private const val DidJwkMethodName = "jwk"
private const val DidWebMethodName = "web"
private const val DidEbsiMethodName = "ebsi"
private const val DidCheqdMethodName = "cheqd"
private const val DidIotaMethodName = "iota"

fun Route.didCreate() {
post(DidKeyMethodName, {
summary = "Create a did:key"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package id.walt.web.controllers
import id.walt.db.models.WalletOperationHistory
import id.walt.oid4vc.data.dif.PresentationDefinition
import id.walt.service.SSIKit2WalletService
import id.walt.web.getWalletService
import io.github.smiley4.ktorswaggerui.dsl.post
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.http.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package id.walt.web.controllers

import id.walt.web.getWalletService
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.server.application.*
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/id/walt/web/controllers/IssuersController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import id.walt.service.issuers.CredentialDataTransferObject
import id.walt.service.issuers.IssuerCredentialsDataTransferObject
import id.walt.service.issuers.IssuerDataTransferObject
import id.walt.service.issuers.IssuersService
import id.walt.web.getWalletService
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.http.*
Expand Down Expand Up @@ -96,4 +95,4 @@ fun Application.issuers() = walletRoute {
}
}
}
}
}
1 change: 0 additions & 1 deletion src/main/kotlin/id/walt/web/controllers/KeyController.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package id.walt.web.controllers

import id.walt.crypto.keys.KeyType
import id.walt.web.getWalletService
import io.github.smiley4.ktorswaggerui.dsl.delete
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.post
Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/id/walt/web/controllers/NftController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package id.walt.web.controllers

import id.walt.service.dto.*
import id.walt.service.nft.fetchers.parameters.*
import id.walt.web.getNftService
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.http.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package id.walt.web
package id.walt.web.controllers

import id.walt.push.PushManager
import id.walt.service.push.PushManager
import io.github.smiley4.ktorswaggerui.dsl.post
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.http.*
Expand All @@ -17,7 +17,7 @@ import java.net.URLDecoder
import java.nio.charset.StandardCharsets


object Notifications {
object NotificationController {

/*
fun splitQuery(url: URI): Map<String?, List<String?>?> {
Expand All @@ -39,7 +39,7 @@ object Notifications {
fun Application.notifications() {
routing {
route("/api/notifications", {
tags = listOf("Notifications")
tags = listOf("NotificationController")
}) {
post("send", {
summary = "Experimental: Push notification system"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package id.walt.push
package id.walt.web.controllers

import id.walt.service.push.PushManager
import id.walt.service.push.Subscription
import id.walt.web.WebBaseRoutes.webWalletRoute
import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.post
import io.github.smiley4.ktorswaggerui.dsl.route
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

object PushController {

fun Application.push() {
routing {
route("r/push", {
tags = listOf("Notifications / Push controlling")
webWalletRoute { // todo: unauthenticated
route("push", {
tags = listOf("NotificationController / Push controlling")
}) {
post("subscription", {
summary = "Subscribe to push notifications [Experimental: Push notification system]"
Expand Down
Loading

0 comments on commit dee7775

Please sign in to comment.