Skip to content

Commit

Permalink
Merge branch 'release/1.2.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
jingjoeh committed Mar 24, 2020
2 parents 788c625 + c749115 commit f04f939
Show file tree
Hide file tree
Showing 34 changed files with 804 additions and 23 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ android {
defaultConfig {
applicationId "org.rfcx.ranger"
manifestPlaceholders = [auth0Domain: "@string/auth0_domain", auth0Scheme: "@string/auth0_scheme"]
versionCode 84
versionName "1.2.5"
versionCode 87
versionName "1.2.6"
minSdkVersion 19
targetSdkVersion 29
multiDexEnabled true
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/rfcx/ranger/RangerApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.koin.core.context.startKoin
import org.koin.core.module.Module
import org.rfcx.ranger.di.DataModule
import org.rfcx.ranger.di.UiModule
import org.rfcx.ranger.service.CleanupAudioCacheWorker
import org.rfcx.ranger.service.LocationCleanupWorker
import org.rfcx.ranger.service.ReportCleanupWorker
import org.rfcx.ranger.util.RealmHelper
Expand All @@ -36,6 +37,7 @@ class RangerApplication : MultiDexApplication() {
setupKoin()
ReportCleanupWorker.enqueuePeriodically()
LocationCleanupWorker.enqueuePeriodically()
CleanupAudioCacheWorker.enqueuePeriodically()

if (BuildConfig.USE_STETHO) {
Stetho.initialize(Stetho.newInitializerBuilder(this)
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/org/rfcx/ranger/data/local/EventDb.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class EventDb(val realm: Realm) {
realm.use { it ->
it.executeTransaction {
val events = it.where(Event::class.java)
.sort("beginsAt",Sort.DESCENDING)
.findAll()
list.addAll(it.copyFromRealm(events))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.rfcx.ranger.data.remote.setusername.SetNameEndpoint
import org.rfcx.ranger.data.remote.shortlink.ShortLinkEndpoint
import org.rfcx.ranger.data.remote.site.SiteEndpoint
import org.rfcx.ranger.data.remote.subscribe.SubscribeEndpoint
import org.rfcx.ranger.data.remote.terms.TermsEndpoint
import org.rfcx.ranger.data.remote.usertouch.UserTouchEndPoint
import org.rfcx.ranger.util.GsonProvider
import org.rfcx.ranger.util.ImprovedDateTypeAdapter
Expand Down Expand Up @@ -101,6 +102,12 @@ object ServiceFactory {
.create(SubscribeEndpoint::class.java)
}

fun makeTermsService(isDebug: Boolean, context: Context): TermsEndpoint {
return createRetrofit(BuildConfig.RANGER_DOMAIN, createAuthTokenOkHttpClient(isDebug, AuthTokenInterceptor(context)),
GsonProvider.getInstance().gson)
.create(TermsEndpoint::class.java)
}

private fun createRetrofit(baseUrl: String, okHttpClient: OkHttpClient, gson: Gson): Retrofit {
return Retrofit.Builder().baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.rfcx.ranger.data.remote.terms

import io.reactivex.Single
import org.rfcx.ranger.entity.terms.TermsRequest
import org.rfcx.ranger.entity.terms.TermsResponse
import retrofit2.http.Body
import retrofit2.http.POST

interface TermsEndpoint {
@POST("v1/users/accept-terms")
fun sendPayload(@Body body: TermsRequest): Single<TermsResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.rfcx.ranger.data.remote.terms

import io.reactivex.Single
import org.rfcx.ranger.entity.terms.TermsRequest
import org.rfcx.ranger.entity.terms.TermsResponse

interface TermsRepository {
fun sendBodyPayload(sendBody: TermsRequest): Single<TermsResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.rfcx.ranger.data.remote.terms

import io.reactivex.Single
import org.rfcx.ranger.entity.terms.TermsRequest
import org.rfcx.ranger.entity.terms.TermsResponse

class TermsRepositoryImp(private val termsEndpoint: TermsEndpoint) : TermsRepository {
override fun sendBodyPayload(sendBody: TermsRequest): Single<TermsResponse> {
return termsEndpoint.sendPayload(sendBody)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.rfcx.ranger.data.remote.terms

import io.reactivex.Single
import org.rfcx.ranger.data.remote.domain.SingleUseCase
import org.rfcx.ranger.data.remote.domain.executor.PostExecutionThread
import org.rfcx.ranger.data.remote.domain.executor.ThreadExecutor
import org.rfcx.ranger.entity.terms.TermsRequest
import org.rfcx.ranger.entity.terms.TermsResponse

class TermsUseCase(private val termsRepository: TermsRepository,
threadExecutor: ThreadExecutor, postExecutionThread: PostExecutionThread
) : SingleUseCase<TermsRequest, TermsResponse>(threadExecutor, postExecutionThread) {
override fun buildUseCaseObservable(params: TermsRequest): Single<TermsResponse> {
return termsRepository.sendBodyPayload(params)
}
}
7 changes: 7 additions & 0 deletions app/src/main/java/org/rfcx/ranger/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ import org.rfcx.ranger.data.remote.subscribe.SubscribeUseCase
import org.rfcx.ranger.data.remote.subscribe.unsubscribe.UnsubscribeRepository
import org.rfcx.ranger.data.remote.subscribe.unsubscribe.UnsubscribeRepositoryImp
import org.rfcx.ranger.data.remote.subscribe.unsubscribe.UnsubscribeUseCase
import org.rfcx.ranger.data.remote.terms.TermsRepository
import org.rfcx.ranger.data.remote.terms.TermsRepositoryImp
import org.rfcx.ranger.data.remote.terms.TermsUseCase
import org.rfcx.ranger.data.remote.usertouch.CheckUserTouchUseCase
import org.rfcx.ranger.data.remote.usertouch.UserTouchRepository
import org.rfcx.ranger.data.remote.usertouch.UserTouchRepositoryImp
Expand Down Expand Up @@ -110,6 +113,9 @@ object DataModule {
single { UnsubscribeRepositoryImp(get()) } bind UnsubscribeRepository::class
single { UnsubscribeUseCase(get(), get(), get()) }

single { TermsRepositoryImp(get()) } bind TermsRepository::class
single { TermsUseCase(get(), get(), get()) }

}

val remoteModule = module {
Expand All @@ -125,6 +131,7 @@ object DataModule {
factory { ServiceFactory.makePasswordService(BuildConfig.DEBUG, androidContext()) }
factory { ServiceFactory.makeProfilePhotoService(BuildConfig.DEBUG, androidContext()) }
factory { ServiceFactory.makeSubscribeService(BuildConfig.DEBUG, androidContext()) }
factory { ServiceFactory.makeTermsService(BuildConfig.DEBUG, androidContext()) }
}

val localModule = module {
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/rfcx/ranger/di/UiModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.rfcx.ranger.view.alerts.guardian.alertType.AlertValueViewModel
import org.rfcx.ranger.view.login.InvitationCodeViewModel
import org.rfcx.ranger.view.login.LoginViewModel
import org.rfcx.ranger.view.login.SetUserNameViewModel
import org.rfcx.ranger.view.login.TermsAndServiceViewModel
import org.rfcx.ranger.view.map.MapDetailViewModel
import org.rfcx.ranger.view.map.MapViewModel
import org.rfcx.ranger.view.map.ReportViewPagerFragmentViewModel
Expand Down Expand Up @@ -67,5 +68,6 @@ object UiModule {
viewModel { LoginViewModel(androidContext(), get()) }
viewModel { InvitationCodeViewModel(androidContext(), get()) }
viewModel { SetUserNameViewModel(androidContext(), get()) }
viewModel { TermsAndServiceViewModel(androidContext(), get()) }
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/org/rfcx/ranger/entity/terms/Terms.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.rfcx.ranger.entity.terms

import com.google.gson.annotations.SerializedName

open class TermsRequest(
val app: String
)

open class TermsResponse(
@SerializedName("success")
val success: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ import com.google.gson.annotations.SerializedName

data class InvitationCodeRequest(
@SerializedName("code")
val code: String
val code: String,

@SerializedName("accept_terms")
val acceptTerms: String,

@SerializedName("app")
val app: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package org.rfcx.ranger.entity.user

data class UserAuthResponse (val guid: String, val email: String?, val nickname: String?,
val idToken: String, val accessToken: String?, val refreshToken: String?,
val roles: Set<String> = setOf(), val accessibleSites: Set<String> = setOf(), val defaultSite: String? = null, val picture: String?) {
val roles: Set<String> = setOf(), val accessibleSites: Set<String> = setOf(), val defaultSite: String? = null, val picture: String?, val consentGivenRangerApp: String?) {

val isRanger: Boolean get() = roles.contains("rfcxUser") && defaultSite != null

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.rfcx.ranger.service

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.work.*
import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit

class CleanupAudioCacheWorker(val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {

private val audioDirectory = File(context.cacheDir, DownLoadEventWorker.AUDIOS_SUB_DIRECTORY)

override fun doWork(): Result {
removeAudioCache()
removeAudioInCache(applicationContext)
return Result.success()
}

/*
/* for version higher or equal 1.2.6
remove .opus all opus in 'audios' cache directory
*/
*/
private fun removeAudioCache() {
val date = Date(System.currentTimeMillis())
audioDirectory.listFiles()?.forEach {
if (it.isFile
&& (it.name.substring(it.name.lastIndexOf(".") + 1) == "opus")
&& it.isLastModifiedOlderThan2Weeks(date)) {
try {
it.delete()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

/* for old version below 1.2.6
remove .opus all opus in main cache directory
*/
private fun removeAudioInCache(context: Context) {
val date = Date(System.currentTimeMillis())
context.cacheDir.listFiles()?.forEach {
if (it.isFile && it.isLastModifiedOlderThan2Weeks(date)) {
try {
it.delete()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

private fun File.isLastModifiedOlderThan2Weeks(date: Date): Boolean {
return (date.time - this.lastModified()) > TWO_WEEKS
}

companion object {
const val TWO_WEEKS: Long = 60 * 1000 * 60 * 24 * 14
private const val UNIQUE_WORK_KEY = "CleanupAudioCacheWorker"
const val AUDIOS_SUB_DIRECTORY = "audios"

fun enqueuePeriodically() {
val workRequest = PeriodicWorkRequestBuilder<CleanupAudioCacheWorker>(1, TimeUnit.DAYS).build()
WorkManager.getInstance().enqueueUniquePeriodicWork(UNIQUE_WORK_KEY, ExistingPeriodicWorkPolicy.REPLACE, workRequest)
}

fun workInfos(): LiveData<List<WorkInfo>> {
return WorkManager.getInstance().getWorkInfosForUniqueWorkLiveData(UNIQUE_WORK_KEY)
}
}
}
26 changes: 17 additions & 9 deletions app/src/main/java/org/rfcx/ranger/service/DownLoadEventWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import okio.sink
import org.rfcx.ranger.BuildConfig
import org.rfcx.ranger.data.local.EventDb
import org.rfcx.ranger.entity.event.Event
import org.rfcx.ranger.service.CleanupAudioCacheWorker.Companion.TWO_WEEKS
import org.rfcx.ranger.util.RealmHelper
import retrofit2.Call
import retrofit2.Response
Expand All @@ -21,25 +22,32 @@ import retrofit2.http.GET
import retrofit2.http.Url
import java.io.File
import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit

class DownLoadEventWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {

private val audioDirectory = File(context.cacheDir, AUDIOS_SUB_DIRECTORY)
private val needTobeDownloadEvent = arrayListOf<Event>()
override fun doWork(): Result {
Log.d(TAG, "doWork")

if (!audioDirectory.exists()) {
audioDirectory.mkdir()
}
val nowDate = Date(System.currentTimeMillis())
val eventDb = EventDb(Realm.getInstance(RealmHelper.migrationConfig()))
val events = eventDb.getEventsSync()
needTobeDownloadEvent.clear()
for (event in events) {
val file = File(applicationContext.cacheDir, "${event.audioId}.opus")
if (!file.exists()) {
needTobeDownloadEvent.add(event)
if ((nowDate.time - event.beginsAt.time) <= TWO_WEEKS) {
val file = File(audioDirectory, "${event.audioId}.opus")
if (!file.exists())
needTobeDownloadEvent.add(event)
} else {
break
}
}

startDownload()

return if (needTobeDownloadEvent.isNotEmpty()) Result.retry() else Result.success()
}

Expand Down Expand Up @@ -69,8 +77,8 @@ class DownLoadEventWorker(context: Context, workerParams: WorkerParameters) : Wo

private fun saveFile(context: Context, response: Response<ResponseBody>, fileName: String,
callback: (Boolean) -> Unit) {
val temp = File(context.cacheDir, "$fileName _temp")
val file = File(context.cacheDir, fileName)
val temp = File(audioDirectory, "$fileName _temp")
val file = File(audioDirectory, fileName)

if (file.exists()) {
callback.invoke(true)
Expand Down Expand Up @@ -106,7 +114,7 @@ class DownLoadEventWorker(context: Context, workerParams: WorkerParameters) : Wo
companion object {
private const val TAG = "DownLoadEventWorker"
private const val UNIQUE_WORK_KEY = "DownLoadEventWorkerUniqueKey"

const val AUDIOS_SUB_DIRECTORY = "audios"
fun enqueue() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/org/rfcx/ranger/util/CredentialKeeper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class CredentialKeeper(val context: Context) {
if (user.picture != null) {
preferences.putString(Preferences.IMAGE_PROFILE, user.picture)
}
if (user.consentGivenRangerApp != null) {
preferences.putBoolean(Preferences.CONSENT_GIVEN, true)
}
preferences.putStringSet(Preferences.ROLES, user.roles)
preferences.putStringSet(Preferences.ACCESSIBLE_SITES, user.accessibleSites)
if (user.defaultSite != null) {
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/java/org/rfcx/ranger/util/CredentialVerifier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class CredentialVerifier(val context: Context) {

// Parsing JWT Token
val metaDataKey = getString(R.string.auth0_metadata_key)
val userMetaDataKey = getString(R.string.auth0_user_metadata_key)
val withoutSignature = token.substring(0, token.lastIndexOf('.') + 1)
try {
val untrusted = Jwts.parser().parseClaimsJwt(withoutSignature)
Expand Down Expand Up @@ -64,12 +65,26 @@ class CredentialVerifier(val context: Context) {
}
}

val userUntrusted = Jwts.parser().parseClaimsJwt(withoutSignature)
var consentGivenRangerApp: String? = null

if (userUntrusted.body[userMetaDataKey] == null) {
consentGivenRangerApp = null
}

val userMetadata = userUntrusted.body[userMetaDataKey]
if (userMetadata != null) {
if ((userMetadata is HashMap<*, *>)) {
consentGivenRangerApp = userMetadata["consentGivenRangerApp"] as String?
}
}

when {
guid.isNullOrEmpty() -> {
return Err(getString(R.string.an_error_occurred))
}
else -> {
return Ok(UserAuthResponse(guid, email, nickname, token, credentials.accessToken, credentials.refreshToken, roles, accessibleSites, defaultSite, picture))
return Ok(UserAuthResponse(guid, email, nickname, token, credentials.accessToken, credentials.refreshToken, roles, accessibleSites, defaultSite, picture, consentGivenRangerApp))
}
}
} catch (e: Exception) {
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/rfcx/ranger/util/Preferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class Preferences(context: Context) {
const val IMAGE_PROFILE = "${PREFIX}IMAGE_PROFILE"
const val EMAIL_SUBSCRIBE = "${PREFIX}EMAIL_SUBSCRIBE"
const val COORDINATES_FORMAT = "${PREFIX}COORDINATES_FORMAT"
const val CONSENT_GIVEN = "${PREFIX}CONSENT_GIVEN"
const val IS_RANGER = "${PREFIX}IS_RANGER"
}

init {
Expand Down
Loading

0 comments on commit f04f939

Please sign in to comment.