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

Verified Commit 8765ad5e authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

feat: Add support for Murena SSO migration

- Introduces `SsoMigrationReceiver` to handle broadcasted intents related to Murena SSO migration status.
- Creates `MurenaSsoMigrationPreferences` to track the migration's progress.
- Prevents account addition or removal during migration.
- Adds utility `StringUtils` for string manipulation.
- Adjusts `AccountUtils` to compare account names before the "@" symbol.
- Defines `MURENA_SSO_MIGRATION` permission.
parent a6196853
Loading
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@
    <permission android:name="foundation.e.permission.ADD_ACCOUNT"
        android:protectionLevel="signature" />

    <permission android:name="foundation.e.permission.MURENA_SSO_MIGRATION"
        android:protectionLevel="signature" />

    <application
        android:name=".EdriveApplication"
        android:allowBackup="true"
@@ -121,6 +124,15 @@
            </intent-filter>
        </receiver>

        <receiver android:name=".murenasso.SsoMigrationReceiver"
            android:enabled="true"
            android:permission="foundation.e.permission.MURENA_SSO_MIGRATION"
            android:exported="true">
            <intent-filter>
                <action android:name="foundation.e.drive.action.MURENA_SSO_MIGRATION"/>
            </intent-filter>
        </receiver>

        <service android:name="androidx.work.impl.foreground.SystemForegroundService"
            android:foregroundServiceType="dataSync"
            tools:node="merge" />
+3 −1
Original line number Diff line number Diff line
@@ -66,7 +66,9 @@ object AccountUtils {
        val accountType = context.getString(R.string.eelo_account_type)

        return accountManager.getAccountsByType(accountType)
            .firstOrNull { account -> account.name == accountName }
            .firstOrNull { account ->
                account.name.substringBefore("@") == accountName.substringBefore("@")
            }
    }

    @JvmStatic
+6 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import foundation.e.drive.account.AccountAdder
import foundation.e.drive.murenasso.MurenaSsoMigrationPreferences
import timber.log.Timber

/**
@@ -35,6 +36,11 @@ class AccountAddedReceiver : BroadcastReceiver() {

        if (context == null || intent == null || intent.extras == null) return

        if (MurenaSsoMigrationPreferences.isSsoMigrationRunning(context)) {
            Timber.i("Murena SSO migration is running, skipping account addition.")
            return
        }

        val extras = intent.extras!!
        val accountName = extras.getString(AccountManager.KEY_ACCOUNT_NAME, "")
        val accountType = extras.getString(AccountManager.KEY_ACCOUNT_TYPE, "")
+10 −2
Original line number Diff line number Diff line
@@ -29,7 +29,9 @@ import androidx.annotation.NonNull;

import foundation.e.drive.R;
import foundation.e.drive.account.AccountRemover;
import foundation.e.drive.murenasso.MurenaSsoMigrationPreferences;
import foundation.e.drive.utils.AppConstants;
import foundation.e.drive.utils.StringUtils;
import foundation.e.drive.utils.ViewUtils;
import timber.log.Timber;

@@ -62,14 +64,20 @@ public class AccountRemoveCallbackReceiver extends BroadcastReceiver {
            return false;
        }

        String currentAccount = preferences.getString(AccountManager.KEY_ACCOUNT_NAME, "");
        String currentAccountType = context.getString(R.string.eelo_account_type);
        final String currentAccount = StringUtils.substringBefore(preferences.getString(AccountManager.KEY_ACCOUNT_NAME,
                ""), "@"); // abc@example.com -> abc
        final String currentAccountType = context.getString(R.string.eelo_account_type);

        if (currentAccount.isEmpty()) {
            Timber.d("No account set up, ignoring account removal");
            return false;
        }

        if (MurenaSsoMigrationPreferences.isSsoMigrationRunning(context)) {
            Timber.i("Murena SSO migration is running, skipping account removal.");
            return false;
        }

        final String accountType = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
        final String accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);

+50 −0
Original line number 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.drive.murenasso

import android.content.Context
import androidx.core.content.edit
import foundation.e.drive.murenasso.MurenaSsoMigrationPreferences.MigrationStatus.Completed
import foundation.e.drive.murenasso.MurenaSsoMigrationPreferences.MigrationStatus.InProgress

object MurenaSsoMigrationPreferences {

    private const val PREFERENCES_NAME = "edrive_sso_migration"
    private const val KEY_IS_SSO_MIGRATION_RUNNING = "is_sso_migration_running"

    @JvmStatic
    fun isSsoMigrationRunning(context: Context): Boolean {
        val preferences = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
        return preferences.getBoolean(KEY_IS_SSO_MIGRATION_RUNNING, false)
    }

    @JvmStatic
    fun updateSsoMigrationStatus(context: Context, status: MigrationStatus) {
        val preferences =
            context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
        when (status) {
            InProgress -> preferences.edit() { putBoolean(KEY_IS_SSO_MIGRATION_RUNNING, true) }
            Completed -> preferences.edit() { putBoolean(KEY_IS_SSO_MIGRATION_RUNNING, false) }
        }
    }

    enum class MigrationStatus {
        InProgress,
        Completed
    }
}
Loading