Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api "com.iterable:iterableapi:3.5.2"
// api project(":iterableapi") // links to local android SDK repo rather than by release
api "com.iterable:iterableapi:3.5.10"
// api project(":iterableapi") // links to local android SDK repo rather than by release
}

4 changes: 2 additions & 2 deletions android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.modules.core.RCTNativeAppEventEmitter;
import com.iterable.iterableapi.AuthFailure;
import com.iterable.iterableapi.InboxSessionManager;
import com.iterable.iterableapi.IterableAction;
import com.iterable.iterableapi.IterableActionContext;
Expand Down Expand Up @@ -109,7 +110,7 @@ public void initializeWithApiKey(String apiKey, ReadableMap configReadableMap, S
@ReactMethod
public void setEmail(@Nullable String email) {
IterableLogger.d(TAG, "setEmail: " + email);

IterableApi.getInstance().setEmail(email);
}

Expand Down Expand Up @@ -154,7 +155,7 @@ public void setUserId(@Nullable String userId) {
@ReactMethod
public void setUserId(@Nullable String userId, @Nullable String authToken) {
IterableLogger.d(TAG, "setUserId: " + userId + " authToken: " + authToken);

IterableApi.getInstance().setUserId(userId, authToken);
}

Expand Down Expand Up @@ -596,12 +597,23 @@ public void onTokenRegistrationSuccessful(String authToken) {
sendEvent(EventName.handleAuthSuccessCalled.name(), null);
}

@Override
public void onTokenRegistrationFailed(Throwable object) {
IterableLogger.v(TAG, "Failed to set authToken");
sendEvent(EventName.handleAuthFailureCalled.name(), null);
@Override
public void onAuthFailure(AuthFailure authFailure) {

JSONObject messageJson = new JSONObject();
try {
messageJson.put("userKey", authFailure.userKey);
messageJson.put("failedAuthToken", authFailure.failedAuthToken);
messageJson.put("failedRequestTime", authFailure.failedRequestTime);
messageJson.put("failureReason", authFailure.failureReason.name());
WritableMap eventData = Serialization.convertJsonToMap(messageJson);
sendEvent(EventName.handleAuthFailureCalled.name(), eventData);
} catch (JSONException e) {
IterableLogger.v(TAG, "Failed to set authToken");
}

}

@ReactMethod
public void addListener(String eventName) {
// Keep: Required for RN built in Event Emitter Calls.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,6 @@ static IterableConfig.Builder getConfigFromReadableMap(ReadableMap iterableConte

configBuilder.setDataRegion(iterableDataRegion);
}

if (iterableContextJSON.has("encryptionEnforced")) {
configBuilder.setEncryptionEnforced(iterableContextJSON.optBoolean("encryptionEnforced"));
}

return configBuilder;
} catch (JSONException e) {
Expand Down
10 changes: 10 additions & 0 deletions example/src/hooks/useIterableApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {

import { Route } from '../constants/routes';
import type { RootStackParamList } from '../types/navigation';
import type { IterableAuthFailure } from '../../../src/core';

type Navigation = StackNavigationProp<RootStackParamList>;

Expand Down Expand Up @@ -149,6 +150,15 @@ export const IterableAppProvider: FunctionComponent<

config.inAppHandler = () => IterableInAppShowResponse.show;

config.authHandler = () => {
console.log('!!!Auth is being requested!!! and app is going to pass null');
return Promise.resolve({authToken:"SomethingNotValid"});
Comment on lines +154 to +155
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace '!!!Auth·is·being·requested!!!·and·app·is·going·to·pass·null' with ⏎··········'!!!Auth·is·being·requested!!!·and·app·is·going·to·pass·null'⏎········ [eslint:prettier/prettier]

Suggested change
console.log('!!!Auth is being requested!!! and app is going to pass null');
return Promise.resolve({authToken:"SomethingNotValid"});
console.log(
'!!!Auth is being requested!!! and app is going to pass null'
);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace authToken:"SomethingNotValid" with ·authToken:·'SomethingNotValid'· [eslint:prettier/prettier]

Suggested change
return Promise.resolve({authToken:"SomethingNotValid"});
return Promise.resolve({ authToken: 'SomethingNotValid' });

}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insert ; [eslint:prettier/prettier]

Suggested change
}
};


config.onJWTError = (err: IterableAuthFailure) => {
console.log('!!!JWT Error!!! '+ err.failureReason.toString(), err);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insert · [eslint:prettier/prettier]

Suggested change
console.log('!!!JWT Error!!! '+ err.failureReason.toString(), err);
console.log('!!!JWT Error!!! ' + err.failureReason.toString(), err);

}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insert ; [eslint:prettier/prettier]

Suggested change
}
};


