-
Notifications
You must be signed in to change notification settings - Fork 375
feat: identity verification 5.8 #2599
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: main
Are you sure you want to change the base?
Changes from all commits
33c5300
faaa927
82cb67f
316fedd
3c044d4
aed18a4
1d85f7f
2120f4f
f539cb9
59215a3
82b5341
b4d2e5d
e67ca19
7d93fa7
0966ae8
0125f76
436ba14
8c047f9
83523a2
ef1a424
771255f
37e1dff
9d1ad8f
765114b
1846e87
fc594b1
3e3086c
26de8e5
aff605b
d07e5c4
8b460e7
c57b0fa
16ce7f6
6844c1f
2f43ff9
cdc61b8
258c8e6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package com.onesignal | ||
|
|
||
| /** | ||
| * Implement this interface and provide an instance to [OneSignal.addUserJwtInvalidatedListener] | ||
| * to be notified when the JWT for a user is invalidated. | ||
| * | ||
| * Callbacks are delivered on a background thread. | ||
| */ | ||
| interface IUserJwtInvalidatedListener { | ||
| /** | ||
| * Called when the JWT is invalidated for [UserJwtInvalidatedEvent.externalId]. | ||
| * Invoked on a background thread; see [IUserJwtInvalidatedListener] class documentation. | ||
| * | ||
| * @param event Describes which user's JWT was invalidated. | ||
| */ | ||
| fun onUserJwtInvalidated(event: UserJwtInvalidatedEvent) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.onesignal | ||
|
|
||
| /** | ||
| * The event passed into [IUserJwtInvalidatedListener.onUserJwtInvalidated]. Delivery occurs on | ||
| * a background thread; see [IUserJwtInvalidatedListener]. | ||
| */ | ||
| class UserJwtInvalidatedEvent( | ||
| val externalId: String, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| package com.onesignal.core.internal.config.impl | ||
|
|
||
| import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler | ||
| import com.onesignal.common.modeling.ModelChangeTags | ||
| import com.onesignal.common.modeling.ModelChangedArgs | ||
| import com.onesignal.core.internal.config.ConfigModel | ||
| import com.onesignal.core.internal.config.ConfigModelStore | ||
| import com.onesignal.core.internal.operations.IOperationRepo | ||
| import com.onesignal.core.internal.startup.IStartableService | ||
| import com.onesignal.debug.internal.logging.Logging | ||
| import com.onesignal.user.internal.UserManager | ||
| import com.onesignal.user.internal.identity.IdentityModelStore | ||
| import com.onesignal.user.internal.identity.JwtTokenStore | ||
|
|
||
| /** | ||
| * Reacts to the identity-verification remote param arriving via config HYDRATE. | ||
| * | ||
| * - When IV transitions from unknown (null) to true: purges anonymous operations. | ||
| * - When IV transitions from unknown (null) to any value: wakes the operation queue. | ||
| * - On beta migration: if IV=true and the current user has an externalId but no JWT, | ||
| * fires [UserJwtInvalidatedEvent] so the developer provides a fresh token. | ||
| */ | ||
| internal class IdentityVerificationService( | ||
| private val _configModelStore: ConfigModelStore, | ||
| private val _operationRepo: IOperationRepo, | ||
| private val _identityModelStore: IdentityModelStore, | ||
| private val _jwtTokenStore: JwtTokenStore, | ||
| private val _userManager: UserManager, | ||
| ) : IStartableService, ISingletonModelStoreChangeHandler<ConfigModel> { | ||
| override fun start() { | ||
| _configModelStore.subscribe(this) | ||
|
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. can this be in a background thread?
Contributor
Author
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. it follows the pattern of other subscribing services like InAppMessagesManager.kt start, and the |
||
| _operationRepo.setJwtInvalidatedHandler { externalId -> | ||
| _userManager.fireJwtInvalidated(externalId) | ||
| } | ||
| } | ||
|
|
||
| override fun onModelReplaced( | ||
| model: ConfigModel, | ||
| tag: String, | ||
| ) { | ||
| if (tag != ModelChangeTags.HYDRATE) return | ||
|
|
||
| val useIV = model.useIdentityVerification | ||
|
|
||
| var jwtInvalidatedExternalId: String? = null | ||
| if (useIV == true) { | ||
| Logging.debug("IdentityVerificationService: IV enabled, purging anonymous operations") | ||
| _operationRepo.removeOperationsWithoutExternalId() | ||
|
|
||
| val externalId = _identityModelStore.model.externalId | ||
| if (externalId != null && _jwtTokenStore.getJwt(externalId) == null) { | ||
| Logging.debug("IdentityVerificationService: IV enabled but no JWT for $externalId, will fire invalidated event after queue wake") | ||
| jwtInvalidatedExternalId = externalId | ||
| } | ||
| } | ||
|
|
||
| _operationRepo.forceExecuteOperations() | ||
|
|
||
| jwtInvalidatedExternalId?.let { _userManager.fireJwtInvalidated(it) } | ||
| } | ||
|
|
||
| override fun onModelUpdated( | ||
| args: ModelChangedArgs, | ||
| tag: String, | ||
| ) { | ||
| // Individual property updates are not expected for remote params; | ||
| // ConfigModelStoreListener replaces the entire model on HYDRATE. | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,18 @@ abstract class Operation(name: String) : Model() { | |
| setStringProperty(::name.name, value) | ||
| } | ||
|
|
||
| /** | ||
| * The external ID of the user this operation belongs to. Used by [IOperationRepo] to look up | ||
| * the correct JWT when identity verification is enabled, and to gate anonymous operations. | ||
| * Stamped automatically by [IOperationRepo] at enqueue time from the current identity model | ||
| * when not already set by the concrete operation's constructor. | ||
| */ | ||
| var externalId: String? | ||
|
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. how do we indicate this to be JWT, can we do a better naming?
Contributor
Author
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. This is the externalId of the user the operation belongs to, I'm not sure I understand your question. While it is relevant for Identity Verification, the term |
||
| get() = getOptStringProperty(::externalId.name) | ||
| set(value) { | ||
| setOptStringProperty(::externalId.name, value) | ||
| } | ||
|
|
||
| init { | ||
| this.name = name | ||
| } | ||
|
|
@@ -49,6 +61,13 @@ abstract class Operation(name: String) : Model() { | |
| */ | ||
| abstract val canStartExecute: Boolean | ||
|
|
||
| /** | ||
| * Whether this operation requires a valid JWT when identity verification is enabled. | ||
| * Override to return `false` for operations whose backend endpoint does not require | ||
| * a JWT (e.g. subscription updates). | ||
| */ | ||
| open val requiresJwt: Boolean get() = true | ||
|
|
||
| /** | ||
| * Called when an operation has resolved a local ID to a backend ID (i.e. successfully | ||
| * created a backend resource). Any IDs within the operation that could be local IDs should | ||
|
|
||
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.
like i mentioned elsewhere, we need suspend methods for these
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.
added