Skip to content

Commit

Permalink
Added feature to do logout
Browse files Browse the repository at this point in the history
  • Loading branch information
this-Aditya committed Dec 11, 2024
1 parent 43167a1 commit cb9cfcc
Show file tree
Hide file tree
Showing 19 changed files with 197 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ class ApplicationStatusManager(
override fun onClose() {
applicationStatusExecutor.stop {
this.processor.stop()
tzProcessor?.stop()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.google.firebase.analytics.FirebaseAnalytics
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
Expand All @@ -48,6 +49,7 @@ import org.radarbase.android.auth.AuthService
import org.radarbase.android.auth.AuthServiceStateReactor
import org.radarbase.android.auth.LoginListener
import org.radarbase.android.auth.LoginManager
import org.radarbase.android.splash.SplashActivity
import org.radarbase.android.util.BindState
import org.radarbase.android.util.BluetoothEnforcer
import org.radarbase.android.util.CoroutineTaskExecutor
Expand All @@ -57,6 +59,7 @@ import org.radarbase.android.util.PermissionBroadcast
import org.radarbase.android.util.PermissionHandler
import org.radarbase.kotlin.coroutines.launchJoin
import org.slf4j.LoggerFactory
import java.io.File
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds

Expand Down Expand Up @@ -373,22 +376,67 @@ abstract class MainActivity : AppCompatActivity(), LoginListener {
* still valid.
*/
protected suspend fun logout(disableRefresh: Boolean) {
logger.trace("NewBroadcastTrace: now performing logout from superclass")
authConnection.applyBinder { invalidate(null, disableRefresh) }
radarConfig.resetConfig()
clearAppData(this)
logger.debug("Disabling Firebase Analytics")
FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(false)
}

override fun loginSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit

override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) {
override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) {
logger.trace("NewBroadcastTrace: Starting splash 1")
delay(1000)
logger.trace("NewBroadcastTrace: Starting splash 2")
logger.info("Starting SplashActivity")
val intent = packageManager.getLaunchIntentForPackage(BuildConfig.LIBRARY_PACKAGE_NAME) ?: return
startActivity(intent.apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
})
finish()
try {
val intent = packageManager.getLaunchIntentForPackage(packageName)
intent ?: return
startActivity(intent.apply {
flags =
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
})
logger.trace("NewBroadcastTrace: Started splash and now finishing")
finish()
logger.trace("NewBroadcastTrace: Started splash and now finished")
} catch (ex: Exception) {
logger.trace("NewBroadcastTrace: Exception when starting splash: $ex")
} finally {
logger.info("NewBroadcastTrace: Logout succeeded method completed")
}
}

private fun clearAppData(context: Context) {
clearCache(context)
clearFilesDir(context)
}

private fun clearFilesDir(context: Context) {
val filesDir = context.filesDir
deleteFilesInDirectory(filesDir)
}

private fun clearCache(context: Context) {
val cacheDir = context.cacheDir
deleteFilesInDirectory(cacheDir)
}

private fun deleteFilesInDirectory(directory: File) {
if (directory.isDirectory) {
val children = directory.listFiles()
if (children != null) {
for (child in children) {
if (child.absolutePath.toString().contains("firebase")) return
deleteFilesInDirectory(child)
}
}
}
directory.delete()
}


companion object {
private val logger = LoggerFactory.getLogger(MainActivity::class.java)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@ interface RadarConfiguration {
*/
suspend fun forceFetch()

suspend fun resetConfig()

/**
* Adds base URL from auth state to configuration.
*/
suspend fun updateWithAuthState(context: Context, appAuthState: AppAuthState?)
suspend fun updateWithAuthState(context: Context, appAuthState: AppAuthState?, isLogoutCall: Boolean = false)

companion object {
const val RADAR_CONFIGURATION_CHANGED = "org.radarcns.android.RadarConfiguration.CHANGED"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ import org.radarbase.android.kafka.ServerStatusListener
import org.radarbase.android.kafka.TopicSendReceipt
import org.radarbase.android.source.*
import org.radarbase.android.util.*
import org.radarbase.android.util.BluetoothEnforcer.Companion
import org.radarbase.android.util.ManagedServiceConnection.Companion.serviceConnection
import org.radarbase.android.util.NotificationHandler.Companion.NOTIFICATION_CHANNEL_INFO
import org.radarbase.android.util.PermissionHandler.Companion.isPermissionGranted
Expand Down Expand Up @@ -238,9 +237,6 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis
launch {
configuration.config.collect(::configure)
}
launch {

}
}

bluetoothReceiver = BluetoothStateReceiver(this) { enabled ->
Expand Down Expand Up @@ -306,6 +302,8 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis
it.close()
sourceRegistrar = null
}
(dataHandler as TableDataHandler).stop()
dataHandler = null
}
recordTrackerJob?.cancel()
statusTrackerJob?.cancel()
Expand Down Expand Up @@ -596,7 +594,18 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis
}
}

override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit
override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) {
radarExecutor.execute {
updateProviders(authState, configuration.latestConfig)
val oldProviders = mConnections
removeProviders(mConnections.toSet())
oldProviders.forEach {
it.stopService()
}
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}
}

