-
Notifications
You must be signed in to change notification settings - Fork 377
feat(iv): Handle logout and fetch IAMs (6/6) #2634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/iv-public-api-05
Are you sure you want to change the base?
Changes from all commits
21b9ae8
9767011
dc93995
207caf3
c49f6b5
6ef0d14
1f82d61
1351fc1
d38940c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package com.onesignal.user.internal | ||
|
|
||
| import com.onesignal.core.internal.config.ConfigModel | ||
| import com.onesignal.user.internal.subscriptions.SubscriptionModelStore | ||
|
|
||
| /** | ||
| * IV-specific behavior for [LogoutHelper]. The base-class call site dispatches via | ||
| * `if (newCodePathsRun) switchUserIv(...) else legacyLogout()`; this extension | ||
| * internally short-circuits on `ivBehaviorActive` to keep Phase 3 users (new code path on, | ||
| * IV behavior off) on the legacy logout flow. | ||
| */ | ||
|
|
||
| /** | ||
| * Performs the IV-aware logout user-switch when [ivBehaviorActive] is true. | ||
| * | ||
| * Order matters and is intentional (mirrors reference branches #2599 and #2613): | ||
| * 1. Set `isDisabledInternally = true` on the CURRENT push subscription with the default | ||
| * NORMAL tag. This propagates through [com.onesignal.user.internal.operations.impl.listeners.SubscriptionModelStoreListener.getUpdateOperation], | ||
| * which reads the still-current OLD identity and enqueues an `UpdateSubscriptionOperation` | ||
| * carrying `(enabled = false, status = UNSUBSCRIBE)` — letting the backend know this device's | ||
| * push subscription is unsubscribing as the user logs out. The OLD user's JWT is still valid | ||
| * here, so the op dispatches successfully. | ||
| * 2. Switch to the new device-scoped (anonymous) user via | ||
| * [UserSwitcher.createAndSwitchToNewUser] with `suppressBackendOperation = true` so the | ||
| * subscription replacement does NOT propagate to listeners — the new anonymous user has no | ||
| * JWT and any create-subscription op for it would 401 indefinitely. | ||
| * | ||
| * Returns `true` when IV-specific handling was applied (caller skips legacy enqueue), | ||
| * or `false` when IV behavior is inactive (caller falls through to the legacy logout). | ||
| */ | ||
| internal fun switchUserIv( | ||
| userSwitcher: UserSwitcher, | ||
| subscriptionModelStore: SubscriptionModelStore, | ||
| configModel: ConfigModel, | ||
| ivBehaviorActive: Boolean, | ||
| ): Boolean { | ||
| if (!ivBehaviorActive) return false | ||
|
|
||
| configModel.pushSubscriptionId?.let { pushSubId -> | ||
| subscriptionModelStore.get(pushSubId)?.let { it.isDisabledInternally = true } | ||
| } | ||
| userSwitcher.createAndSwitchToNewUser(suppressBackendOperation = true) | ||
| return true | ||
|
Comment on lines
+37
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 The Extended reasoning...Two bugs from one misplaced line
configModel.pushSubscriptionId?.let { pushSubId ->
subscriptionModelStore.get(pushSubId)?.let { it.isDisabledInternally = true } // (A)
}
userSwitcher.createAndSwitchToNewUser(suppressBackendOperation = true) // (B)The Bug 1 — fires an UpdateSubscriptionOperation against the OLD user on every IV logoutThe change propagates This contradicts the file's own docstring, which states the flag exists "to prevent the model-store listener from generating create-subscription ops that would 401". On every IV logout it actually generates an unsubscribe op for the user being logged out — the OLD user's JWT is still in Bug 2 — the flag never lands on the new anonymous userImmediately after (A), step (B) calls val newPushSubscription = SubscriptionModel().apply {
id = currentPushSubscription?.id ?: idManager.createLocalId()
type = SubscriptionType.PUSH
optedIn = currentPushSubscription?.optedIn ?: true
address = currentPushSubscription?.address ?: ""
status = currentPushSubscription?.status ?: SubscriptionStatus.NO_PERMISSION
sdk = oneSignalUtils.sdkVersion
deviceOS = this@UserSwitcher.deviceOS ?: ""
carrier = carrierName ?: ""
appVersion = androidUtils.getAppVersion(appContextProvider()) ?: ""
}
// ...
subscriptionModelStore.clear(ModelChangeTags.NO_PROPOGATE)
// ...
subscriptionModelStore.replaceAll(subscriptions, ModelChangeTags.NO_PROPOGATE)The new Step-by-step proofStarting state: user logged in with
How to fixTwo complementary changes:
Both verifiers (4 on bug_003, 3 on bug_004) confirmed the chain end-to-end; one verifier on bug_004 noted the practical 401 impact is mitigated by
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nan-li to look at this |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please make this lazy