124 lines
4.5 KiB
Kotlin
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.sessions.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) }
|
|
}
|
|
}
|
|
}
|