Skip to content

Commit

Permalink
style: KtLint fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Lastaapps committed Sep 2, 2024
1 parent 38e4e5c commit 031619f
Show file tree
Hide file tree
Showing 362 changed files with 7,364 additions and 6,030 deletions.
13 changes: 7 additions & 6 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ ktlint_code_style = ktlint_official
# Indentation
indent_size = 4
indent_style = space
max_line_lengt = 100

# Trailing Comma
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
trailing-comma-on-call-site = true
trailing-comma-on-declaration-site = true

# Disable wrapping that I don't like
ktlint_standard_wrapping = disabled
ktlint_standard_multiline-expression-wrapping = disabled

# Compose
# https://mrmans0n.github.io/compose-rules/ktlint/
ktlint_function_naming_ignore_when_annotated_with = Composable
compose_disallow_material2 = true
compose_allowed_from_m2 = icons
compose_disallow_unstable_collections = true
# I'm responsible enough, hopefully
ktlint_compose_vm-forwarding-check = disabled

# modules for DI
[*Module.kt]
ktlint_standard_filename = disabled
Original file line number Diff line number Diff line change
Expand Up @@ -44,134 +44,150 @@ import java.net.URLDecoder
internal class AndroidAgataCtuWalletApi(
httpClient: HttpClient,
) : AgataCtuWalletApi {
private val client: HttpClient =
httpClient.config {
// Disable redirects, because when I was testing it with Python I got into loop sometimes
// Also it has to extract some cookies from some of the requests, so redirects manually handled
followRedirects = false
// Because of many redirects
expectSuccess = false

private val client: HttpClient = httpClient.config {
// Disable redirects, because when I was testing it with Python I got into loop sometimes
// Also it has to extract some cookies from some of the requests, so redirects manually handled
followRedirects = false
// Because of many redirects
expectSuccess = false
// disable logging, so user credentials/secrets are not accidentally logged
install(Logging) {
level = LogLevel.NONE
}

// disable logging, so user credentials/secrets are not accidentally logged
install(Logging) {
level = LogLevel.NONE
BrowserUserAgent()
}

BrowserUserAgent()
}

// Get balance from Agata
// Originally written by Marekkon5
override suspend fun getBalance(
username: String,
password: String,
): Outcome<Float> = catchingNetwork {
nullable {
// Go to the auth provider
client.get("https://agata.suz.cvut.cz/secure/index.php")
.headers[HttpHeaders.Location]
.bind()
.let { url -> client.get(url) }

// Get new url params
.let { request ->
val body = request.bodyAsText()
val returnUrl = Regex("var returnURL = \"(.+?)\"")
.find(body)?.groups?.get(1)?.value.bind()
val otherParams = Regex("var otherParams = \"(.+?)\"")
.find(body)?.groups?.get(1)?.value.bind()
"${returnUrl}&entityID=https://idp2.civ.cvut.cz/idp/shibboleth${otherParams}"
}
// Get to SSO
.let { url -> client.get(url).headers[HttpHeaders.Location].bind() }
.let { sso -> client.get(sso) }
.let { ssoResponse ->
// Extract JSESSIONID cookie
val jsessionid = ssoResponse.headers[HttpHeaders.SetCookie]
?.split(";")
?.firstOrNull()
?.split("=")
?.getOrNull(1)
.bind()

// Resolve SSO
val url =
"https://idp2.civ.cvut.cz${ssoResponse.headers[HttpHeaders.Location]}"

// result ignored, must happen
client.get(url)

client.post(url) {
setBody(
FormDataContent(
Parameters.build {
append("j_username", username)
append("j_password", password)
append("_eventId_proceed", "")
},
),
)
Cookie("JSESSIONID", jsessionid)
header(HttpHeaders.Referrer, url)
header(HttpHeaders.ContentType, "application/x-www-form-urlencoded")
): Outcome<Float> =
catchingNetwork {
nullable {
// Go to the auth provider
client
.get("https://agata.suz.cvut.cz/secure/index.php")
.headers[HttpHeaders.Location]
.bind()
.let { url -> client.get(url) }
// Get new url params
.let { request ->
val body = request.bodyAsText()
val returnUrl =
Regex("var returnURL = \"(.+?)\"")
.find(body)
?.groups
?.get(1)
?.value
.bind()
val otherParams =
Regex("var otherParams = \"(.+?)\"")
.find(body)
?.groups
?.get(1)
?.value
.bind()
"$returnUrl&entityID=https://idp2.civ.cvut.cz/idp/shibboleth$otherParams"
}
}
// Get to SSO
.let { url -> client.get(url).headers[HttpHeaders.Location].bind() }
.let { sso -> client.get(sso) }
.let { ssoResponse ->
// Extract JSESSIONID cookie
val jsessionid =
ssoResponse.headers[HttpHeaders.SetCookie]
?.split(";")
?.firstOrNull()
?.split("=")
?.getOrNull(1)
.bind()

// Extract response codes from html
.bodyAsText()
.let { html ->
var relayState: String? = null
var samlResponse: String? = null
// Resolve SSO
val url =
"https://idp2.civ.cvut.cz${ssoResponse.headers[HttpHeaders.Location]}"

val inputRegex =
"""<input[^>]*name="([^"]+)"[^>]*value="([^"]+)"[^>]""".toRegex()
inputRegex.findAll(html)
.forEach {
val name = it.groups[1].bind().value
val value = it.groups[2].bind().value
when (name) {
"RelayState" -> relayState = URLDecoder.decode(value, "UTF-8")
"SAMLResponse" -> samlResponse = value
}
}
if (relayState == null || samlResponse == null) {
return@catchingNetwork WalletError.InvalidCredentials.left()
}
// result ignored, must happen
client.get(url)

// Send the shit back to Agata and get session cookie
val response =
client.post("https://agata.suz.cvut.cz/Shibboleth.sso/SAML2/POST") {
client.post(url) {
setBody(
FormDataContent(
Parameters.build {
append("RelayState", relayState.bind())
append("SAMLResponse", samlResponse.bind())
append("j_username", username)
append("j_password", password)
append("_eventId_proceed", "")
},
),
)
header(HttpHeaders.Referrer, "https://idp2.civ.cvut.cz/")
Cookie("JSESSIONID", jsessionid)
header(HttpHeaders.Referrer, url)
header(HttpHeaders.ContentType, "application/x-www-form-urlencoded")
}
}
// Extract response codes from html
.bodyAsText()
.let { html ->
var relayState: String? = null
var samlResponse: String? = null

val inputRegex =
"""<input[^>]*name="([^"]+)"[^>]*value="([^"]+)"[^>]""".toRegex()
inputRegex
.findAll(html)
.forEach {
val name = it.groups[1].bind().value
val value = it.groups[2].bind().value
when (name) {
"RelayState" -> relayState = URLDecoder.decode(value, "UTF-8")
"SAMLResponse" -> samlResponse = value
}
}
if (relayState == null || samlResponse == null) {
return@catchingNetwork WalletError.InvalidCredentials.left()
}

response.headers[HttpHeaders.SetCookie]
?.split(";")
?.getOrNull(0)
.bind()
}.let { sessionCookie ->
// Get balance from Agata
client.get("https://agata.suz.cvut.cz/secure/index.php") {
// The session cookie has variable name, so using raw headers here
header("Cookie", sessionCookie)
// Send the shit back to Agata and get session cookie
val response =
client.post("https://agata.suz.cvut.cz/Shibboleth.sso/SAML2/POST") {
setBody(
FormDataContent(
Parameters.build {
append("RelayState", relayState.bind())
append("SAMLResponse", samlResponse.bind())
},
),
)
header(HttpHeaders.Referrer, "https://idp2.civ.cvut.cz/")
}

response.headers[HttpHeaders.SetCookie]
?.split(";")
?.getOrNull(0)
.bind()
}.let { sessionCookie ->
// Get balance from Agata
client.get("https://agata.suz.cvut.cz/secure/index.php") {
// The session cookie has variable name, so using raw headers here
header("Cookie", sessionCookie)
}
}.let { finalResponse ->
"""<h4><span[^>]*>(?:<span[^>]*>)?([\d, ]+) Kč<"""
.toRegex()
.find(finalResponse.bodyAsText())
?.groups
?.get(1)
?.value
.bind()
.replace(",", ".")
.replace(" ", "")
.trim()
.toFloatOrNull()
.bind()
}
}.let { finalResponse ->
"""<h4><span[^>]*>(?:<span[^>]*>)?([\d, ]+) Kč<""".toRegex()
.find(finalResponse.bodyAsText())?.groups?.get(1)?.value
.bind()
.replace(",", ".")
.replace(" ", "")
.trim()
.toFloatOrNull()
.bind()
}
}?.right() ?: WalletError.TotallyBroken.left()
}.flatten()
}?.right() ?: WalletError.TotallyBroken.left()
}.flatten()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023, Petr Laštovička as Lasta apps, All rights reserved
* Copyright 2024, Petr Laštovička as Lasta apps, All rights reserved
*
* This file is part of Menza.
*
Expand All @@ -25,6 +25,4 @@ import cz.lastaapps.api.agata.AgataDatabase

internal const val DB_NAME = "agata_api.db"

internal fun createAgataDBDriver(
context: Context,
) = AgataDatabaseSqlDriver(AndroidSqliteDriver(AgataDatabase.Schema, context, DB_NAME))
internal fun createAgataDBDriver(context: Context) = AgataDatabaseSqlDriver(AndroidSqliteDriver(AgataDatabase.Schema, context, DB_NAME))
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023, Petr Laštovička as Lasta apps, All rights reserved
* Copyright 2024, Petr Laštovička as Lasta apps, All rights reserved
*
* This file is part of Menza.
*
Expand Down Expand Up @@ -27,7 +27,8 @@ import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.bind
import org.koin.dsl.module

internal actual val platform: Module = module {
factory { createAgataDBDriver(get()) }
factoryOf(::AndroidAgataCtuWalletApi) bind AgataCtuWalletApi::class
}
internal actual val platform: Module =
module {
factory { createAgataDBDriver(get()) }
factoryOf(::AndroidAgataCtuWalletApi) bind AgataCtuWalletApi::class
}
Loading

0 comments on commit 031619f

Please sign in to comment.