Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b752891 authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

Browser: Allow Re-OAuth from notification

parent f3c57df5
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -35,10 +35,11 @@ import at.bitfire.davdroid.ui.account.AccountSettingsActivity
import dagger.assisted.Assisted
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dagger.assisted.AssistedInject
import foundation.e.accountmanager.AccountTypes
import foundation.e.accountmanager.AccountTypes
import foundation.e.accountmanager.ui.setup.ReOAuthActivity
import foundation.e.accountmanager.utils.AccountHelper
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.runInterruptible
import java.io.IOException
import java.io.IOException
import java.io.InterruptedIOException
import java.util.logging.Level
import java.util.logging.Level
import java.util.logging.Logger
import java.util.logging.Logger
import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.cancellation.CancellationException
@@ -188,10 +189,17 @@ class RefreshCollectionsWorker @AssistedInject constructor(
        } catch (e: UnauthorizedException) {
        } catch (e: UnauthorizedException) {
            logger.log(Level.SEVERE, "Not authorized (anymore)", e)
            logger.log(Level.SEVERE, "Not authorized (anymore)", e)
            // notify that we need to re-authenticate in the account settings
            // notify that we need to re-authenticate in the account settings
            val settingsIntent = Intent(applicationContext, AccountSettingsActivity::class.java)
            val isOidcAccount = AccountHelper.isOidcAccount(applicationContext, account)
                .putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account)
            val (settingsIntent, notificationMessage) = if (isOidcAccount) {
                Intent(applicationContext, ReOAuthActivity::class.java) to
                        applicationContext.getString(R.string.sync_error_authentication_oauth)
            } else {
                Intent(applicationContext, AccountSettingsActivity::class.java) to
                        applicationContext.getString(R.string.sync_error_authentication_failed)
            }
            settingsIntent.putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account)
            notifyRefreshError(
            notifyRefreshError(
                applicationContext.getString(R.string.sync_error_authentication_failed),
                notificationMessage,
                settingsIntent
                settingsIntent
            )
            )
            return Result.failure()
            return Result.failure()
+6 −1
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import at.bitfire.davdroid.resource.SyncState
import at.bitfire.davdroid.sync.account.InvalidAccountException
import at.bitfire.davdroid.sync.account.InvalidAccountException
import at.bitfire.synctools.storage.LocalStorageException
import at.bitfire.synctools.storage.LocalStorageException
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.accountmanager.utils.AccountHelper
import foundation.e.accountmanager.utils.SystemUtils
import foundation.e.accountmanager.utils.SystemUtils
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.coroutineScope
@@ -779,7 +780,11 @@ abstract class SyncManager<LocalType: LocalResource, out CollectionType: LocalCo
                if (isNetworkAvailable) {
                if (isNetworkAvailable) {
                    syncResult.numAuthExceptions++
                    syncResult.numAuthExceptions++
                }
                }
                message = context.getString(R.string.sync_error_authentication_failed)
                message = if (AccountHelper.isOidcAccount(context, account)) {
                    context.getString(R.string.sync_error_authentication_oauth)
                } else {
                    context.getString(R.string.sync_error_authentication_failed)
                }
            }
            }


            is HttpException, is DavException -> {
            is HttpException, is DavException -> {
+7 −1
Original line number Original line Diff line number Diff line
@@ -27,6 +27,8 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.accountmanager.ui.setup.ReOAuthActivity
import foundation.e.accountmanager.utils.AccountHelper
import okhttp3.HttpUrl
import okhttp3.HttpUrl
import java.io.IOException
import java.io.IOException
import java.util.logging.Level
import java.util.logging.Level
@@ -116,7 +118,11 @@ class SyncNotificationManager @AssistedInject constructor(
    ) = notificationRegistry.notifyIfPossible(NotificationRegistry.NOTIFY_SYNC_ERROR, tag = notificationTag) {
    ) = notificationRegistry.notifyIfPossible(NotificationRegistry.NOTIFY_SYNC_ERROR, tag = notificationTag) {
        val contentIntent: Intent
        val contentIntent: Intent
        if (e is UnauthorizedException) {
        if (e is UnauthorizedException) {
            contentIntent = Intent(context, AccountSettingsActivity::class.java)
            contentIntent = if (AccountHelper.isOidcAccount(context, account)) {
                Intent(context, ReOAuthActivity::class.java)
            } else {
                Intent(context, AccountSettingsActivity::class.java)
            }
            contentIntent.putExtra(
            contentIntent.putExtra(
                AccountSettingsActivity.EXTRA_ACCOUNT,
                AccountSettingsActivity.EXTRA_ACCOUNT,
                account
                account
+96 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2025 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 *
 */
package foundation.e.accountmanager.ui.setup

import android.accounts.Account
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.glance.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import at.bitfire.davdroid.ui.AppTheme
import at.bitfire.davdroid.ui.account.AccountSettingsActivity
import at.bitfire.davdroid.ui.account.AccountSettingsModel
import dagger.hilt.android.AndroidEntryPoint
import foundation.e.accountmanager.utils.AccountHelper

@AndroidEntryPoint
class ReOAuthActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Retrieve the Account from the Intent
        val account: Account? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            intent.getParcelableExtra(AccountSettingsActivity.EXTRA_ACCOUNT, Account::class.java)
        } else {
            @Suppress("DEPRECATION")
            intent.getParcelableExtra(AccountSettingsActivity.EXTRA_ACCOUNT)
        }

        setContent {
            AppTheme {
                if (account != null) {
                    OAuthHandlerScreen(
                        account = account,
                        onFinished = { finish() }
                    )
                } else {
                    finish()
                }
            }
        }
    }
}

@Composable
fun OAuthHandlerScreen(
    account: Account,
    onFinished: () -> Unit,
) {
    val context = LocalContext.current
    val model = hiltViewModel { factory: AccountSettingsModel.Factory ->
        factory.create(account)
    }

    val authRequestContract = rememberLauncherForActivityResult(model.authorizationContract()) { authResponse ->
        if (authResponse != null) {
            model.authenticate(authResponse)

            // Sync after authenticated
            AccountHelper.scheduleSyncWithDelay(context)
        } else {
            model.authCodeFailed()
        }
        onFinished()
    }

    // Auto-launch immediately, no UI shown
    LaunchedEffect(Unit) {
        val request = model.newAuthorizationRequest()
        if (request != null) {
            authRequestContract.launch(request)
        } else {
            onFinished()
        }
    }
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -34,4 +34,6 @@
    <string name="privacy_policy_title_nav">"Privacy Policy"</string>
    <string name="privacy_policy_title_nav">"Privacy Policy"</string>
    <string name="navigation_drawer_open_webcalmanager">Web Calendar Manager</string>
    <string name="navigation_drawer_open_webcalmanager">Web Calendar Manager</string>
    <string name="legacy_murena_login">Legacy Murena.io</string>
    <string name="legacy_murena_login">Legacy Murena.io</string>

    <string name="sync_error_authentication_oauth">Authentication issue. Tap to sign in again</string>
</resources>
</resources>
Loading