Skip to content

Commit

Permalink
Add certificate transparency check to all network calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Niels Masdorp committed Jul 26, 2020
1 parent 8bea5b2 commit 131d185
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 60 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
- Stuurt notificaties als je voorraad/koopblok status verandert
- Optie om notificaties naar een Telegram (groeps)chat te sturen
- Je Bol.com credentials worden versleuteld opgeslagen op je telefoon en verlaten je telefoon nooit
- Dark mode
- Versleutelde verbinding met Bol.com (SSL en Certificate Transparency check)
- Donker thema
- Kopieer snel een EAN door lang op een product te drukken
- Zie de volledige product naam door op een product te drukken

Expand Down
11 changes: 7 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ android {
applicationId "com.nielsmasdorp.lvbnotifier"
minSdkVersion 26
targetSdkVersion 28
versionCode 40
versionCode 41
versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -36,14 +36,14 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

// Material
implementation 'com.google.android.material:material:1.3.0-alpha01'
implementation 'com.google.android.material:material:1.3.0-alpha02'

// AndroidX
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation "androidx.work:work-runtime-ktx:2.3.4"
implementation "androidx.work:work-runtime-ktx:2.4.0"
implementation "androidx.preference:preference:1.1.1"
implementation "androidx.security:security-crypto:1.1.0-alpha01"

Expand All @@ -59,6 +59,9 @@ dependencies {
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"

// Cert transparency
implementation "com.babylon.certificatetransparency:certificatetransparency-android:0.2.0"

// Chuck
debugApi 'com.readystatesoftware.chuck:library:1.1.0'
releaseApi 'com.readystatesoftware.chuck:library-no-op:1.1.0'
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".LVBNotifierApplication"
android:name=".LvBuddyApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,32 @@ import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import androidx.core.app.NotificationManagerCompat
import com.nielsmasdorp.lvbnotifier.di.appModule
import com.nielsmasdorp.lvbnotifier.di.*
import com.nielsmasdorp.lvbnotifier.work.StateUpdateScheduler
import org.koin.android.ext.android.inject
import org.koin.android.ext.android.startKoin

class LVBNotifierApplication : Application() {
class LvBuddyApplication : Application() {

private val notificationScheduler: StateUpdateScheduler by inject()

private val notificationManager: NotificationManagerCompat by inject()

override fun onCreate() {
super.onCreate()
startKoin(this, listOf(appModule))
startKoin(
this,
listOf(
settingsModule,
notificationsModule,
stockModule,
buyBoxModule,
clipBoardModule,
authModule,
networkModule,
uiModule
)
)
setupNotificationChannel()
notificationScheduler.schedule()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.nielsmasdorp.domain.notifications.NotificationHandler
import com.nielsmasdorp.lvbnotifier.LVBNotifierApplication.Companion.NOTIFICATION_CHANNEL_ID
import com.nielsmasdorp.lvbnotifier.LvBuddyApplication.Companion.NOTIFICATION_CHANNEL_ID
import com.nielsmasdorp.lvbnotifier.R
import com.nielsmasdorp.lvbnotifier.presentation.stock.StockActivity
import java.util.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.nielsmasdorp.lvbnotifier.di
import android.content.Context
import androidx.core.app.NotificationManagerCompat
import androidx.work.WorkManager
import com.babylon.certificatetransparency.certificateTransparencyInterceptor
import com.nielsmasdorp.domain.auth.TokenManager
import com.nielsmasdorp.domain.buybox.BuyBoxRepository
import com.nielsmasdorp.domain.clipboard.Clipboard
Expand Down Expand Up @@ -45,7 +46,7 @@ import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import java.io.File

fun createLVBStockService(client: OkHttpClient): StockService {
private fun createLVBStockService(client: OkHttpClient): StockService {
return Retrofit.Builder()
.baseUrl("https://api.bol.com/retailer/")
.client(client)
Expand All @@ -54,15 +55,15 @@ fun createLVBStockService(client: OkHttpClient): StockService {
.create(StockService::class.java)
}

fun createMessageService(client: OkHttpClient): TelegramService {
private fun createMessageService(client: OkHttpClient): TelegramService {
return Retrofit.Builder()
.baseUrl("https://api.telegram.org")
.client(client)
.build()
.create(TelegramService::class.java)
}

fun createBuyBoxService(client: OkHttpClient): BuyBoxService {
private fun createBuyBoxService(client: OkHttpClient): BuyBoxService {
return Retrofit.Builder()
.baseUrl("https://www.bol.com/nl/rnwy/artikelen/")
.client(client)
Expand All @@ -71,29 +72,54 @@ fun createBuyBoxService(client: OkHttpClient): BuyBoxService {
.create(BuyBoxService::class.java)
}

fun getCacheDir(context: Context): File {
private fun getCacheDir(context: Context): File {
return File(context.applicationContext.cacheDir, "http-cache")
}

val appModule = module {

val settingsModule = module {
single<SharedPrefsDataStore> { EncryptedSharedPreferenceDataStore(androidApplication()) }
single<SettingsRepository> {
SharedPreferencesSettingsRepository(
get()
)
}
}

val notificationsModule = module {
single { NotificationManagerCompat.from(androidApplication()) }

single<LastKnownStockRepository> {
SharedPreferencesLastKnownStockRepository(
single<NotificationHandler>("telegramNotificationHandler", definition = {
TelegramNotificationHandler(
createMessageService(get("defaultClient")),
get()
)
})
single<NotificationHandler>("systemNotificationHandler", definition = {
SystemNotificationHandler(get(), get())
})
single {
SendNotification(
get("telegramNotificationHandler"),
get("systemNotificationHandler"),
get()
)
}
single<BuyBoxRepository> {
ScrapeBuyBoxRepository(
createBuyBoxService(get("buyBoxClient")),
single { WorkManager.getInstance(androidApplication()) }
single {
StateUpdateScheduler(
get(),
get(),
get()
)
}
single<SettingsRepository> {
SharedPreferencesSettingsRepository(
single { ShouldPoll(get(), get()) }
single { CanSendNotifications(get()) }
single { CanSendBuyBoxNotifications(get(), get()) }
single { CheckNewLVBState(get(), get(), get(), get(), get(), get(), get(), get()) }
}

val stockModule = module {
single<LastKnownStockRepository> {
SharedPreferencesLastKnownStockRepository(
get()
)
}
Expand All @@ -103,38 +129,29 @@ val appModule = module {
get()
)
}
single<NotificationHandler>("telegramNotificationHandler") {
TelegramNotificationHandler(
createMessageService(get("defaultClient")),
get()
)
}
single<NotificationHandler>("systemNotificationHandler") {
SystemNotificationHandler(get(), get())
}
single<MessageProvider> { AndroidMessageProvider(androidApplication()) }
single<Clipboard> { AndroidClipboard(androidApplication()) }
single { GetLastKnownStock(get()) }
single { SetLastKnownStock(get()) }
single { GetBuyBoxStatus(get()) }
single { SetBuyBoxStatus(get()) }
single { GetStock(get()) }
single { SaveProductEAN(get()) }
single { ShouldPoll(get(), get()) }
single { CanShowStock(get()) }
single { CanSendNotifications(get()) }
single { CanSendBuyBoxNotifications(get(), get()) }

single { CheckNewLVBState(get(), get(), get(), get(), get(), get(), get(), get()) }
}

single {
SendNotification(
get("telegramNotificationHandler"),
get("systemNotificationHandler"),
val buyBoxModule = module {
single<BuyBoxRepository> {
ScrapeBuyBoxRepository(
createBuyBoxService(get("buyBoxClient")),
get()
)
}
single { GetBuyBoxStatus(get()) }
single { SetBuyBoxStatus(get()) }
}

val clipBoardModule = module {
single { SaveProductEAN(get()) }
single<Clipboard> { AndroidClipboard(androidApplication()) }
}

val authModule = module {
single<AuthService> {
Retrofit.Builder()
.baseUrl("https://login.bol.com/")
Expand All @@ -150,45 +167,46 @@ val appModule = module {
settingsRepository = get()
)
}
}

val networkModule = module {
single("certTransparencyInterceptor", definition = {
certificateTransparencyInterceptor {
// Enable for all hosts
+"*.*"
}
})
single("defaultClient", definition = {
OkHttpClient.Builder().apply {
addNetworkInterceptor(get("certTransparencyInterceptor"))
//addInterceptor(ChuckInterceptor(androidApplication()))
}.build()
})

single("buyBoxClient", definition = {
OkHttpClient.Builder().apply {
addNetworkInterceptor(get("certTransparencyInterceptor"))
addNetworkInterceptor(CacheInterceptor())
cache(get())
//addInterceptor(ChuckInterceptor(androidApplication()))
}.build()
})

single("stockClient", definition = {
OkHttpClient.Builder().apply {
addNetworkInterceptor(get("certTransparencyInterceptor"))
addNetworkInterceptor(CacheInterceptor())
addInterceptor(OAuth2Interceptor(get()))
authenticator(OAuth2Authenticator(get()))
cache(get())
addInterceptor(ChuckInterceptor(androidApplication()))
}.build()
})

single {
Cache(getCacheDir(get()), 10 * 1024 * 1024.toLong()) // 10 MiB
}
}

single { WorkManager.getInstance(androidApplication()) }
single {
StateUpdateScheduler(
get(),
get(),
get()
)
}

val uiModule = module {
single<MessageProvider> { AndroidMessageProvider(androidApplication()) }
viewModel { StockViewModel(get(), get(), get(), get()) }

viewModel { SettingsViewModel(get(), get(), get(), get(), get()) }
}

0 comments on commit 131d185

Please sign in to comment.