+login by token and server library improvements
This commit is contained in:
parent
5df6709983
commit
449de2e504
@ -44,7 +44,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3")
|
||||
api("net.sergeych:unikrypto:1.2.1-SNAPSHOT")
|
||||
api("net.sergeych:parsec3:0.3.1-SNAPSHOT")
|
||||
api("net.sergeych:parsec3:0.3.2-SNAPSHOT")
|
||||
api("net.sergeych:boss-serialization-mp:0.2.4-SNAPSHOT")
|
||||
3 }
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class SuperloginClient<D, S : WithAdapter>(
|
||||
adapterReady = CompletableDeferred()
|
||||
}
|
||||
globalLaunch {
|
||||
transport.adapter().invokeCommand(api.slLogout)
|
||||
transport.adapter().invokeCommand(serverApi.slLogout)
|
||||
adapterReady.complete(Unit)
|
||||
}
|
||||
} else {
|
||||
@ -102,12 +102,12 @@ class SuperloginClient<D, S : WithAdapter>(
|
||||
|
||||
private var jobs = listOf<Job>()
|
||||
|
||||
private val api = SuperloginServerApi<WithAdapter>()
|
||||
private val serverApi = SuperloginServerApi<WithAdapter>()
|
||||
|
||||
private suspend fun tryRestoreLogin() {
|
||||
slData?.loginToken?.let { token ->
|
||||
try {
|
||||
val ar = transport.adapter().invokeCommand(api.slLoginByToken, token)
|
||||
val ar = transport.adapter().invokeCommand(serverApi.slLoginByToken, token)
|
||||
slData = if (ar is AuthenticationResult.Success) {
|
||||
val data: D? = ar.applicationData?.let { BossDecoder.decodeFrom(dataType, it) }
|
||||
SuperloginData(ar.loginToken, data)
|
||||
@ -170,11 +170,14 @@ class SuperloginClient<D, S : WithAdapter>(
|
||||
return rn.registerWithData(loginName, password, extraData = BossEncoder.encode(dataType, data))
|
||||
.also { rr ->
|
||||
if (rr is Registration.Result.Success) {
|
||||
slData = SuperloginData(rr.loginToken, rr.encodedData?.let { BossDecoder.decodeFrom(dataType, it) })
|
||||
slData = SuperloginData(rr.loginToken, extractData(rr.encodedData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractData(rr: ByteArray?): D?
|
||||
= rr?.let { BossDecoder.decodeFrom(dataType, it) }
|
||||
|
||||
private fun mustBeLoggedOut() {
|
||||
if (isLoggedIn)
|
||||
throw IllegalStateException("please log out first")
|
||||
@ -190,14 +193,24 @@ class SuperloginClient<D, S : WithAdapter>(
|
||||
slData = null
|
||||
}
|
||||
|
||||
suspend fun LoginByToken(token: ByteArray): SuperloginData<D> {
|
||||
/**
|
||||
* Try to log in by specified token, returned by [Registration.Result.Success.loginToken] or
|
||||
* [SuperloginData.loginToken] respectively.
|
||||
*
|
||||
* @return updated login data (and new token value) or null if token is not (or not anymore)
|
||||
* available for logging in.
|
||||
*/
|
||||
suspend fun loginByToken(token: ByteArray): SuperloginData<D>? {
|
||||
mustBeLoggedOut()
|
||||
val r = invoke(api.slLoginByToken,token)
|
||||
when(r) {
|
||||
val r = invoke(serverApi.slLoginByToken,token)
|
||||
return when(r) {
|
||||
AuthenticationResult.LoginIdUnavailable -> TODO()
|
||||
AuthenticationResult.LoginUnavailable -> TODO()
|
||||
AuthenticationResult.LoginUnavailable -> null
|
||||
AuthenticationResult.RestoreIdUnavailable -> TODO()
|
||||
is AuthenticationResult.Success -> TODO()
|
||||
is AuthenticationResult.Success -> SuperloginData(
|
||||
r.loginToken,
|
||||
extractData(r.applicationData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,5 +23,20 @@ interface SLServerTraits {
|
||||
*/
|
||||
suspend fun register(registrationArgs: RegistrationArgs): AuthenticationResult
|
||||
|
||||
/**
|
||||
* Logging out procedure does not need any extra logic unless reuired by application
|
||||
* server software. Default implementation does nothing.
|
||||
*/
|
||||
suspend fun logout() {}
|
||||
|
||||
/**
|
||||
* Try to log in using an authentication token, which normally is returned in
|
||||
* [AuthenticationResult.Success.loginToken]. If the server implementation
|
||||
* does not support login token, don't implement it, use the default implementation.
|
||||
*
|
||||
* Otherwise, implement login by token and return either [AuthenticationResult.Success]
|
||||
* or [AuthenticationResult.LoginUnavailable]. So not return anything else.
|
||||
*/
|
||||
suspend fun loginByToken(token: ByteArray): AuthenticationResult
|
||||
= AuthenticationResult.LoginUnavailable
|
||||
}
|
@ -25,4 +25,7 @@ inline fun <reified D, T : SLServerSession<D>, H : CommandHost<T>> AdapterBuilde
|
||||
loginName = null
|
||||
traits.logout()
|
||||
}
|
||||
on(a2.slLoginByToken) { token ->
|
||||
traits.loginByToken(token)
|
||||
}
|
||||
}
|
@ -4,16 +4,15 @@ import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.sergeych.parsec3.CommandHost
|
||||
import net.sergeych.parsec3.Parsec3WSClient
|
||||
import net.sergeych.parsec3.WithAdapter
|
||||
import net.sergeych.parsec3.parsec3TransportServer
|
||||
import net.sergeych.superlogin.AuthenticationResult
|
||||
import net.sergeych.superlogin.RegistrationArgs
|
||||
import net.sergeych.superlogin.SuperloginServerApi
|
||||
import net.sergeych.superlogin.client.LoginState
|
||||
import net.sergeych.superlogin.client.Registration
|
||||
import net.sergeych.superlogin.client.SuperloginClient
|
||||
import net.sergeych.superlogin.server.SLServerApiBase
|
||||
import net.sergeych.superlogin.server.SLServerSession
|
||||
import net.sergeych.superlogin.server.SLServerTraits
|
||||
import net.sergeych.superlogin.server.superloginServer
|
||||
@ -22,11 +21,12 @@ import kotlin.random.Random
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
data class TestSession(var buzz: String = "BuZZ") : SLServerSession<TestData>()
|
||||
|
||||
|
||||
object TestApiServer : SLServerApiBase<TestData>() {
|
||||
class TestApiServer<T : WithAdapter> : CommandHost<T>() {
|
||||
val loginName by command<Unit, String?>()
|
||||
}
|
||||
|
||||
@ -56,6 +56,12 @@ object TestServerTraits : SLServerTraits {
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loginByToken(token: ByteArray): AuthenticationResult {
|
||||
return byToken[token.toList()]?.let {
|
||||
AuthenticationResult.Success(token, it.extraData)
|
||||
} ?: AuthenticationResult.LoginUnavailable
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@ -63,6 +69,16 @@ data class TestData(
|
||||
val foo: String,
|
||||
)
|
||||
|
||||
//fun <S: SLServerSession<*>,A: CommandHost<S>> Application.superloginServer(
|
||||
// traits: SLServerTraits,
|
||||
// api: A,
|
||||
// f: AdapterBuilder<S,A>.()->Unit) {
|
||||
// parsec3TransportServer(api) {
|
||||
// superloginServer(traits)
|
||||
// f()
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
internal class WsServerKtTest {
|
||||
|
||||
@ -71,7 +87,8 @@ internal class WsServerKtTest {
|
||||
fun testWsServer() {
|
||||
|
||||
embeddedServer(Netty, port = 8080) {
|
||||
parsec3TransportServer(TestApiServer) {
|
||||
parsec3TransportServer(TestApiServer<SLServerSession<TestData>>()) {
|
||||
// superloginServer(TestServerTraits,TestApiServer<SLServerSession<TestData>>()) {
|
||||
newSession { TestSession() }
|
||||
superloginServer(TestServerTraits)
|
||||
on(api.loginName) {
|
||||
@ -80,11 +97,10 @@ internal class WsServerKtTest {
|
||||
}
|
||||
}.start(wait = false)
|
||||
|
||||
val client = Parsec3WSClient("ws://localhost:8080/api/p3", SuperloginServerApi<WithAdapter>()) {
|
||||
}
|
||||
|
||||
val client = Parsec3WSClient("ws://localhost:8080/api/p3")
|
||||
|
||||
runBlocking {
|
||||
val api = TestApiServer<WithAdapter>()
|
||||
val slc = SuperloginClient<TestData, WithAdapter>(client)
|
||||
assertEquals(LoginState.LoggedOut, slc.state.value)
|
||||
var rt = slc.register("foo", "passwd", TestData("bar!"))
|
||||
@ -94,7 +110,7 @@ internal class WsServerKtTest {
|
||||
println(rt.secret)
|
||||
assertEquals("bar!", rt.data<TestData>()?.foo)
|
||||
|
||||
assertEquals("foo", slc.call(TestApiServer.loginName))
|
||||
assertEquals("foo", slc.call(api.loginName))
|
||||
|
||||
val s = slc.state.value
|
||||
assertIs<LoginState.LoggedIn<TestData>>(s)
|
||||
@ -105,12 +121,15 @@ internal class WsServerKtTest {
|
||||
}
|
||||
slc.logout()
|
||||
assertIs<LoginState.LoggedOut>(slc.state.value)
|
||||
assertEquals(null, slc.call(TestApiServer.loginName))
|
||||
assertEquals(null, slc.call(api.loginName))
|
||||
|
||||
rt = slc.register("foo", "passwd", TestData("nobar"))
|
||||
assertIs<Registration.Result.InvalidLogin>(rt)
|
||||
|
||||
// slc.loginByToken()
|
||||
var ar = slc.loginByToken(token)
|
||||
assertNotNull(ar)
|
||||
assertEquals("bar!", ar.data?.foo)
|
||||
assertEquals("foo", slc.call(api.loginName))
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user