import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.html.*
+import org.litote.kmongo.and
import org.litote.kmongo.eq
+import org.litote.kmongo.ne
+import org.litote.kmongo.setValue
import starshipfights.CurrentConfiguration
import starshipfights.data.Id
import starshipfights.data.admiralty.Admiral
}
get("/logout") {
- call.sessions.get<Id<UserSession>>()?.let { sessId ->
+ call.getUserSession()?.let { sess ->
launch {
- UserSession.del(sessId)
+ val newTime = System.currentTimeMillis() - 100
+ UserSession.update(UserSession::id eq sess.id, setValue(UserSession::expirationMillis, newTime))
}
}
redirect("/")
}
+ get("/logout/{id}") {
+ val id = Id<UserSession>(call.parameters.getOrFail("id"))
+ call.getUserSession()?.let { sess ->
+ launch {
+ val newTime = System.currentTimeMillis() - 100
+ UserSession.update(and(UserSession::id eq id, UserSession::user eq sess.user), setValue(UserSession::expirationMillis, newTime))
+ }
+ }
+
+ redirect("/me/manage")
+ }
+
+ get("/logout-all") {
+ call.getUserSession()?.let { sess ->
+ launch {
+ val newTime = System.currentTimeMillis() - 100
+ UserSession.update(and(UserSession::user eq sess.user, UserSession::id ne sess.id), setValue(UserSession::expirationMillis, newTime))
+ }
+ }
+
+ redirect("/me/manage")
+ }
+
currentProvider.installRouting(this)
}
}
import kotlinx.coroutines.*
import org.litote.kmongo.div
import org.litote.kmongo.lt
-import org.litote.kmongo.lte
import org.litote.kmongo.setValue
import starshipfights.data.admiralty.Admiral
import starshipfights.data.admiralty.BattleRecord
UserSession.initialize()
return launch {
- launch {
- while (currentCoroutineContext().isActive) {
- launch {
- UserSession.remove(UserSession::expirationMillis lte System.currentTimeMillis())
- }
- delay(900_000)
- }
- }
-
+ // Repair ships
launch {
while (currentCoroutineContext().isActive) {
val now = Instant.now()
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.toList
import kotlinx.html.*
+import org.litote.kmongo.and
import org.litote.kmongo.eq
import org.litote.kmongo.or
import starshipfights.auth.getUser
import starshipfights.data.admiralty.DrydockStatus
import starshipfights.data.admiralty.ShipInDrydock
import starshipfights.data.auth.User
+import starshipfights.data.auth.UserSession
import starshipfights.data.auth.usernameRegexStr
import starshipfights.data.auth.usernameTooltip
import starshipfights.game.Faction
import starshipfights.game.toUrlSlug
import starshipfights.redirect
import java.time.Instant
+import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
+import java.util.*
+
+private val instantFormatter: DateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.US)
suspend fun ApplicationCall.userPage(): HTML.() -> Unit {
val username = parameters["name"]!!
}
suspend fun ApplicationCall.manageUserPage(): HTML.() -> Unit {
- val currentUser = getUser() ?: redirect("/login")
+ val currentSession = getUserSession() ?: redirect("/login")
+ val currentUser = User.get(currentSession.user) ?: redirect("/login")
+ val allUserSessions = UserSession.select(and(UserSession::user eq currentUser.id)).toList()
return page(
"User Preferences", standardNavBar(), PageNavSidebar(
}
}
}
+ section {
+ h1 { +"Other Active Sessions" }
+ table {
+ tr {
+ th { +"User-Agent" }
+ th { +"Client IPs" }
+ th { +Entities.nbsp }
+ }
+ val now = System.currentTimeMillis()
+ val expiredSessions = mutableListOf<UserSession>()
+ allUserSessions.forEach { session ->
+ if (session.expirationMillis < now) {
+ expiredSessions += session
+ return@forEach
+ }
+
+ tr {
+ td { +session.userAgent }
+ td {
+ session.clientAddresses.forEachIndexed { i, clientAddress ->
+ if (i != 0) br
+ +clientAddress
+ }
+ }
+ td {
+ a(href = "/logout/${session.id}") { +"Logout" }
+ }
+ }
+ }
+ tr {
+ td {
+ colSpan = "3"
+ a(href = "/logout-all") { +"Logout All" }
+ }
+ }
+ expiredSessions.forEach { session ->
+ tr {
+ td { +session.userAgent }
+ td {
+ session.clientAddresses.forEachIndexed { i, clientAddress ->
+ if (i != 0) br
+ +clientAddress
+ }
+ }
+ td {
+ +"Expired at "
+ +instantFormatter.format(Instant.ofEpochMilli(session.expirationMillis))
+ }
+ }
+ }
+ }
+ }
}
}
tr {
th { +"Role" }
th { +"Against" }
+ th { +"Time" }
th { +"Result" }
}
records.sortedBy { it.whenEnded }.forEach { record ->
+opponent.fullName
}
}
+ td {
+ +instantFormatter.format(record.whenEnded)
+ }
td {
+when (recordRoles[record.id]) {
record.winner -> "Victory"