import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.html.*
-import kotlinx.serialization.json.JsonObject
-import kotlinx.serialization.json.JsonPrimitive
+import kotlinx.serialization.Serializable
import org.litote.kmongo.*
-import starshipfights.*
+import starshipfights.CurrentConfiguration
+import starshipfights.DiscordLogin
import starshipfights.data.Id
import starshipfights.data.admiralty.*
import starshipfights.data.auth.User
import starshipfights.data.auth.UserSession
import starshipfights.data.createNonce
-import starshipfights.game.*
+import starshipfights.forbid
+import starshipfights.game.Faction
+import starshipfights.game.ShipType
+import starshipfights.game.toUrlSlug
import starshipfights.info.*
+import starshipfights.redirect
import java.time.Instant
import java.time.temporal.ChronoUnit
agent = discordLogin.userAgent
}
- install(RateLimit)
+ install(RateLimit) {
+ jsonCodec = JsonClientCodec
+ }
}
override fun installAuth(conf: Authentication.Configuration) {
}
}
- val userInfo = JsonConfigCodec.parseToJsonElement(userInfoJson) as? JsonObject ?: redirect("/login")
- val discordId = (userInfo["id"] as? JsonPrimitive)?.content ?: redirect("/login")
- val discordUsername = (userInfo["username"] as? JsonPrimitive)?.content ?: redirect("/login")
- val discordDiscriminator = (userInfo["discriminator"] as? JsonPrimitive)?.content ?: redirect("/login")
- val discordAvatar = (userInfo["avatar"] as? JsonPrimitive)?.content
+ val userInfo = JsonClientCodec.decodeFromString(DiscordUserInfo.serializer(), userInfoJson)
+ val (discordId, discordUsername, discordDiscriminator, discordAvatar) = userInfo
var redirectTo = "/me"
val userSession = UserSession(
user = user.id,
- clientAddresses = listOf(call.request.origin.remoteHost),
+ clientAddresses = if (user.logIpAddresses) listOf(call.request.origin.remoteHost) else emptyList(),
userAgent = userAgent,
expiration = Instant.now().plus(1, ChronoUnit.HOURS)
)
return nonces.remove(nonce)
}
}
+
+@Serializable
+data class DiscordUserInfo(
+ val id: String,
+ val username: String,
+ val discriminator: String,
+ val avatar: String
+)
import io.ktor.request.*
import io.ktor.sessions.*
import io.ktor.util.*
+import kotlinx.serialization.json.Json
import starshipfights.forbid
import starshipfights.data.Id
import starshipfights.data.auth.User
}
suspend fun UserSession.renewed(clientAddress: String) = copy(
- expiration = Instant.now().plus(1, ChronoUnit.HOURS),
+ expiration = Instant.now().plus(2, ChronoUnit.HOURS),
clientAddresses = if (User.get(user)?.logIpAddresses != true)
emptyList()
else if (clientAddresses.lastOrNull() != clientAddress)
else
forbid()
}
+
+val JsonClientCodec = Json {
+ ignoreUnknownKeys = true
+}
import org.litote.kmongo.eq
import org.litote.kmongo.gt
import org.litote.kmongo.or
-import starshipfights.forbid
import starshipfights.auth.*
import starshipfights.data.Id
import starshipfights.data.admiralty.*
import starshipfights.data.auth.*
+import starshipfights.forbid
import starshipfights.game.*
import starshipfights.redirect
import java.time.Instant
}
}
}
+ section {
+ val currRank = admiral.rank
+ if (currRank.ordinal < AdmiralRank.values().size - 1) {
+ val nextRank = AdmiralRank.values()[currRank.ordinal + 1]
+ val reqAcumen = nextRank.minAcumen - currRank.minAcumen
+ val hasAcumen = admiral.acumen - currRank.minAcumen
+
+ label {
+ h2 { +"Progress to Promotion" }
+ progress {
+ style = "width:100%;box-sizing:border-box"
+ max = "$reqAcumen"
+ value = "$hasAcumen"
+ +"$hasAcumen/$reqAcumen"
+ }
+ }
+ p {
+ +"${admiral.fullName} is $hasAcumen/$reqAcumen Acumen away from being promoted to ${nextRank.getDisplayName(admiral.faction)}"
+ }
+ } else {
+ h2 { +"Progress to Promotion" }
+ p {
+ +"${admiral.fullName} is at the maximum rank possible for the ${admiral.faction.navyName}."
+ }
+ }
+ }
section {
h2 { +"Manage Fleet" }
p {