Skip to content

Commit f29d0df

Browse files
committed
Add UNAUTHORIZED handling to OperationRepo and operation executors
1 parent bf759d2 commit f29d0df

File tree

8 files changed

+74
-23
lines changed

8 files changed

+74
-23
lines changed

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/IOperationRepo.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ interface IOperationRepo {
4242
suspend fun awaitInitialized()
4343

4444
fun forceExecuteOperations()
45+
46+
fun setPaused(paused: Boolean)
4547
}
4648

4749
// Extension function so the syntax containsInstanceOf<Operation>() can be used over

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationRepo.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ internal class OperationRepo(
189189
waiter.wake(LoopWaiterMessage(false))
190190
}
191191

192+
override fun setPaused(paused: Boolean) {
193+
this.paused = paused
194+
}
195+
192196
/**
193197
* Waits until a new operation is enqueued, then wait an additional
194198
* amount of time afterwards, so operations can be grouped/batched.
@@ -262,7 +266,15 @@ internal class OperationRepo(
262266
ops.forEach { _operationModelStore.remove(it.operation.id) }
263267
ops.forEach { it.waiter?.wake(true) }
264268
}
265-
ExecutionResult.FAIL_UNAUTHORIZED, // TODO: Need to provide callback for app to reset JWT. For now, fail with no retry.
269+
ExecutionResult.FAIL_UNAUTHORIZED -> {
270+
Logging.error("Operation execution failed with invalid jwt, pausing the operation repo: $operations")
271+
// keep the failed operation and pause the operation repo from executing
272+
paused = true
273+
// add back all operations to the front of the queue to be re-executed.
274+
synchronized(queue) {
275+
ops.reversed().forEach { queue.add(0, it) }
276+
}
277+
}
266278
ExecutionResult.FAIL_NORETRY,
267279
ExecutionResult.FAIL_CONFLICT,
268280
-> {

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/IdentityOperationExecutor.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ internal class IdentityOperationExecutor(
4545

4646
if (lastOperation is SetAliasOperation) {
4747
try {
48+
val identityAlias = _identityModelStore.getIdentityAlias()
4849
_identityBackend.setAlias(
4950
lastOperation.appId,
50-
IdentityConstants.ONESIGNAL_ID,
51-
lastOperation.onesignalId,
51+
identityAlias.first,
52+
identityAlias.second,
5253
mapOf(lastOperation.label to lastOperation.value),
54+
_identityModelStore.model.jwtToken,
5355
)
5456

5557
// ensure the now created alias is in the model as long as the user is still current.
@@ -66,8 +68,10 @@ internal class IdentityOperationExecutor(
6668
ExecutionResponse(ExecutionResult.FAIL_NORETRY)
6769
NetworkUtils.ResponseStatusType.CONFLICT ->
6870
ExecutionResponse(ExecutionResult.FAIL_CONFLICT, retryAfterSeconds = ex.retryAfterSeconds)
69-
NetworkUtils.ResponseStatusType.UNAUTHORIZED ->
70-
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED, retryAfterSeconds = ex.retryAfterSeconds)
71+
NetworkUtils.ResponseStatusType.UNAUTHORIZED -> {
72+
_identityModelStore.invalidateJwt()
73+
return ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED)
74+
}
7175
NetworkUtils.ResponseStatusType.MISSING -> {
7276
if (ex.statusCode == 404 && _newRecordState.isInMissingRetryWindow(lastOperation.onesignalId)) {
7377
return ExecutionResponse(ExecutionResult.FAIL_RETRY, retryAfterSeconds = ex.retryAfterSeconds)
@@ -93,6 +97,7 @@ internal class IdentityOperationExecutor(
9397
IdentityConstants.ONESIGNAL_ID,
9498
lastOperation.onesignalId,
9599
lastOperation.label,
100+
_identityModelStore.model.jwtToken,
96101
)
97102

98103
// ensure the now deleted alias is not in the model as long as the user is still current.
@@ -110,8 +115,10 @@ internal class IdentityOperationExecutor(
110115
ExecutionResponse(ExecutionResult.SUCCESS)
111116
NetworkUtils.ResponseStatusType.INVALID ->
112117
ExecutionResponse(ExecutionResult.FAIL_NORETRY)
113-
NetworkUtils.ResponseStatusType.UNAUTHORIZED ->
114-
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED, retryAfterSeconds = ex.retryAfterSeconds)
118+
NetworkUtils.ResponseStatusType.UNAUTHORIZED -> {
119+
_identityModelStore.invalidateJwt()
120+
return ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED)
121+
}
115122
NetworkUtils.ResponseStatusType.MISSING -> {
116123
return if (ex.statusCode == 404 && _newRecordState.isInMissingRetryWindow(lastOperation.onesignalId)) {
117124
ExecutionResponse(ExecutionResult.FAIL_RETRY, retryAfterSeconds = ex.retryAfterSeconds)

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/LoginUserFromSubscriptionOperationExecutor.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ internal class LoginUserFromSubscriptionOperationExecutor(
4646
_subscriptionBackend.getIdentityFromSubscription(
4747
loginUserOp.appId,
4848
loginUserOp.subscriptionId,
49+
_identityModelStore.model.jwtToken,
4950
)
5051
val backendOneSignalId = identities.getOrDefault(IdentityConstants.ONESIGNAL_ID, null)
5152

@@ -82,8 +83,10 @@ internal class LoginUserFromSubscriptionOperationExecutor(
8283
return when (responseType) {
8384
NetworkUtils.ResponseStatusType.RETRYABLE ->
8485
ExecutionResponse(ExecutionResult.FAIL_RETRY)
85-
NetworkUtils.ResponseStatusType.UNAUTHORIZED ->
86+
NetworkUtils.ResponseStatusType.UNAUTHORIZED -> {
87+
_identityModelStore.invalidateJwt()
8688
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED)
89+
}
8790
else ->
8891
ExecutionResponse(ExecutionResult.FAIL_NORETRY)
8992
}

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/LoginUserOperationExecutor.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ internal class LoginUserOperationExecutor(
126126
)
127127
createUser(loginUserOp, operations)
128128
}
129+
ExecutionResult.FAIL_UNAUTHORIZED -> {
130+
_identityModelStore.invalidateJwt()
131+
ExecutionResponse(result.result)
132+
}
129133
else -> ExecutionResponse(result.result)
130134
}
131135
}
@@ -212,8 +216,10 @@ internal class LoginUserOperationExecutor(
212216
return when (responseType) {
213217
NetworkUtils.ResponseStatusType.RETRYABLE ->
214218
ExecutionResponse(ExecutionResult.FAIL_RETRY, retryAfterSeconds = ex.retryAfterSeconds)
215-
NetworkUtils.ResponseStatusType.UNAUTHORIZED ->
216-
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED, retryAfterSeconds = ex.retryAfterSeconds)
219+
NetworkUtils.ResponseStatusType.UNAUTHORIZED -> {
220+
_identityModelStore.invalidateJwt()
221+
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED)
222+
}
217223
else ->
218224
ExecutionResponse(ExecutionResult.FAIL_PAUSE_OPREPO)
219225
}

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/RefreshUserOperationExecutor.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ internal class RefreshUserOperationExecutor(
5353

5454
private suspend fun getUser(op: RefreshUserOperation): ExecutionResponse {
5555
try {
56-
val alias = _identityModelStore.getIdentityAlias()
56+
val identityAlias = _identityModelStore.getIdentityAlias()
5757
val response =
5858
_userBackend.getUser(
5959
op.appId,
60-
alias.first,
61-
alias.second,
60+
identityAlias.first,
61+
identityAlias.second,
6262
_identityModelStore.model.jwtToken,
6363
)
6464

@@ -70,6 +70,7 @@ internal class RefreshUserOperationExecutor(
7070
for (aliasKVP in response.identities) {
7171
identityModel[aliasKVP.key] = aliasKVP.value
7272
}
73+
identityModel.jwtToken = _identityModelStore.model.jwtToken
7374

7475
val propertiesModel = PropertiesModel()
7576
propertiesModel.onesignalId = op.onesignalId

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.onesignal.user.internal.backend.IdentityConstants
2525
import com.onesignal.user.internal.backend.SubscriptionObject
2626
import com.onesignal.user.internal.backend.SubscriptionObjectType
2727
import com.onesignal.user.internal.builduser.IRebuildUserService
28+
import com.onesignal.user.internal.identity.IdentityModelStore
2829
import com.onesignal.user.internal.operations.CreateSubscriptionOperation
2930
import com.onesignal.user.internal.operations.DeleteSubscriptionOperation
3031
import com.onesignal.user.internal.operations.TransferSubscriptionOperation
@@ -38,6 +39,7 @@ internal class SubscriptionOperationExecutor(
3839
private val _subscriptionBackend: ISubscriptionBackendService,
3940
private val _deviceService: IDeviceService,
4041
private val _applicationService: IApplicationService,
42+
private val _identityModelStore: IdentityModelStore,
4143
private val _subscriptionModelStore: SubscriptionModelStore,
4244
private val _configModelStore: ConfigModelStore,
4345
private val _buildUserService: IRebuildUserService,
@@ -105,12 +107,14 @@ internal class SubscriptionOperationExecutor(
105107
AndroidUtils.getAppVersion(_applicationService.appContext),
106108
)
107109

110+
val identityAlias = _identityModelStore.getIdentityAlias()
108111
val result =
109112
_subscriptionBackend.createSubscription(
110113
createOperation.appId,
111-
IdentityConstants.ONESIGNAL_ID,
112-
createOperation.onesignalId,
114+
identityAlias.first,
115+
identityAlias.second,
113116
subscription,
117+
_identityModelStore.model.jwtToken,
114118
) ?: return ExecutionResponse(ExecutionResult.SUCCESS)
115119

116120
val backendSubscriptionId = result.first
@@ -148,8 +152,10 @@ internal class SubscriptionOperationExecutor(
148152
NetworkUtils.ResponseStatusType.INVALID,
149153
->
150154
ExecutionResponse(ExecutionResult.FAIL_NORETRY)
151-
NetworkUtils.ResponseStatusType.UNAUTHORIZED ->
155+
NetworkUtils.ResponseStatusType.UNAUTHORIZED -> {
156+
_identityModelStore.invalidateJwt()
152157
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED, retryAfterSeconds = ex.retryAfterSeconds)
158+
}
153159
NetworkUtils.ResponseStatusType.MISSING -> {
154160
if (ex.statusCode == 404 && _newRecordState.isInMissingRetryWindow(createOperation.onesignalId)) {
155161
return ExecutionResponse(ExecutionResult.FAIL_RETRY, retryAfterSeconds = ex.retryAfterSeconds)
@@ -247,6 +253,7 @@ internal class SubscriptionOperationExecutor(
247253
startingOperation.subscriptionId,
248254
IdentityConstants.ONESIGNAL_ID,
249255
startingOperation.onesignalId,
256+
_identityModelStore.model.jwtToken,
250257
)
251258
} catch (ex: BackendException) {
252259
val responseType = NetworkUtils.getResponseStatusType(ex.statusCode)
@@ -278,7 +285,7 @@ internal class SubscriptionOperationExecutor(
278285

279286
private suspend fun deleteSubscription(op: DeleteSubscriptionOperation): ExecutionResponse {
280287
try {
281-
_subscriptionBackend.deleteSubscription(op.appId, op.subscriptionId)
288+
_subscriptionBackend.deleteSubscription(op.appId, op.subscriptionId, _identityModelStore.model.jwtToken)
282289

283290
// remove the subscription model as a HYDRATE in case for some reason it still exists.
284291
_subscriptionModelStore.remove(op.subscriptionId, ModelChangeTags.HYDRATE)

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import com.onesignal.core.internal.operations.Operation
1313
import com.onesignal.debug.LogLevel
1414
import com.onesignal.debug.internal.logging.Logging
1515
import com.onesignal.user.internal.backend.IUserBackendService
16-
import com.onesignal.user.internal.backend.IdentityConstants
1716
import com.onesignal.user.internal.backend.PropertiesDeltasObject
1817
import com.onesignal.user.internal.backend.PropertiesObject
1918
import com.onesignal.user.internal.backend.PurchaseObject
@@ -88,7 +87,12 @@ internal class UpdateUserOperationExecutor(
8887
val sessionCount = if (deltasObject.sessionCount != null) deltasObject.sessionCount!! + 1 else 1
8988

9089
deltasObject =
91-
PropertiesDeltasObject(deltasObject.sessionTime, sessionCount, deltasObject.amountSpent, deltasObject.purchases)
90+
PropertiesDeltasObject(
91+
deltasObject.sessionTime,
92+
sessionCount,
93+
deltasObject.amountSpent,
94+
deltasObject.purchases,
95+
)
9296
refreshDeviceMetadata = true
9397
}
9498
is TrackSessionEndOperation -> {
@@ -107,7 +111,12 @@ internal class UpdateUserOperationExecutor(
107111
}
108112

109113
deltasObject =
110-
PropertiesDeltasObject(sessionTime, deltasObject.sessionCount, deltasObject.amountSpent, deltasObject.purchases)
114+
PropertiesDeltasObject(
115+
sessionTime,
116+
deltasObject.sessionCount,
117+
deltasObject.amountSpent,
118+
deltasObject.purchases,
119+
)
111120
}
112121
is TrackPurchaseOperation -> {
113122
if (appId == null) {
@@ -138,14 +147,16 @@ internal class UpdateUserOperationExecutor(
138147

139148
if (appId != null && onesignalId != null) {
140149
try {
150+
val identityAlias = _identityModelStore.getIdentityAlias()
141151
val rywData =
142152
_userBackend.updateUser(
143153
appId,
144-
IdentityConstants.ONESIGNAL_ID,
145-
onesignalId,
154+
identityAlias.first,
155+
identityAlias.second,
146156
propertiesObject,
147157
refreshDeviceMetadata,
148158
deltasObject,
159+
_identityModelStore.model.jwtToken,
149160
)
150161

151162
if (rywData != null) {
@@ -185,8 +196,10 @@ internal class UpdateUserOperationExecutor(
185196
return when (responseType) {
186197
NetworkUtils.ResponseStatusType.RETRYABLE ->
187198
ExecutionResponse(ExecutionResult.FAIL_RETRY, retryAfterSeconds = ex.retryAfterSeconds)
188-
NetworkUtils.ResponseStatusType.UNAUTHORIZED ->
199+
NetworkUtils.ResponseStatusType.UNAUTHORIZED -> {
200+
_identityModelStore.invalidateJwt()
189201
ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED, retryAfterSeconds = ex.retryAfterSeconds)
202+
}
190203
NetworkUtils.ResponseStatusType.MISSING -> {
191204
if (ex.statusCode == 404 && _newRecordState.isInMissingRetryWindow(onesignalId)) {
192205
return ExecutionResponse(ExecutionResult.FAIL_RETRY, retryAfterSeconds = ex.retryAfterSeconds)

0 commit comments

Comments
 (0)