private fun removeProviders(sourceProviders: Set<SourceProvider<*>>) {
if (sourceProviders.isEmpty()) {
Expand Down Expand Up @@ -770,8 +779,6 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis
private val logger = LoggerFactory.getLogger(RadarService::class.java)
private const val RADAR_PACKAGE = "org.radarbase.android"

const val ACTION_PROVIDERS_UPDATED = "$RADAR_PACKAGE.ACTION_PROVIDERS_UPDATED"

const val ACTION_CHECK_PERMISSIONS = "$RADAR_PACKAGE.ACTION_CHECK_PERMISSIONS"
const val EXTRA_PERMISSIONS = "$RADAR_PACKAGE.EXTRA_PERMISSIONS"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ abstract class AuthService : LifecycleService(), LoginListener {
private val serviceMutex: Mutex = Mutex(false)
private val registryTweakMutex: Mutex = Mutex(false)
private val authUpdateMutex: Mutex = Mutex(false)
private var shouldUpdateAuth: AtomicBoolean = AtomicBoolean(true)

private var needLoadedState: AtomicBoolean = AtomicBoolean(true)

Expand Down Expand Up @@ -99,6 +100,7 @@ abstract class AuthService : LifecycleService(), LoginListener {
override fun onCreate() {
super.onCreate()

shouldUpdateAuth = AtomicBoolean(true)
networkConnectedListener = NetworkConnectedReceiver(this)

executor.start()
Expand Down Expand Up @@ -135,8 +137,10 @@ abstract class AuthService : LifecycleService(), LoginListener {
authState
.collectLatest { state ->
logger.trace("Collected AppAuth: {}", state)
radarConfig.updateWithAuthState(this@AuthService, state)
}
if (shouldUpdateAuth.get()) {
radarConfig.updateWithAuthState(this@AuthService, state)
}
}
}
launch(Dispatchers.Default) {
networkConnectedListener.monitor()
Expand Down Expand Up @@ -185,6 +189,20 @@ abstract class AuthService : LifecycleService(), LoginListener {
}
}
}
launch(Dispatchers.Default) {
authStateLogout
.collectLatest {
logger.info("Logout succeeded")
shouldUpdateAuth = AtomicBoolean(false)
val clearedState = latestAppAuth.reset()
_authState.value = clearedState
authSerialization.remove()
callListeners {
it.listener.logoutSucceeded(null, clearedState)
}
radarConfig.updateWithAuthState(this@AuthService, clearedState, true)
}
}
}
}
}
Expand Down Expand Up @@ -235,6 +253,10 @@ abstract class AuthService : LifecycleService(), LoginListener {
suspend fun refreshIfOnline() {
executor.execute {
logger.debug("Refreshing if online")
if (!shouldUpdateAuth.get()) {
logger.debug("Performing logout aborting refresh")
return@execute
}
for (i in 1..3) {
if (!isNetworkStatusReceived) {
delay(100)
Expand Down Expand Up @@ -345,7 +367,7 @@ abstract class AuthService : LifecycleService(), LoginListener {
_authState.value = authState
}

override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) {
override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) {
lifecycleScope.launch {
_authStateLogout.emit(AuthLoginListener.AuthStateLogout(manager, authState))
}
Expand Down Expand Up @@ -405,6 +427,7 @@ abstract class AuthService : LifecycleService(), LoginListener {

suspend fun invalidate(token: String?, disableRefresh: Boolean) {
executor.execute {
logger.trace("NewBroadcastTrace: Invalidating auth state")
updateState { auth ->
logger.info("Invalidating authentication state")
if (token != null && token != auth.token) return@updateState
Expand Down Expand Up @@ -476,6 +499,7 @@ abstract class AuthService : LifecycleService(), LoginListener {

override fun onBind(intent: Intent): IBinder? {
super.onBind(intent)
shouldUpdateAuth = AtomicBoolean(true)
return AuthServiceBinder()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ abstract class LoginActivity : AppCompatActivity(), LoginListener {
finish()
}

override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit

companion object {
private val logger = LoggerFactory.getLogger(LoginActivity::class.java)
const val ACTION_LOGIN = "org.radarcns.auth.LoginActivity.login"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ interface LoginListener {
*/
fun loginFailed(manager: LoginManager?, ex: Exception?)

fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState)
suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState)
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class ManagementPortalLoginManager(
if (authState.authenticationSource != SOURCE_TYPE) return
if (disableRefresh) {
authState.clear()
listener.logoutSucceeded(this@ManagementPortalLoginManager, AppAuthState())
} else authState.invalidate()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class AppConfigRadarConfiguration(
}
}

override suspend fun doFetch(maxCacheAge: Long) {
override suspend fun doFetch(maxCacheAgeMillis: Long) {
val (client, appConfig) = configMutex.withLock {
Pair(client, appConfig)
}
Expand Down Expand Up @@ -175,6 +175,11 @@ class AppConfigRadarConfiguration(
}
}

override suspend fun reset() {
status.value = RadarConfiguration.RemoteConfigStatus.INITIAL
auth = null
}

private suspend fun updateConfiguration(auth: AppAuthState?, config: SingleRadarConfiguration?) {
val appConfig = config?.let { value ->
val serverConfig = value.optString(BASE_URL_KEY) { baseUrl ->
Expand Down
Loading

0 comments on commit cb9cfcc

Please sign in to comment.