setItblConfig(config);

const key = apiKey ?? process.env.ITBL_API_KEY;
Expand Down
16 changes: 15 additions & 1 deletion src/core/classes/Iterable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type { IterableCommerceItem } from './IterableCommerceItem';
import { IterableConfig } from './IterableConfig';
import { IterableLogger } from './IterableLogger';
import { RNIterableAPI } from './RNIterableAPI';
import type { IterableAuthFailure } from '../types';

const RNEventEmitter = new NativeEventEmitter(RNIterableAPI);

Expand Down Expand Up @@ -952,12 +953,16 @@ export class Iterable {
RNEventEmitter.addListener(IterableEventName.handleAuthCalled, () => {
// MOB-10423: Check if we can use chain operator (?.) here instead


Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete [eslint:prettier/prettier]

//This is where RN SDK asks front end of the client/app to pass authToken
Iterable.savedConfig.authHandler!()
.then((promiseResult) => {
// Promise result can be either just String OR of type AuthResponse.
// If type AuthReponse, authToken will be parsed looking for `authToken` within promised object. Two additional listeners will be registered for success and failure callbacks sent by native bridge layer.
// Else it will be looked for as a String.
if (typeof promiseResult === typeof new IterableAuthResponse()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete [eslint:prettier/prettier]


// Set authToken at bridge layer
RNIterableAPI.passAlongAuthToken(
(promiseResult as IterableAuthResponse).authToken
);
Expand All @@ -972,6 +977,9 @@ export class Iterable {
} else if (
authResponseCallback === IterableAuthResponseResult.FAILURE
) {
// We are currently only reporting JWT related errors. In
// the future, we should handle other types of errors as
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
// the future, we should handle other types of errors as
// the future, we should handle other types of errors as

// well.
if ((promiseResult as IterableAuthResponse).failureCallback) {
(promiseResult as IterableAuthResponse).failureCallback?.();
}
Expand All @@ -997,10 +1005,16 @@ export class Iterable {
authResponseCallback = IterableAuthResponseResult.SUCCESS;
}
);

RNEventEmitter.addListener(
IterableEventName.handleAuthFailureCalled,
() => {
(authFailureResponse: IterableAuthFailure) => {
// This line will just mark the flag for above listener to indicate something failed
// catch(err) will only indicate failure on high level. No actions should be taken inside catch(err)
authResponseCallback = IterableAuthResponseResult.FAILURE;

// This line will call the actual JWT error with authFailure objec
Iterable.savedConfig?.onJWTError?.(authFailureResponse);
}
);
}
Expand Down
13 changes: 11 additions & 2 deletions src/core/classes/IterableConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { IterableAction } from './IterableAction';
import type { IterableActionContext } from './IterableActionContext';
import type { IterableAuthResponse } from './IterableAuthResponse';

import type { IterableAuthFailure } from '../types/IterableAuthFailure';
/**
* An IterableConfig object sets various properties of the SDK.
*
Expand Down Expand Up @@ -203,7 +203,16 @@ export class IterableConfig {
* @returns A promise that resolves to an `IterableAuthResponse`, a `string`,
* or `undefined`.
*/
authHandler?: () => Promise<IterableAuthResponse | string | undefined>;
authHandler?: () => Promise<IterableAuthResponse | string | IterableAuthFailure | undefined>;

Comment on lines +206 to +207
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace IterableAuthResponse·|·string·|·IterableAuthFailure·|·undefined with ⏎····IterableAuthResponse·|·string·|·IterableAuthFailure·|·undefined⏎·· [eslint:prettier/prettier]

Suggested change
authHandler?: () => Promise<IterableAuthResponse | string | IterableAuthFailure | undefined>;
authHandler?: () => Promise<
IterableAuthResponse | string | IterableAuthFailure | undefined
>;

/**
* A callback function that is called when the SDK encounters an error while
* validing the JWT.
*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
*
*

* The retry for JWT should be automatically handled by the native SDK, so
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
* The retry for JWT should be automatically handled by the native SDK, so
* The retry for JWT should be automatically handled by the native SDK, so

* this is just for logging/transparency purposes.
*/
onJWTError?: (authFailure: IterableAuthFailure) => void;

/**
* Set the verbosity of Android and iOS project's log system.
Expand Down
39 changes: 39 additions & 0 deletions src/core/enums/IterableAuthFailureReason.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

* The reason for the failure of an authentication attempt.
*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
*
*

* This is generally related to JWT token validation.
*/
export enum IterableAuthFailureReason {
/**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
/**
/**

* An auth token's expiration must be less than one year from its issued-at
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
* An auth token's expiration must be less than one year from its issued-at
* An auth token's expiration must be less than one year from its issued-at

* time.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
* time.
* time.

*/
AUTH_TOKEN_EXPIRATION_INVALID,
/** The token has expired. */
AUTH_TOKEN_EXPIRED,
/** Token has an invalid format (failed a regular expression check). */
AUTH_TOKEN_FORMAT_INVALID,
/** `onAuthTokenRequested` threw an exception. */
AUTH_TOKEN_GENERATION_ERROR,
/** Any other error not captured by another constant. */
AUTH_TOKEN_GENERIC_ERROR,
/** Iterable has invalidated this token and it cannot be used. */
AUTH_TOKEN_INVALIDATED,
/** The request to Iterable's API did not include a JWT authorization header. */
AUTH_TOKEN_MISSING,
/** `onAuthTokenRequested` returned a null JWT token. */
AUTH_TOKEN_NULL,
/**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
/**
/**

* Iterable could not decode the token's payload (`iat`, `exp`, `email`,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
* Iterable could not decode the token's payload (`iat`, `exp`, `email`,
* Iterable could not decode the token's payload (`iat`, `exp`, `email`,

* or `userId`).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
* or `userId`).
* or `userId`).

*/
AUTH_TOKEN_PAYLOAD_INVALID,
/** Iterable could not validate the token's authenticity. */
AUTH_TOKEN_SIGNATURE_INVALID,
/**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
/**
/**

* The token doesn't include an `email` or a `userId`. Or, one of these
* values is included, but it references a user that isn't in the Iterable
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete · [eslint:prettier/prettier]

Suggested change
* values is included, but it references a user that isn't in the Iterable
* values is included, but it references a user that isn't in the Iterable

* project.
*/
AUTH_TOKEN_USER_KEY_INVALID,
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insert [eslint:prettier/prettier]

18 changes: 18 additions & 0 deletions src/core/types/IterableAuthFailure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { IterableAuthFailureReason } from "../enums/IterableAuthFailureReason";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 issues:

1. Replace "../enums/IterableAuthFailureReason" with '../enums/IterableAuthFailureReason' [eslint:prettier/prettier]


2. Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Suggested change
import type { IterableAuthFailureReason } from "../enums/IterableAuthFailureReason";
import type { IterableAuthFailureReason } from '../enums/IterableAuthFailureReason';


/**
* Represents an auth failure object.
*/
export interface IterableAuthFailure {
/** userId or email of the signed-in user */
userKey: string;

/** the authToken which caused the failure */
failedAuthToken: string;

/** the timestamp of the failed request */
failedRequestTime: number;

/** indicates a reason for failure */
failureReason: IterableAuthFailureReason;
}
1 change: 1 addition & 0 deletions src/core/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './IterableEdgeInsetDetails';
export * from './IterableAuthFailure';