Skip to content

Commit

Permalink
MBL-1171: Feature flag for OAuth (#1938)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkariang committed Jan 30, 2024
1 parent ebb2418 commit 62034f0
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 32 deletions.
2 changes: 0 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,6 @@ apollo {
}

repositories {
// This is the only reference we cannot remove yet as it has not been migrated to mavenCentral() or google()
// see - https://github.com/google/flexbox-layout/issues/566
maven {
url 'https://maven.google.com'
}
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@
android:parentActivityName=".ui.activities.LoginToutActivity"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Login" />
<activity
android:name=".ui.activities.OAuthActivity"
android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:scheme="ksrauth2"
android:host="authorize" />
</intent-filter>
</activity>
<activity
android:name=".ui.activities.LoginToutActivity"
android:parentActivityName=".ui.activities.DiscoveryActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ enum class FlagKey(val key: String) {
ANDROID_GOOGLE_ANALYTICS("android_google_analytics"),
ANDROID_PRE_LAUNCH_SCREEN("android_pre_launch_screen"),
ANDROID_DARK_MODE_ENABLED("android_dark_mode_enabled"),
ANDROID_POST_CAMPAIGN_PLEDGES("android_post_campaign_pledges")
ANDROID_POST_CAMPAIGN_PLEDGES("android_post_campaign_pledges"),
ANDROID_OAUTH("android_oauth")
}

fun FeatureFlagClient.getFetchInterval(): Long =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import com.kickstarter.ui.IntentKey
import com.kickstarter.ui.activities.CommentsActivity
import com.kickstarter.ui.activities.CreatorBioActivity
import com.kickstarter.ui.activities.LoginActivity
import com.kickstarter.ui.activities.OAuthActivity
import com.kickstarter.ui.activities.PaymentMethodsSettingsActivity
import com.kickstarter.ui.activities.PreLaunchProjectPageActivity
import com.kickstarter.ui.activities.ProjectPageActivity
import com.kickstarter.ui.activities.ProjectUpdatesActivity
import com.kickstarter.ui.activities.ReportProjectActivity
import com.kickstarter.ui.activities.ResetPasswordActivity
import com.kickstarter.ui.activities.SetPasswordActivity
import com.kickstarter.ui.activities.SignupActivity
import com.kickstarter.ui.activities.UpdateActivity
import com.kickstarter.ui.activities.VideoActivity
import com.kickstarter.ui.data.LoginReason
Expand All @@ -32,6 +34,20 @@ fun Intent.getPreLaunchProjectActivity(context: Context, slug: String?, project:
return intent
}

fun Intent.getStartLoginIntent(isOAuthEnabled: Boolean, context: Context): Intent {
return if (isOAuthEnabled)
this.setClass(context, OAuthActivity::class.java)
else
this.setClass(context, LoginActivity::class.java)
}

fun Intent.getSignupIntent(isOAuthEnabled: Boolean, context: Context): Intent {
return if (isOAuthEnabled)
this.setClass(context, OAuthActivity::class.java)
else
this.setClass(context, SignupActivity::class.java)
}

/**
* Retruns the Intent for start the PaymentMethodsSettigns activity
* @param context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import com.kickstarter.ui.compose.designsystem.KickstarterApp
import com.kickstarter.ui.data.ActivityResult.Companion.create
import com.kickstarter.ui.data.LoginReason
import com.kickstarter.ui.extensions.startDisclaimerChromeTab
import com.kickstarter.ui.extensions.startLogin
import com.kickstarter.ui.extensions.startSignup
import com.kickstarter.viewmodels.LoginToutViewModel
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
Expand Down Expand Up @@ -113,12 +115,16 @@ class LoginToutActivity : ComponentActivity() {

viewModel.outputs.startLoginActivity()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { startLogin() }
.subscribe {
this.startLogin(it)
}
.addToDisposable(disposables)

viewModel.outputs.startSignupActivity()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { startSignup() }
.subscribe {
this.startSignup(it)
}
.addToDisposable(disposables)

viewModel.outputs.startFacebookConfirmationActivity()
Expand Down Expand Up @@ -235,18 +241,6 @@ class LoginToutActivity : ComponentActivity() {
TransitionUtils.transition(this, TransitionUtils.fadeIn())
}

private fun startLogin() {
val intent = Intent(this, LoginActivity::class.java)
startActivityForResult(intent, ActivityRequestCodes.LOGIN_FLOW)
TransitionUtils.transition(this, TransitionUtils.fadeIn())
}

private fun startSignup() {
val intent = Intent(this, SignupActivity::class.java)
startActivityForResult(intent, ActivityRequestCodes.LOGIN_FLOW)
TransitionUtils.transition(this, TransitionUtils.fadeIn())
}

private fun startTwoFactorFacebookChallenge() {
val intent = Intent(this, TwoFactorActivity::class.java)
.putExtra(IntentKey.FACEBOOK_LOGIN, true)
Expand Down
24 changes: 24 additions & 0 deletions app/src/main/java/com/kickstarter/ui/activities/OAuthActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kickstarter.ui.activities

import android.os.Bundle
import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import com.kickstarter.ui.extensions.finishWithAnimation
import com.kickstarter.ui.extensions.setUpConnectivityStatusCheck

class OAuthActivity : AppCompatActivity() {

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

setUpConnectivityStatusCheck(lifecycle)

this.onBackPressedDispatcher.addCallback {
finishWithAnimation()
}

// TODO: Will continue work on https://kickstarter.atlassian.net/browse/MBL-1167
}
}
15 changes: 15 additions & 0 deletions app/src/main/java/com/kickstarter/ui/extensions/ActivityExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.lifecycle.Lifecycle
import com.google.android.play.core.review.ReviewInfo
import com.google.android.play.core.review.ReviewManagerFactory
import com.kickstarter.R
import com.kickstarter.libs.ActivityRequestCodes
import com.kickstarter.libs.Environment
import com.kickstarter.libs.utils.Secrets
import com.kickstarter.libs.utils.TransitionUtils
Expand All @@ -23,6 +24,8 @@ import com.kickstarter.libs.utils.extensions.getPreLaunchProjectActivity
import com.kickstarter.libs.utils.extensions.getProjectUpdatesActivityIntent
import com.kickstarter.libs.utils.extensions.getReportProjectActivityIntent
import com.kickstarter.libs.utils.extensions.getRootCommentsActivityIntent
import com.kickstarter.libs.utils.extensions.getSignupIntent
import com.kickstarter.libs.utils.extensions.getStartLoginIntent
import com.kickstarter.libs.utils.extensions.getUpdatesActivityIntent
import com.kickstarter.libs.utils.extensions.getVideoActivityIntent
import com.kickstarter.libs.utils.extensions.reduceToPreLaunchProject
Expand Down Expand Up @@ -230,6 +233,18 @@ fun Activity.startPreLaunchProjectActivity(project: Project, previousScreen: Str
TransitionUtils.transition(this, TransitionUtils.slideInFromRight())
}

fun Activity.startLogin(isOauthPathEnabled: Boolean) {
val intent = Intent().getStartLoginIntent(isOauthPathEnabled, this)
startActivityForResult(intent, ActivityRequestCodes.LOGIN_FLOW)
TransitionUtils.transition(this, TransitionUtils.fadeIn())
}

fun Activity.startSignup(isOauthPathEnabled: Boolean) {
val intent = Intent().getSignupIntent(isOauthPathEnabled, this)
startActivityForResult(intent, ActivityRequestCodes.LOGIN_FLOW)
TransitionUtils.transition(this, TransitionUtils.fadeIn())
}

fun Activity.startDisclaimerChromeTab(disclaimerItem: DisclaimerItems, environment: Environment?) {
val path = when (disclaimerItem) {
DisclaimerItems.TERMS -> HelpActivity.TERMS_OF_USE
Expand Down
24 changes: 13 additions & 11 deletions app/src/main/java/com/kickstarter/viewmodels/LoginToutViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ interface LoginToutViewModel {
fun startFacebookConfirmationActivity(): Observable<Pair<ErrorEnvelope.FacebookUser, String>>

/** Emits when the login activity should be started. */
fun startLoginActivity(): Observable<Unit>
fun startLoginActivity(): Observable<Boolean>

/** Emits when the signup activity should be started. */
fun startSignupActivity(): Observable<Unit>
fun startSignupActivity(): Observable<Boolean>

/** Emits when a user has successfully logged in using Facebook, but has require two-factor authentication enabled. */
fun startTwoFactorChallenge(): Observable<Unit>
Expand Down Expand Up @@ -139,14 +139,14 @@ interface LoginToutViewModel {
@VisibleForTesting
val facebookAccessToken = PublishSubject.create<String>()
private val facebookLoginClick = PublishSubject.create<List<String>>()
private val loginClick = PublishSubject.create<Unit>()
private val loginClick = PublishSubject.create<Boolean>()
private val onResetPasswordFacebookErrorDialogClicked = PublishSubject.create<Unit>()
private val onLoginFacebookErrorDialogClicked = PublishSubject.create<Unit>()

@VisibleForTesting
val loginError = PublishSubject.create<ErrorEnvelope?>()
private val loginReason = PublishSubject.create<LoginReason>()
private val signupClick = PublishSubject.create<Unit>()
private val signupClick = PublishSubject.create<Boolean>()
private val disclaimerItemClicked = PublishSubject.create<DisclaimerItems>()

@VisibleForTesting
Expand All @@ -155,8 +155,8 @@ interface LoginToutViewModel {
private val showFacebookErrorDialog = BehaviorSubject.create<Unit>()
private val startResetPasswordActivity = BehaviorSubject.create<Unit>()
private val startFacebookConfirmationActivity: Observable<Pair<ErrorEnvelope.FacebookUser, String>>
private val startLoginActivity: Observable<Unit>
private val startSignupActivity: Observable<Unit>
private val startLoginActivity: Observable<Boolean>
private val startSignupActivity: Observable<Boolean>
private val showDisclaimerActivity: Observable<DisclaimerItems>

val inputs: Inputs = this
Expand Down Expand Up @@ -185,11 +185,11 @@ interface LoginToutViewModel {
}

override fun loginClick() {
loginClick.onNext(Unit)
loginClick.onNext(environment.featureFlagClient()?.getBoolean(FlagKey.ANDROID_OAUTH) ?: false)
}

override fun signupClick() {
signupClick.onNext(Unit)
signupClick.onNext(environment.featureFlagClient()?.getBoolean(FlagKey.ANDROID_OAUTH) ?: false)
}

override fun disclaimerItemClicked(disclaimerItem: DisclaimerItems) {
Expand Down Expand Up @@ -231,11 +231,11 @@ interface LoginToutViewModel {
return startFacebookConfirmationActivity
}

override fun startLoginActivity(): Observable<Unit> {
override fun startLoginActivity(): Observable<Boolean> {
return startLoginActivity
}

override fun startSignupActivity(): Observable<Unit> {
override fun startSignupActivity(): Observable<Boolean> {
return startSignupActivity
}

Expand Down Expand Up @@ -335,7 +335,9 @@ interface LoginToutViewModel {
.addToDisposable(disposables)

onLoginFacebookErrorDialogClicked
.subscribe { startLoginActivity.onNext(Unit) }
.subscribe {
startLoginActivity.onNext((environment.featureFlagClient()?.getBoolean(FlagKey.ANDROID_OAUTH) ?: false))
}
.addToDisposable(disposables)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,28 @@ class IntentExtTest : KSRobolectricTestCase() {
assertEquals(intent.component?.className, "com.kickstarter.ui.activities.SetPasswordActivity")
assertEquals(intent.extras?.get(IntentKey.EMAIL), "test@kickstarter.com")
}

@Test
fun testStartLoginIntent() {

// - Simulates feature flag off
val intentOldFlow = Intent().getStartLoginIntent(isOAuthEnabled = false, context())
assertEquals(intentOldFlow.component?.className, "com.kickstarter.ui.activities.LoginActivity")

// - Simulates feature flag on
val intentNewFlow = Intent().getStartLoginIntent(isOAuthEnabled = true, context())
assertEquals(intentNewFlow.component?.className, "com.kickstarter.ui.activities.OAuthActivity")
}

@Test
fun testStartSignupIntent() {

// - Simulates feature flag off
val intentOldFlow = Intent().getSignupIntent(isOAuthEnabled = false, context())
assertEquals(intentOldFlow.component?.className, "com.kickstarter.ui.activities.SignupActivity")

// - Simulates feature flag on
val intentNewFlow = Intent().getSignupIntent(isOAuthEnabled = true, context())
assertEquals(intentNewFlow.component?.className, "com.kickstarter.ui.activities.OAuthActivity")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class LoginToutViewModelTest : KSRobolectricTestCase() {
private lateinit var vm: LoginToutViewModel.LoginToutViewmodel
private val finishWithSuccessfulResult = TestSubscriber<Unit>()
private val loginError = TestSubscriber<ErrorEnvelope>()
private val startLoginActivity = TestSubscriber<Unit>()
private val startSignupActivity = TestSubscriber<Unit>()
private val startLoginActivity = TestSubscriber<Boolean>()
private val startSignupActivity = TestSubscriber<Boolean>()
private val currentUser = TestSubscriber<User?>()
private val showDisclaimerActivity = TestSubscriber<DisclaimerItems>()
private val startResetPasswordActivity = TestSubscriber<Unit>()
Expand Down Expand Up @@ -55,25 +55,70 @@ class LoginToutViewModelTest : KSRobolectricTestCase() {
}

@Test
fun testLoginButtonClicked() {
fun testLoginButtonClicked_when_FFOff() {
setUpEnvironment(environment(), LoginReason.DEFAULT)

startLoginActivity.assertNoValues()

vm.inputs.loginClick()

startLoginActivity.assertValueCount(1)
startLoginActivity.assertValue(false)
segmentTrack.assertValues(EventName.PAGE_VIEWED.eventName, EventName.CTA_CLICKED.eventName)
}

@Test
fun testSignupButtonClicked() {
fun testLoginButtonClicked_when_FFOn() {
val environment = environment()
.toBuilder()
.featureFlagClient(object : MockFeatureFlagClient() {
override fun getBoolean(FlagKey: FlagKey): Boolean {
return true
}
})
.build()

setUpEnvironment(environment, LoginReason.DEFAULT)

startLoginActivity.assertNoValues()

vm.inputs.loginClick()

startLoginActivity.assertValueCount(1)
startLoginActivity.assertValue(true)
segmentTrack.assertValues(EventName.PAGE_VIEWED.eventName, EventName.CTA_CLICKED.eventName)
}

@Test
fun testSignupButtonClicked_when_FFOff() {
setUpEnvironment(environment(), LoginReason.DEFAULT)
startSignupActivity.assertNoValues()

vm.inputs.signupClick()

startSignupActivity.assertValueCount(1)
startSignupActivity.assertValue(false)
segmentTrack.assertValues(EventName.PAGE_VIEWED.eventName, EventName.CTA_CLICKED.eventName)
}

@Test
fun testSignupButtonClicked_when_FFOn() {
val environment = environment()
.toBuilder()
.featureFlagClient(object : MockFeatureFlagClient() {
override fun getBoolean(FlagKey: FlagKey): Boolean {
return true
}
})
.build()

setUpEnvironment(environment, LoginReason.DEFAULT)
startSignupActivity.assertNoValues()

vm.inputs.signupClick()

startSignupActivity.assertValueCount(1)
startSignupActivity.assertValue(true)
segmentTrack.assertValues(EventName.PAGE_VIEWED.eventName, EventName.CTA_CLICKED.eventName)
}

Expand Down

0 comments on commit 62034f0

Please sign in to comment.