even better ktor server integration
This commit is contained in:
parent
5cd4f00b1d
commit
652950633f
@ -14,6 +14,12 @@ It also contains useful tools for this type of application:
|
|||||||
|
|
||||||
- `AccessControlObject` to contain recoverable password-protected data with a backup `secret` word to restore access.
|
- `AccessControlObject` to contain recoverable password-protected data with a backup `secret` word to restore access.
|
||||||
|
|
||||||
Will be published under MIT when become usable.
|
## Usage
|
||||||
|
|
||||||
|
Currently, complie it and publisj into mavenLocal, and use from there. Soon will be published to some public maven repo.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Will be published under MIT as soon as first RC will be published.
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,11 @@ kotlin {
|
|||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val jvmMain by getting
|
val jvmMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation("io.ktor:ktor-server-core:$ktor_version")
|
||||||
|
}
|
||||||
|
}
|
||||||
val jvmTest by getting {
|
val jvmTest by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-server-core:$ktor_version")
|
implementation("io.ktor:ktor-server-core:$ktor_version")
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package net.sergeych.superlogin.server
|
package net.sergeych.superlogin.server
|
||||||
|
|
||||||
|
import io.ktor.server.application.*
|
||||||
import net.sergeych.parsec3.AdapterBuilder
|
import net.sergeych.parsec3.AdapterBuilder
|
||||||
import net.sergeych.parsec3.CommandHost
|
import net.sergeych.parsec3.CommandHost
|
||||||
import net.sergeych.parsec3.WithAdapter
|
import net.sergeych.parsec3.WithAdapter
|
||||||
|
import net.sergeych.parsec3.parsec3TransportServer
|
||||||
import net.sergeych.superlogin.*
|
import net.sergeych.superlogin.*
|
||||||
import net.sergeych.unikrypto.SignedRecord
|
import net.sergeych.unikrypto.SignedRecord
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -12,9 +14,61 @@ fun randomACOLike(): ByteArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a superlogin server on a curretn adapter builder, using some session builder lambda.
|
* Create superlogin server using default parsec 3 server transport providing session creation
|
||||||
|
* lambda and a block to set up server-specific api. The session must inherit [SLServerSession]
|
||||||
|
* with application-specific data, and implement all of its abstract methods at list (also it
|
||||||
|
* might need t override some default methods, see docs. For example:
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* // Application-specific API declaration
|
||||||
|
* class TestApiServer<T : WithAdapter> : CommandHost<T>() {
|
||||||
|
* val foobar by command<Unit, String?>()
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // application data to be included in the "user" data transfered to and from the client:
|
||||||
|
* data class TestData(clientData: String)
|
||||||
|
*
|
||||||
|
* // session state, is kept until the user connection (e.g. session) is closed, in the RAM:
|
||||||
|
* class TestSession(var sessionData: String) : SLServerSession<TestData>()
|
||||||
|
*
|
||||||
|
* // Create a server in a ktor context:
|
||||||
|
* fun Application.serverModule() {
|
||||||
|
* SuperloginServer(TestApiServer<TestSession>(), { TestSession("foobar") }) {
|
||||||
|
* // application API implementation
|
||||||
|
* on(api.foobar) {
|
||||||
|
* "Session data: ${sessionData}, loginName: $currentLoginName user data: $superloginData"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* @param api service specific API declaration (usually in the shared code)
|
||||||
|
* @param sessionBuilder function that creates new session. Session is created on every incoming
|
||||||
|
* connection so try not to do any time and resource consuming operations there
|
||||||
|
* @param adapterBuilder block that should implement service-specific api.
|
||||||
|
* @param D application specific data (included in the session and transferred with registration
|
||||||
|
* and login)
|
||||||
|
* @param T service-specific session, class implementing any session-based code specific to the
|
||||||
|
* application but also implement necessary `superlogin` methods (implementing abstract
|
||||||
|
* ones) that implement user login data persistence and search.
|
||||||
|
*/
|
||||||
|
inline fun <reified D, T : SLServerSession<D>,> Application.SuperloginServer(
|
||||||
|
api: CommandHost<T>,
|
||||||
|
crossinline sessionBuilder: suspend AdapterBuilder<T, CommandHost<T>>.()->T,
|
||||||
|
crossinline adapterBuilder: AdapterBuilder<T, CommandHost<T>>.()->Unit
|
||||||
|
) {
|
||||||
|
parsec3TransportServer(api) {
|
||||||
|
setupSuperloginServer { sessionBuilder() }
|
||||||
|
adapterBuilder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a superlogin server manually, on a current adapter builder, using some session builder lambda.
|
||||||
* Note that session must inherit [SLServerSession] and implement necessary abstract methods
|
* Note that session must inherit [SLServerSession] and implement necessary abstract methods
|
||||||
* that do store and retrieve user data. It sould be used like:
|
* that do store and retrieve user data. Usually you can do it easier with [SuperloginServer] call.
|
||||||
|
* If you want to do it manually (fr example using a custom transport), do it like this:
|
||||||
* ```
|
* ```
|
||||||
* parsec3TransportServer(TestApiServer<TestSession>()) {
|
* parsec3TransportServer(TestApiServer<TestSession>()) {
|
||||||
* // the session extends SLServerSession and contain app-specific data and
|
* // the session extends SLServerSession and contain app-specific data and
|
||||||
@ -31,8 +85,8 @@ fun randomACOLike(): ByteArray {
|
|||||||
*
|
*
|
||||||
* @param sessionBuilder code that builds a new session over the adapter.
|
* @param sessionBuilder code that builds a new session over the adapter.
|
||||||
*/
|
*/
|
||||||
inline fun <reified D, T : SLServerSession<D>, H : CommandHost<T>> AdapterBuilder<T, H>.superloginServer(
|
inline fun <reified D, T : SLServerSession<D>, H : CommandHost<T>> AdapterBuilder<T, H>.setupSuperloginServer(
|
||||||
crossinline sessionBuilder: suspend AdapterBuilder<T,H>.()->T
|
crossinline sessionBuilder: suspend AdapterBuilder<T, H>.() -> T,
|
||||||
) {
|
) {
|
||||||
newSession { sessionBuilder() }
|
newSession { sessionBuilder() }
|
||||||
addErrors(SuperloginExceptionsRegistry)
|
addErrors(SuperloginExceptionsRegistry)
|
||||||
|
@ -5,16 +5,13 @@ import io.ktor.server.engine.*
|
|||||||
import io.ktor.server.netty.*
|
import io.ktor.server.netty.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import net.sergeych.parsec3.CommandHost
|
import net.sergeych.parsec3.*
|
||||||
import net.sergeych.parsec3.Parsec3WSClient
|
|
||||||
import net.sergeych.parsec3.WithAdapter
|
|
||||||
import net.sergeych.parsec3.parsec3TransportServer
|
|
||||||
import net.sergeych.superlogin.*
|
import net.sergeych.superlogin.*
|
||||||
import net.sergeych.superlogin.client.LoginState
|
import net.sergeych.superlogin.client.LoginState
|
||||||
import net.sergeych.superlogin.client.Registration
|
import net.sergeych.superlogin.client.Registration
|
||||||
import net.sergeych.superlogin.client.SuperloginClient
|
import net.sergeych.superlogin.client.SuperloginClient
|
||||||
import net.sergeych.superlogin.server.SLServerSession
|
import net.sergeych.superlogin.server.SLServerSession
|
||||||
import net.sergeych.superlogin.server.superloginServer
|
import net.sergeych.superlogin.server.setupSuperloginServer
|
||||||
import net.sergeych.unikrypto.PublicKey
|
import net.sergeych.unikrypto.PublicKey
|
||||||
import superlogin.assertThrowsAsync
|
import superlogin.assertThrowsAsync
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -193,6 +190,7 @@ internal class WsServerKtTest {
|
|||||||
assertTrue { slc.isLoggedIn }
|
assertTrue { slc.isLoggedIn }
|
||||||
assertEquals("foo", slc.call(api.loginName))
|
assertEquals("foo", slc.call(api.loginName))
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,10 +210,19 @@ internal class WsServerKtTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified D, T : SLServerSession<D>, H : CommandHost<T>> Application.SuperloginServer(
|
||||||
|
api: H,
|
||||||
|
crossinline sessionBuilder: suspend AdapterBuilder<T, H>.()->T,
|
||||||
|
crossinline adapterBuilder: AdapterBuilder<T, H>.()->Unit
|
||||||
|
) {
|
||||||
|
parsec3TransportServer(api) {
|
||||||
|
setupSuperloginServer { sessionBuilder() }
|
||||||
|
adapterBuilder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Application.testServerModule() {
|
fun Application.testServerModule() {
|
||||||
parsec3TransportServer(TestApiServer<TestSession>()) {
|
SuperloginServer(TestApiServer<TestSession>(), { TestSession() }) {
|
||||||
// superloginServer(TestServerTraits,TestApiServer<SLServerSession<TestData>>()) {
|
|
||||||
superloginServer { TestSession() }
|
|
||||||
on(api.loginName) {
|
on(api.loginName) {
|
||||||
println("login name called. now we have $currentLoginName : $superloginData")
|
println("login name called. now we have $currentLoginName : $superloginData")
|
||||||
currentLoginName
|
currentLoginName
|
||||||
|
Loading…
Reference in New Issue
Block a user