Simplify password connections
This commit is contained in:
parent
1347b9ea10
commit
e1c8ffcd5d
4 changed files with 14 additions and 48 deletions
|
@ -6,15 +6,11 @@ import androidx.core.content.edit
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.wbrawner.piholeclient.PiHoleApiService
|
||||
import com.wbrawner.piholeclient.Summary
|
||||
import com.wbrawner.piholeclient.VersionResponse
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.ConnectException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.util.regex.Pattern
|
||||
import java.util.regex.Pattern.DOTALL
|
||||
|
||||
const val KEY_BASE_URL = "baseUrl"
|
||||
const val KEY_API_KEY = "apiKey"
|
||||
|
@ -56,7 +52,9 @@ class AddPiHelperViewModel(
|
|||
suspend fun beginScanning(deviceIpAddress: String) {
|
||||
val addressParts = deviceIpAddress.split(".").toMutableList()
|
||||
var chunks = 1
|
||||
val ipAddresses = mutableListOf<String>()
|
||||
// If the Pi-hole is correctly set up, then there should be a special host for it as
|
||||
// "pi.hole"
|
||||
val ipAddresses = mutableListOf("pi.hole")
|
||||
while (chunks <= IP_MAX) {
|
||||
val chunkSize = (IP_MAX - IP_MIN + 1) / chunks
|
||||
if (chunkSize == 1) {
|
||||
|
@ -111,16 +109,8 @@ class AddPiHelperViewModel(
|
|||
}
|
||||
|
||||
suspend fun authenticateWithPassword(password: String) {
|
||||
// Perform the login to get the PHPSESSID cookie set
|
||||
apiService.login(password)
|
||||
val html = apiService.getApiToken()
|
||||
val matcher = Pattern.compile(".*Raw API Token: ([a-z0-9]+).*", DOTALL)
|
||||
.matcher(html)
|
||||
if (!matcher.matches()) {
|
||||
throw RuntimeException("Unable to retrieve API token from password")
|
||||
}
|
||||
val apiToken = matcher.group(1)!!
|
||||
authenticateWithApiKey(apiToken)
|
||||
// The Pi-hole API key is just the web password hashed twice with SHA-256
|
||||
authenticateWithApiKey(password.hash().hash())
|
||||
}
|
||||
|
||||
suspend fun authenticateWithApiKey(apiKey: String) {
|
||||
|
@ -143,4 +133,4 @@ class AddPiHelperViewModel(
|
|||
baseUrl = null
|
||||
apiKey = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
package com.wbrawner.pihelper
|
||||
|
||||
fun <T, R> R.transform(block: (R) -> T): T = block(this)
|
||||
import java.math.BigInteger
|
||||
import java.security.MessageDigest
|
||||
|
||||
fun String.hash(): String = BigInteger(
|
||||
1,
|
||||
MessageDigest.getInstance("SHA-256").digest(this.toByteArray())
|
||||
).toString(16)
|
||||
|
|
|
@ -15,12 +15,11 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.pihelper.MainActivity.Companion.ACTION_FORGET_PIHOLE
|
||||
import kotlinx.android.synthetic.main.fragment_main.toolbar
|
||||
import kotlinx.android.synthetic.main.fragment_info.*
|
||||
import kotlinx.android.synthetic.main.fragment_main.toolbar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.lang.RuntimeException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class InfoFragment : Fragment(), CoroutineScope {
|
||||
|
@ -30,7 +29,6 @@ class InfoFragment : Fragment(), CoroutineScope {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
throw RuntimeException("I crashed!")
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
|
|
@ -4,20 +4,14 @@ import com.squareup.moshi.Moshi
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
interface PiHoleApiService {
|
||||
var baseUrl: String?
|
||||
var apiKey: String?
|
||||
|
||||
suspend fun login(password: String): String
|
||||
|
||||
suspend fun getApiToken(): String
|
||||
|
||||
suspend fun getSummary(
|
||||
version: Boolean = false,
|
||||
type: Boolean = false
|
||||
|
@ -48,8 +42,6 @@ interface PiHoleApiService {
|
|||
}
|
||||
|
||||
const val BASE_PATH = "/admin/api.php"
|
||||
const val INDEX_PATH = "/admin/index.php"
|
||||
const val API_TOKEN_PATH = "/admin/scripts/pi-hole/php/api_token.php"
|
||||
|
||||
class OkHttpPiHoleApiService(
|
||||
private val okHttpClient: OkHttpClient,
|
||||
|
@ -110,26 +102,6 @@ class OkHttpPiHoleApiService(
|
|||
return sendRequest(request.build(), TopItemsResponse::class)!!
|
||||
}
|
||||
|
||||
override suspend fun login(password: String): String {
|
||||
val url = urlBuilder
|
||||
.encodedPath(INDEX_PATH)
|
||||
.addQueryParameter("login", "")
|
||||
val body = "pw=$password".toRequestBody("application/x-www-form-urlencoded".toMediaType())
|
||||
val request = Request.Builder()
|
||||
.post(body)
|
||||
.url(url.build())
|
||||
return sendRequest(request.build(), String::class)!!
|
||||
}
|
||||
|
||||
override suspend fun getApiToken(): String {
|
||||
val url = urlBuilder
|
||||
.encodedPath(API_TOKEN_PATH)
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url(url.build())
|
||||
return sendRequest(request.build(), String::class)!!
|
||||
}
|
||||
|
||||
override suspend fun enable(): StatusResponse {
|
||||
val apiToken = this.apiKey ?: throw java.lang.IllegalStateException("No API Token provided")
|
||||
val url = urlBuilder
|
||||
|
|
Loading…
Reference in a new issue