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

Commit dee7775

Browse files
committed
Restructured web controllers, updated paths, updated Swagger docs, permissions
1 parent 3134725 commit dee7775

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+167
-119
lines changed

src/main/kotlin/id/walt/Application.kt

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ package id.walt
22

33
import id.walt.config.ConfigManager
44
import id.walt.db.Db
5-
import id.walt.push.PushController.push
65
import id.walt.web.Administration.configureAdministration
7-
import id.walt.web.Notifications.notifications
8-
import id.walt.web.auth
9-
import id.walt.web.configureSecurity
106
import id.walt.web.controllers.*
7+
import id.walt.web.controllers.NotificationController.notifications
8+
import id.walt.web.controllers.PushController.push
119
import id.walt.web.plugins.*
1210
import io.github.oshai.kotlinlogging.KotlinLogging
1311
import io.ktor.server.application.*
@@ -66,7 +64,6 @@ fun Application.module() {
6664
keys()
6765
exchange()
6866
history()
69-
wallets()
7067
web3accounts()
7168
accounts()
7269
nfts()

src/main/kotlin/id/walt/db/Db.kt

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ object Db {
7676

7777
runBlocking {
7878
AccountsService.register(EmailAccountRequest("Max Mustermann", "[email protected]", "string"))
79+
AccountsService.register(EmailAccountRequest("Max Mustermann", "[email protected]", "password"))
7980
}
8081
}
8182

src/main/kotlin/id/walt/db/models/AccountWalletMappings.kt

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import kotlinx.uuid.UUID
66
import org.jetbrains.exposed.sql.Table
77
import org.jetbrains.exposed.sql.javatime.timestamp
88

9-
enum class AccountWalletPermissions {
10-
ADMINISTRATE,
11-
USE,
12-
READ_ONLY
9+
@Serializable
10+
enum class AccountWalletPermissions(val power: Int) {
11+
ADMINISTRATE(9999),
12+
USE(100),
13+
READ_ONLY(10)
1314
}
1415

1516
object AccountWalletMappings : Table("account_wallet_mapping") {

src/main/kotlin/id/walt/service/account/AccountsService.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import id.walt.db.models.*
44
import id.walt.db.models.todo.AccountIssuers
55
import id.walt.db.models.todo.Issuers
66
import id.walt.service.WalletServiceManager
7-
import id.walt.web.generateToken
7+
import id.walt.web.controllers.generateToken
88
import id.walt.web.model.AccountRequest
99
import id.walt.web.model.AddressAccountRequest
1010
import id.walt.web.model.EmailAccountRequest
@@ -34,7 +34,8 @@ object AccountsService {
3434
val walletService = WalletServiceManager.getWalletService(registeredUserId, createdInitialWalletId)
3535

3636
// Add default data:
37-
walletService.createDid("key", mapOf("alias" to JsonPrimitive("Onboarding")))
37+
val createdDid = walletService.createDid("key", mapOf("alias" to JsonPrimitive("Onboarding")))
38+
walletService.setDefault(createdDid)
3839

3940
transaction {
4041
queryDefaultIssuer("walt.id")?.let { defaultIssuer ->

src/main/kotlin/id/walt/service/account/EmailAccountStrategy.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package id.walt.service.account
22

33
import de.mkammerer.argon2.Argon2Factory
44
import id.walt.db.models.Accounts
5-
import id.walt.web.ByteLoginRequest
5+
import id.walt.web.controllers.ByteLoginRequest
66
import id.walt.web.UnauthorizedException
77
import id.walt.web.model.EmailAccountRequest
88
import kotlinx.datetime.Clock

src/main/kotlin/id/walt/push/PushManager.kt src/main/kotlin/id/walt/service/push/PushManager.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package id.walt.push
1+
package id.walt.service.push
22

33
import id.walt.config.ConfigManager
44
import id.walt.config.PushConfig

src/main/kotlin/id/walt/push/Subscription.kt src/main/kotlin/id/walt/service/push/Subscription.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package id.walt.push
1+
package id.walt.service.push
22

33
import id.walt.crypto.utils.Base64Utils.base64Decode
44
import kotlinx.serialization.Serializable
+9-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
package id.walt.web
22

3+
import id.walt.db.models.AccountWalletPermissions
34
import io.ktor.http.*
5+
import kotlinx.serialization.SerialName
46

5-
open class WebException(val status: HttpStatusCode, message: String) : Exception(message)
7+
sealed class WebException(val status: HttpStatusCode, message: String) : Exception(message)
68

79
class UnauthorizedException(message: String) : WebException(HttpStatusCode.Unauthorized, message)
10+
11+
@SerialName("InsufficientPermissions")
12+
class InsufficientPermissionsException(
13+
minimumRequired: AccountWalletPermissions,
14+
current: AccountWalletPermissions,
15+
) : WebException(HttpStatusCode.Unauthorized, "You do not have enough permissions to access this action. Minimum required permissions: $minimumRequired, your current permissions: $current")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package id.walt.web
2+
3+
import io.github.smiley4.ktorswaggerui.dsl.route
4+
import io.ktor.server.application.*
5+
import io.ktor.server.auth.*
6+
import io.ktor.server.routing.*
7+
8+
object WebBaseRoutes {
9+
10+
private fun Route.routedWebWalletRoute(block: Route.() -> Unit) =
11+
route("wallet-api", {
12+
13+
}) {
14+
block.invoke(this)
15+
}
16+
17+
fun Application.webWalletRoute(block: Route.() -> Unit) = routing {
18+
routedWebWalletRoute(block)
19+
}
20+
21+
fun Application.authenticatedWebWalletRoute(block: Route.() -> Unit) = routing {
22+
authenticate("authenticated-session", "authenticated-bearer") {
23+
routedWebWalletRoute(block)
24+
}
25+
}
26+
}
27+
28+

src/main/kotlin/id/walt/web/controllers/AccountController.kt

+10-15
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,25 @@ package id.walt.web.controllers
22

33
import id.walt.db.models.AccountWalletListing
44
import id.walt.service.account.AccountsService
5-
import id.walt.web.getUserUUID
5+
import id.walt.web.WebBaseRoutes.authenticatedWebWalletRoute
66
import io.github.smiley4.ktorswaggerui.dsl.get
77
import io.github.smiley4.ktorswaggerui.dsl.route
88
import io.ktor.http.*
99
import io.ktor.server.application.*
10-
import io.ktor.server.auth.*
1110
import io.ktor.server.response.*
12-
import io.ktor.server.routing.*
1311

1412
fun Application.accounts() {
15-
routing {
16-
authenticate("authenticated-session", "authenticated-bearer") {
17-
route("r/wallet", {
13+
authenticatedWebWalletRoute {
14+
route("wallet") {
15+
route("accounts", {
16+
tags = listOf("Accounts")
1817
}) {
19-
route("accounts", {
20-
tags = listOf("Accounts")
18+
get("wallets", {
19+
summary = "Get wallets associated with account"
20+
response { HttpStatusCode.OK to { body<AccountWalletListing>() } }
2121
}) {
22-
get("wallets", {
23-
summary = "Get wallets associated with account"
24-
response { HttpStatusCode.OK to { body<AccountWalletListing>() } }
25-
}) {
26-
val user = getUserUUID()
27-
context.respond(AccountsService.getAccountWalletMappings(user))
28-
}
22+
val user = getUserUUID()
23+
context.respond(AccountsService.getAccountWalletMappings(user))
2924
}
3025
}
3126
}

src/main/kotlin/id/walt/web/AccountManagement.kt src/main/kotlin/id/walt/web/controllers/AuthController.kt

+33-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
package id.walt.web
1+
package id.walt.web.controllers
22

33
//import id.walt.web.model.LoginRequestJson
4+
import id.walt.db.models.AccountWalletMappings
5+
import id.walt.db.models.AccountWalletPermissions
46
import id.walt.service.WalletServiceManager
57
import id.walt.service.account.AccountsService
68
import id.walt.utils.RandomUtils
9+
import id.walt.web.InsufficientPermissionsException
10+
import id.walt.web.UnauthorizedException
11+
import id.walt.web.WebBaseRoutes.webWalletRoute
712
import id.walt.web.model.AccountRequest
813
import id.walt.web.model.EmailAccountRequest
914
import id.walt.web.model.LoginRequestJson
@@ -16,12 +21,15 @@ import io.ktor.server.application.*
1621
import io.ktor.server.auth.*
1722
import io.ktor.server.request.*
1823
import io.ktor.server.response.*
19-
import io.ktor.server.routing.*
2024
import io.ktor.server.sessions.*
2125
import io.ktor.util.pipeline.*
2226
import kotlinx.serialization.json.JsonPrimitive
2327
import kotlinx.serialization.json.buildJsonObject
2428
import kotlinx.uuid.UUID
29+
import kotlinx.uuid.toJavaUUID
30+
import org.jetbrains.exposed.sql.and
31+
import org.jetbrains.exposed.sql.select
32+
import org.jetbrains.exposed.sql.transactions.transaction
2533
import kotlin.collections.set
2634
import kotlin.time.Duration.Companion.days
2735

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

94102

95103
fun Application.auth() {
96-
routing {
97-
route("r/auth", {
104+
webWalletRoute {
105+
route("auth", {
98106
tags = listOf("Authentication")
99107
}) {
100108
post("login", {
@@ -227,3 +235,24 @@ fun PipelineContext<Unit, ApplicationCall>.getUsersSessionToken(): String? =
227235
?.removePrefix("Bearer ")
228236

229237
fun getNftService() = WalletServiceManager.getNftService()
238+
239+
fun PipelineContext<Unit, ApplicationCall>.ensurePermissionsForWallet(required: AccountWalletPermissions): Boolean {
240+
val userId = getUserUUID().toJavaUUID()
241+
val walletId = getWalletId().toJavaUUID()
242+
243+
val permissions = transaction {
244+
(AccountWalletMappings.select { (AccountWalletMappings.account eq userId) and (AccountWalletMappings.wallet eq walletId) }
245+
.firstOrNull()
246+
?: throw UnauthorizedException("This account does not have access to the specified wallet.")
247+
)[AccountWalletMappings.permissions]
248+
}
249+
250+
if (permissions.power >= required.power) {
251+
return true
252+
} else {
253+
throw InsufficientPermissionsException(
254+
minimumRequired = required,
255+
current = permissions
256+
)
257+
}
258+
}

src/main/kotlin/id/walt/web/controllers/CredentialController.kt

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package id.walt.web.controllers
22

33
import id.walt.db.models.WalletCredential
4-
import id.walt.web.getWalletService
54
import io.github.smiley4.ktorswaggerui.dsl.delete
65
import io.github.smiley4.ktorswaggerui.dsl.get
76
import io.github.smiley4.ktorswaggerui.dsl.put

src/main/kotlin/id/walt/web/controllers/DidController.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package id.walt.web.controllers
22

3-
import id.walt.web.DidCreation.didCreate
4-
import id.walt.web.getWalletService
3+
import id.walt.web.controllers.DidCreation.didCreate
54
import io.github.smiley4.ktorswaggerui.dsl.delete
65
import io.github.smiley4.ktorswaggerui.dsl.get
76
import io.github.smiley4.ktorswaggerui.dsl.post

src/main/kotlin/id/walt/web/DidCreation.kt src/main/kotlin/id/walt/web/controllers/DidCreation.kt

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
package id.walt.web
1+
package id.walt.web.controllers
22

33
import io.github.smiley4.ktorswaggerui.dsl.post
44
import io.ktor.http.*
55
import io.ktor.server.response.*
66
import io.ktor.server.routing.*
77
import kotlinx.serialization.json.JsonPrimitive
88

9-
private const val DidKeyMethodName = "key"
10-
private const val DidJwkMethodName = "jwk"
11-
private const val DidWebMethodName = "web"
12-
private const val DidEbsiMethodName = "ebsi"
13-
private const val DidCheqdMethodName = "cheqd"
14-
private const val DidIotaMethodName = "iota"
15-
169
object DidCreation {
1710

11+
private const val DidKeyMethodName = "key"
12+
private const val DidJwkMethodName = "jwk"
13+
private const val DidWebMethodName = "web"
14+
private const val DidEbsiMethodName = "ebsi"
15+
private const val DidCheqdMethodName = "cheqd"
16+
private const val DidIotaMethodName = "iota"
17+
1818
fun Route.didCreate() {
1919
post(DidKeyMethodName, {
2020
summary = "Create a did:key"

src/main/kotlin/id/walt/web/controllers/ExchangeController.kt

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package id.walt.web.controllers
33
import id.walt.db.models.WalletOperationHistory
44
import id.walt.oid4vc.data.dif.PresentationDefinition
55
import id.walt.service.SSIKit2WalletService
6-
import id.walt.web.getWalletService
76
import io.github.smiley4.ktorswaggerui.dsl.post
87
import io.github.smiley4.ktorswaggerui.dsl.route
98
import io.ktor.http.*

src/main/kotlin/id/walt/web/controllers/HistoryController.kt

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package id.walt.web.controllers
22

3-
import id.walt.web.getWalletService
43
import io.github.smiley4.ktorswaggerui.dsl.get
54
import io.github.smiley4.ktorswaggerui.dsl.route
65
import io.ktor.server.application.*

src/main/kotlin/id/walt/web/controllers/IssuersController.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import id.walt.service.issuers.CredentialDataTransferObject
44
import id.walt.service.issuers.IssuerCredentialsDataTransferObject
55
import id.walt.service.issuers.IssuerDataTransferObject
66
import id.walt.service.issuers.IssuersService
7-
import id.walt.web.getWalletService
87
import io.github.smiley4.ktorswaggerui.dsl.get
98
import io.github.smiley4.ktorswaggerui.dsl.route
109
import io.ktor.http.*
@@ -96,4 +95,4 @@ fun Application.issuers() = walletRoute {
9695
}
9796
}
9897
}
99-
}
98+
}

src/main/kotlin/id/walt/web/controllers/KeyController.kt

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package id.walt.web.controllers
22

33
import id.walt.crypto.keys.KeyType
4-
import id.walt.web.getWalletService
54
import io.github.smiley4.ktorswaggerui.dsl.delete
65
import io.github.smiley4.ktorswaggerui.dsl.get
76
import io.github.smiley4.ktorswaggerui.dsl.post

src/main/kotlin/id/walt/web/controllers/NftController.kt

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package id.walt.web.controllers
22

33
import id.walt.service.dto.*
44
import id.walt.service.nft.fetchers.parameters.*
5-
import id.walt.web.getNftService
65
import io.github.smiley4.ktorswaggerui.dsl.get
76
import io.github.smiley4.ktorswaggerui.dsl.route
87
import io.ktor.http.*

src/main/kotlin/id/walt/web/Notifications.kt src/main/kotlin/id/walt/web/controllers/NotificationController.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package id.walt.web
1+
package id.walt.web.controllers
22

3-
import id.walt.push.PushManager
3+
import id.walt.service.push.PushManager
44
import io.github.smiley4.ktorswaggerui.dsl.post
55
import io.github.smiley4.ktorswaggerui.dsl.route
66
import io.ktor.http.*
@@ -17,7 +17,7 @@ import java.net.URLDecoder
1717
import java.nio.charset.StandardCharsets
1818

1919

20-
object Notifications {
20+
object NotificationController {
2121

2222
/*
2323
fun splitQuery(url: URI): Map<String?, List<String?>?> {
@@ -39,7 +39,7 @@ object Notifications {
3939
fun Application.notifications() {
4040
routing {
4141
route("/api/notifications", {
42-
tags = listOf("Notifications")
42+
tags = listOf("NotificationController")
4343
}) {
4444
post("send", {
4545
summary = "Experimental: Push notification system"

src/main/kotlin/id/walt/push/PushController.kt src/main/kotlin/id/walt/web/controllers/PushController.kt

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
package id.walt.push
1+
package id.walt.web.controllers
22

3+
import id.walt.service.push.PushManager
4+
import id.walt.service.push.Subscription
5+
import id.walt.web.WebBaseRoutes.webWalletRoute
36
import io.github.smiley4.ktorswaggerui.dsl.get
47
import io.github.smiley4.ktorswaggerui.dsl.post
58
import io.github.smiley4.ktorswaggerui.dsl.route
69
import io.ktor.http.*
710
import io.ktor.server.application.*
811
import io.ktor.server.request.*
912
import io.ktor.server.response.*
10-
import io.ktor.server.routing.*
1113

1214
object PushController {
1315

1416
fun Application.push() {
15-
routing {
16-
route("r/push", {
17-
tags = listOf("Notifications / Push controlling")
17+
webWalletRoute { // todo: unauthenticated
18+
route("push", {
19+
tags = listOf("NotificationController / Push controlling")
1820
}) {
1921
post("subscription", {
2022
summary = "Subscribe to push notifications [Experimental: Push notification system]"

0 commit comments

Comments
 (0)