Integrate SslManager into the ValidationExecutor

This commit is contained in:
Aidan Follestad 2019-01-11 18:12:51 -08:00
commit 909e5420ad
9 changed files with 63 additions and 14 deletions

View file

@ -20,12 +20,12 @@ import android.app.Application
import android.app.Application.ActivityLifecycleCallbacks import android.app.Application.ActivityLifecycleCallbacks
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
import androidx.core.text.HtmlCompat.fromHtml import androidx.core.text.HtmlCompat.fromHtml
import com.afollestad.materialdialogs.utils.MDUtil.resolveColor import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
import com.afollestad.nocknock.utilities.ext.toUri
import com.afollestad.nocknock.utilities.ui.toast import com.afollestad.nocknock.utilities.ui.toast
typealias ActivityLifeChange = (activity: Activity, resumed: Boolean) -> Unit typealias ActivityLifeChange = (activity: Activity, resumed: Boolean) -> Unit
@ -57,8 +57,6 @@ fun Application.onActivityLifeChange(cb: ActivityLifeChange) {
fun String.toHtml() = fromHtml(this, FROM_HTML_MODE_LEGACY) fun String.toHtml() = fromHtml(this, FROM_HTML_MODE_LEGACY)
fun String.toUri() = Uri.parse(this)!!
fun Activity.viewUrl(url: String) { fun Activity.viewUrl(url: String) {
val customTabsIntent = CustomTabsIntent.Builder() val customTabsIntent = CustomTabsIntent.Builder()
.apply { .apply {

View file

@ -25,6 +25,7 @@ import com.afollestad.nocknock.data.AppDatabase
import com.afollestad.nocknock.data.Database1to2Migration import com.afollestad.nocknock.data.Database1to2Migration
import com.afollestad.nocknock.data.Database2to3Migration import com.afollestad.nocknock.data.Database2to3Migration
import com.afollestad.nocknock.data.Database3to4Migration import com.afollestad.nocknock.data.Database3to4Migration
import com.afollestad.nocknock.data.Database4to5Migration
import com.afollestad.nocknock.notifications.Qualifiers.MAIN_ACTIVITY_CLASS import com.afollestad.nocknock.notifications.Qualifiers.MAIN_ACTIVITY_CLASS
import com.afollestad.nocknock.ui.main.MainActivity import com.afollestad.nocknock.ui.main.MainActivity
import com.afollestad.nocknock.utilities.ext.systemService import com.afollestad.nocknock.utilities.ext.systemService
@ -43,7 +44,8 @@ val mainModule = module {
.addMigrations( .addMigrations(
Database1to2Migration(), Database1to2Migration(),
Database2to3Migration(), Database2to3Migration(),
Database3to4Migration() Database3to4Migration(),
Database4to5Migration()
) )
.build() .build()
} }

View file

@ -0,0 +1,20 @@
/**
* Designed and developed by Aidan Follestad (@afollestad)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.afollestad.nocknock.utilities.ext
import android.net.Uri
fun String.toUri() = Uri.parse(this)!!

View file

@ -34,7 +34,7 @@ import com.afollestad.nocknock.data.model.ValidationResult
SiteSettings::class, SiteSettings::class,
Site::class Site::class
], ],
version = 4, version = 5,
exportSchema = false exportSchema = false
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)

View file

@ -57,3 +57,15 @@ class Database3to4Migration : Migration(3, 4) {
) )
} }
} }
/**
* Migrates the database from version 4 to 5.
*
* @author Aidan Follestad (@afollestad)
*/
class Database4to5Migration : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE `site_settings` ADD COLUMN certificatePath TEXT")
}
}

View file

@ -40,8 +40,10 @@ data class SiteSettings(
/** Whether or not the [Site] is enabled for automatic periodic checks. */ /** Whether or not the [Site] is enabled for automatic periodic checks. */
var disabled: Boolean, var disabled: Boolean,
/** The network response timeout for validation attempts. */ /** The network response timeout for validation attempts. */
var networkTimeout: Int var networkTimeout: Int,
/** The Uri to a self signed certificate. */
var certificate: String?
) : Serializable { ) : Serializable {
constructor() : this(0, 0, STATUS_CODE, null, false, 0) constructor() : this(0, 0, STATUS_CODE, null, false, 0, null)
} }

View file

@ -25,7 +25,7 @@ import org.koin.dsl.module.module
val engineModule = module { val engineModule = module {
single { single {
RealValidationExecutor(get(), get(), get(), get(), get(), get()) RealValidationExecutor(get(), get(), get(), get(), get(), get(), get())
} bind ValidationExecutor::class } bind ValidationExecutor::class
factory { RealSslManager(get()) } bind SslManager::class factory { RealSslManager(get()) } bind SslManager::class

View file

@ -23,13 +23,16 @@ import com.afollestad.nocknock.data.model.Site
import com.afollestad.nocknock.data.model.Status.ERROR import com.afollestad.nocknock.data.model.Status.ERROR
import com.afollestad.nocknock.data.model.Status.OK import com.afollestad.nocknock.data.model.Status.OK
import com.afollestad.nocknock.engine.R import com.afollestad.nocknock.engine.R
import com.afollestad.nocknock.engine.ssl.SslManager
import com.afollestad.nocknock.engine.validation.ValidationJob.Companion.KEY_SITE_ID import com.afollestad.nocknock.engine.validation.ValidationJob.Companion.KEY_SITE_ID
import com.afollestad.nocknock.utilities.ext.toUri
import com.afollestad.nocknock.utilities.providers.BundleProvider import com.afollestad.nocknock.utilities.providers.BundleProvider
import com.afollestad.nocknock.utilities.providers.JobInfoProvider import com.afollestad.nocknock.utilities.providers.JobInfoProvider
import com.afollestad.nocknock.utilities.providers.StringProvider import com.afollestad.nocknock.utilities.providers.StringProvider
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jetbrains.annotations.TestOnly
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.util.concurrent.TimeUnit.MILLISECONDS import java.util.concurrent.TimeUnit.MILLISECONDS
import timber.log.Timber.d as log import timber.log.Timber.d as log
@ -66,7 +69,8 @@ class RealValidationExecutor(
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val bundleProvider: BundleProvider, private val bundleProvider: BundleProvider,
private val jobInfoProvider: JobInfoProvider, private val jobInfoProvider: JobInfoProvider,
private val database: AppDatabase private val database: AppDatabase,
private val sslManager: SslManager
) : ValidationExecutor { ) : ValidationExecutor {
private var clientTimeoutChanger: ClientTimeoutChanger = { client, timeout -> private var clientTimeoutChanger: ClientTimeoutChanger = { client, timeout ->
@ -161,7 +165,16 @@ class RealValidationExecutor(
.build() .build()
return try { return try {
val client = clientTimeoutChanger(okHttpClient, siteSettings.networkTimeout) val clientWithTimeout = clientTimeoutChanger(okHttpClient, siteSettings.networkTimeout)
val client = if (!siteSettings.certificate.isNullOrEmpty()) {
sslManager.clientForCertificate(
certUri = siteSettings.certificate!!.toUri(),
host = site.url.toUri().host ?: "",
client = clientWithTimeout
)
} else {
clientWithTimeout
}
val response = client.newCall(request) val response = client.newCall(request)
.execute() .execute()
@ -199,7 +212,9 @@ class RealValidationExecutor(
jobScheduler.allPendingJobs jobScheduler.allPendingJobs
.firstOrNull { job -> job.id == site.id.toInt() } .firstOrNull { job -> job.id == site.id.toInt() }
// @TestOnly fun setClientTimeoutChanger(changer: ClientTimeoutChanger) { @Suppress("unused")
// this.clientTimeoutChanger = changer @TestOnly
// } fun setClientTimeoutChanger(changer: ClientTimeoutChanger) {
this.clientTimeoutChanger = changer
}
} }

View file

@ -45,7 +45,7 @@ import okhttp3.ResponseBody
import org.junit.Test import org.junit.Test
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
class CheckStatusManagerTest { class ValidationExecutorTest {
private val timeoutError = "Oh no, a timeout" private val timeoutError = "Oh no, a timeout"