core/features/auth/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/auth/server/AuthenticationRoutingConfig...

124 lines
4.5 KiB
Kotlin

package dev.inmo.postssystem.features.auth.server
import dev.inmo.postssystem.features.auth.common.*
import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService
import dev.inmo.postssystem.features.common.server.ApplicationAuthenticationConfigurator
import dev.inmo.postssystem.features.users.common.User
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.configurators.*
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.auth.*
import io.ktor.server.response.respond
import io.ktor.server.routing.*
import io.ktor.server.sessions.sessions
import kotlinx.serialization.builtins.nullable
data class AuthUserPrincipal(
val user: User
) : Principal
fun User.principal() = AuthUserPrincipal(this)
class AuthenticationRoutingConfigurator(
private val authFeature: AuthFeature,
private val authTokensService: AuthTokensService,
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element, ApplicationAuthenticationConfigurator.Element {
override fun Route.invoke() {
unifiedRouter.apply {
route(authRootPathPart) {
post(authAuthPathPart) {
safely(
{
// TODO:: add error info
it.printStackTrace()
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
val creds = uniload(AuthCreds.serializer())
val tokenInfo = authFeature.auth(creds)
if (tokenInfo == null) {
if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
}
}
}
post (authRefreshPathPart) {
safely(
{
// TODO:: add error info
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
val refreshToken = uniload(RefreshToken.serializer())
val tokenInfo = authFeature.refresh(refreshToken)
if (tokenInfo == null) {
if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
}
}
}
post(authGetMePathPart) {
safely(
{
// TODO:: add error info
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
unianswer(
User.serializer().nullable,
authFeature.getMe(
uniload(AuthToken.serializer())
)
)
}
}
}
}
}
override fun AuthenticationConfig.invoke() {
session<AuthToken> {
validate {
val result = authTokensService.getUserPrincipal(it)
if (result.isSuccess) {
result.getOrThrow().principal()
} else {
null
}
}
challenge { call.respond(HttpStatusCode.Unauthorized) }
}
}
}