diff --git a/app/src/main/java/com/afollestad/nocknock/AppExt.kt b/app/src/main/java/com/afollestad/nocknock/AppExt.kt index c7af855..828e01f 100644 --- a/app/src/main/java/com/afollestad/nocknock/AppExt.kt +++ b/app/src/main/java/com/afollestad/nocknock/AppExt.kt @@ -20,12 +20,12 @@ import android.app.Application import android.app.Application.ActivityLifecycleCallbacks import android.content.ActivityNotFoundException import android.content.Intent -import android.net.Uri import android.os.Bundle import androidx.browser.customtabs.CustomTabsIntent import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY import androidx.core.text.HtmlCompat.fromHtml import com.afollestad.materialdialogs.utils.MDUtil.resolveColor +import com.afollestad.nocknock.utilities.ext.toUri import com.afollestad.nocknock.utilities.ui.toast 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.toUri() = Uri.parse(this)!! - fun Activity.viewUrl(url: String) { val customTabsIntent = CustomTabsIntent.Builder() .apply { diff --git a/app/src/main/java/com/afollestad/nocknock/koin/MainModule.kt b/app/src/main/java/com/afollestad/nocknock/koin/MainModule.kt index d61e13a..07f6410 100644 --- a/app/src/main/java/com/afollestad/nocknock/koin/MainModule.kt +++ b/app/src/main/java/com/afollestad/nocknock/koin/MainModule.kt @@ -25,6 +25,7 @@ import com.afollestad.nocknock.data.AppDatabase import com.afollestad.nocknock.data.Database1to2Migration import com.afollestad.nocknock.data.Database2to3Migration 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.ui.main.MainActivity import com.afollestad.nocknock.utilities.ext.systemService @@ -43,7 +44,8 @@ val mainModule = module { .addMigrations( Database1to2Migration(), Database2to3Migration(), - Database3to4Migration() + Database3to4Migration(), + Database4to5Migration() ) .build() } diff --git a/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt b/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt new file mode 100644 index 0000000..2fa66dc --- /dev/null +++ b/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt @@ -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)!! diff --git a/data/src/main/java/com/afollestad/nocknock/data/AppDatabase.kt b/data/src/main/java/com/afollestad/nocknock/data/AppDatabase.kt index bfceff4..47687ba 100644 --- a/data/src/main/java/com/afollestad/nocknock/data/AppDatabase.kt +++ b/data/src/main/java/com/afollestad/nocknock/data/AppDatabase.kt @@ -34,7 +34,7 @@ import com.afollestad.nocknock.data.model.ValidationResult SiteSettings::class, Site::class ], - version = 4, + version = 5, exportSchema = false ) @TypeConverters(Converters::class) diff --git a/data/src/main/java/com/afollestad/nocknock/data/DatabaseMigrations.kt b/data/src/main/java/com/afollestad/nocknock/data/DatabaseMigrations.kt index 0bf5f0d..520a553 100644 --- a/data/src/main/java/com/afollestad/nocknock/data/DatabaseMigrations.kt +++ b/data/src/main/java/com/afollestad/nocknock/data/DatabaseMigrations.kt @@ -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") + } +} diff --git a/data/src/main/java/com/afollestad/nocknock/data/model/SiteSettings.kt b/data/src/main/java/com/afollestad/nocknock/data/model/SiteSettings.kt index 91667a7..bc73589 100644 --- a/data/src/main/java/com/afollestad/nocknock/data/model/SiteSettings.kt +++ b/data/src/main/java/com/afollestad/nocknock/data/model/SiteSettings.kt @@ -40,8 +40,10 @@ data class SiteSettings( /** Whether or not the [Site] is enabled for automatic periodic checks. */ var disabled: Boolean, /** The network response timeout for validation attempts. */ - var networkTimeout: Int + var networkTimeout: Int, + /** The Uri to a self signed certificate. */ + var certificate: String? ) : Serializable { - constructor() : this(0, 0, STATUS_CODE, null, false, 0) + constructor() : this(0, 0, STATUS_CODE, null, false, 0, null) } diff --git a/engine/src/main/java/com/afollestad/nocknock/engine/EngineModule.kt b/engine/src/main/java/com/afollestad/nocknock/engine/EngineModule.kt index e02bc1a..071960c 100644 --- a/engine/src/main/java/com/afollestad/nocknock/engine/EngineModule.kt +++ b/engine/src/main/java/com/afollestad/nocknock/engine/EngineModule.kt @@ -25,7 +25,7 @@ import org.koin.dsl.module.module val engineModule = module { single { - RealValidationExecutor(get(), get(), get(), get(), get(), get()) + RealValidationExecutor(get(), get(), get(), get(), get(), get(), get()) } bind ValidationExecutor::class factory { RealSslManager(get()) } bind SslManager::class diff --git a/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt b/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt index c247669..e4c6908 100644 --- a/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt +++ b/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt @@ -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.OK 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.utilities.ext.toUri import com.afollestad.nocknock.utilities.providers.BundleProvider import com.afollestad.nocknock.utilities.providers.JobInfoProvider import com.afollestad.nocknock.utilities.providers.StringProvider import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response +import org.jetbrains.annotations.TestOnly import java.net.SocketTimeoutException import java.util.concurrent.TimeUnit.MILLISECONDS import timber.log.Timber.d as log @@ -66,7 +69,8 @@ class RealValidationExecutor( private val stringProvider: StringProvider, private val bundleProvider: BundleProvider, private val jobInfoProvider: JobInfoProvider, - private val database: AppDatabase + private val database: AppDatabase, + private val sslManager: SslManager ) : ValidationExecutor { private var clientTimeoutChanger: ClientTimeoutChanger = { client, timeout -> @@ -161,7 +165,16 @@ class RealValidationExecutor( .build() 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) .execute() @@ -199,7 +212,9 @@ class RealValidationExecutor( jobScheduler.allPendingJobs .firstOrNull { job -> job.id == site.id.toInt() } -// @TestOnly fun setClientTimeoutChanger(changer: ClientTimeoutChanger) { -// this.clientTimeoutChanger = changer -// } + @Suppress("unused") + @TestOnly + fun setClientTimeoutChanger(changer: ClientTimeoutChanger) { + this.clientTimeoutChanger = changer + } } diff --git a/engine/src/test/kotlin/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt b/engine/src/test/kotlin/com/afollestad/nocknock/engine/ValidationExecutorTest.kt similarity index 99% rename from engine/src/test/kotlin/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt rename to engine/src/test/kotlin/com/afollestad/nocknock/engine/ValidationExecutorTest.kt index db859f4..c880f01 100644 --- a/engine/src/test/kotlin/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt +++ b/engine/src/test/kotlin/com/afollestad/nocknock/engine/ValidationExecutorTest.kt @@ -45,7 +45,7 @@ import okhttp3.ResponseBody import org.junit.Test import java.net.SocketTimeoutException -class CheckStatusManagerTest { +class ValidationExecutorTest { private val timeoutError = "Oh no, a timeout"