MOB-2426: Bug fixed and enhancements#11
Conversation
…le optional options parameter in Android triggerAction
There was a problem hiding this comment.
Pull request overview
Updates the React Native wrapper to align with TransmitSecurity Account Protection SDK 3.0.0, expanding the public JS API (session token, page-load logging, richer trigger actions) and updating the example + docs accordingly.
Changes:
- Upgraded native dependencies to AccountProtection 3.0.0 (iOS CocoaPods + Android Gradle).
- Expanded JS/native bridge APIs:
initializeIOS(...)w/ config + userId,setAuthenticatedUser(...), enhancedtriggerAction(...), plusgetSessionToken()andlogPageLoad(...). - Updated example app and documentation to reflect new initialization requirements (
/risk-collect/) and behavioral tracking guidance (testID).
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/index.tsx | Adds new TS types/enums and updates exported JS API signatures (init/config, user, triggerAction, session token, page load). |
| react-native-ts-accountprotection.podspec | Bumps iOS native dependency AccountProtection to 3.0.0. |
| ios/TsAccountprotection.swift | Implements updated iOS bridge methods and new APIs (session token, page-load logging, location config, claimed user id type). |
| ios/TsAccountprotection.mm | Updates Objective-C extern declarations to match new Swift bridge signatures. |
| android/src/main/java/com/tsaccountprotection/TsAccountprotectionModule.kt | Updates Android bridge methods to new APIs and adds session token/page-load/location/customAttributes support. |
| android/build.gradle | Pins Android SDK dependency to com.ts.sdk:accountprotection:3.0.0. |
| android/src/main/res/values/strings.xml | Removes placeholder credential strings from the library resources. |
| example/src/App.tsx | Updates example usage to new init/user/session/triggerAction APIs and adds extra demo data. |
| example/src/screens/login.tsx | Logs page load on mount; adds testID to login button. |
| example/src/screens/authenticated-user.tsx | Logs page load on mount; tweaks default demo values. |
| example/src/config.ts | Updates example baseUrl to include /risk-collect/ and fixes trailing semicolon. |
| example/android/app/build.gradle | Updates example Android dependency to 3.0.0. |
| example/android/app/src/main/java/com/tsaccountprotectionexample/MainApplication.kt | Keeps Android SDK init in onCreate (minor formatting changes). |
| example/android/app/src/main/res/values/strings.xml | Adds example app credential/baseUrl strings with /risk-collect/. |
| example/ios/TransmitSecurity.plist | Updates example plist baseUrl to /risk-collect/ and sets a clientId placeholder. |
| example/ios/Podfile.lock | Updates pods lockfile to AccountProtection 3.0.0 and wrapper version. |
| example/ios/TsAccountprotectionExample.xcodeproj/project.pbxproj | Updates CocoaPods integration references/build phases for the example project. |
| README.md | Updates integration docs for 3.0.0 APIs/config, adds behavioral tracking guidance and new API docs. |
| RELEASE_NOTES.md | Adds a 3.0.0 release entry summarizing API changes and breaking changes. |
| MIGRATION_0.1.9-0.2.0.md | Extends migration guide with new APIs and initialization/action option changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| export interface TSLocationConfig { | ||
| mode: 'disabled' | 'default' | 'forceCurrent' | 'forceLastKnown' | 'lastKnown'; | ||
| validFor?: number | null | undefined; // return last-known only if it is not older than `validFor` minutes. |
There was a problem hiding this comment.
validFor?: number | null | undefined is redundant because an optional property already covers undefined. Prefer validFor?: number | null (or just validFor?: number) to keep the public type surface simpler.
| validFor?: number | null | undefined; // return last-known only if it is not older than `validFor` minutes. | |
| validFor?: number | null; // return last-known only if it is not older than `validFor` minutes. |
| @@ -4,12 +4,17 @@ import { SafeAreaView, Keyboard, Alert, Platform } from 'react-native'; | |||
|
|
|||
| import { | |||
| initializeSDKIOS, | |||
There was a problem hiding this comment.
initializeSDKIOS is imported but not used (the only reference is commented out). With noUnusedLocals enabled in the repo tsconfig, this will fail yarn typecheck; remove the import or use it (e.g., behind a platform/feature flag).
| initializeSDKIOS, |
| func initializeIOS( | ||
| _ clientId: String, | ||
| baseUrl: String, | ||
| configuration: [String: Any]?, | ||
| userId: String?, | ||
| resolve: @escaping RCTPromiseResolveBlock, | ||
| reject: @escaping RCTPromiseRejectBlock) -> Void { | ||
| runBlockOnMain { | ||
| var nativeConfiguration: AccountProtection.TSInitSDKConfiguration? | ||
|
|
||
| if let config = configuration { | ||
| let enableTrackingBehavioralData = config["enableTrackingBehavioralData"] as? Bool | ||
| let enableLocationEvents = config["enableLocationEvents"] as? Bool | ||
|
|
||
| nativeConfiguration = TSInitSDKConfiguration( | ||
| enableTrackingBehavioralData: enableTrackingBehavioralData ?? true, | ||
| enableLocationEvents: enableLocationEvents ?? false | ||
| ) | ||
| } | ||
|
|
||
| TSAccountProtection.initialize(baseUrl: baseUrl, clientId: clientId, userId: userId, configuration: nativeConfiguration) | ||
|
|
||
| resolve(true) |
There was a problem hiding this comment.
initializeIOS no longer validates baseUrl. Since baseUrl is now required (and docs say it must include /risk-collect/), it would be better to reject early when baseUrl is empty/invalid to avoid confusing downstream SDK failures.
| **Available TSClaimedUserIdType values:** | ||
| - `TSClaimedUserIdType.email` | ||
| - `TSClaimedUserIdType.username` | ||
| - `TSClaimedUserIdType.phoneNumber` | ||
| - `TSClaimedUserIdType.accountId` | ||
| - `TSClaimedUserIdType.ssn` | ||
| - `TSClaimedUserIdType.nationalId` | ||
| - `TSClaimedUserIdType.passportNumber` | ||
| - `TSClaimedUserIdType.driversLicenseNumber` | ||
| - `TSClaimedUserIdType.other` | ||
| const options = { | ||
| claimUserId: "user123", // @deprecated - still works for backward compatibility | ||
| claimedUserId: "user@example.com", // NEW - preferred field | ||
| claimedUserIdType: TSClaimedUserIdType.email, // NEW - specifies identifier type | ||
| correlationId: "correlation-123" | ||
| } | ||
| ``` |
There was a problem hiding this comment.
There is a Markdown formatting issue: after listing available TSClaimedUserIdType values, a const options = { ... } snippet starts without an opening code fence, and the closing fence appears later. This breaks rendering; wrap that snippet in a proper fenced code block.
| **Option 1: Basic initialization (uses TransmitSecurity.plist configuration)** | ||
| ```js | ||
| import { initializeSDKIOS } from 'react-native-ts-accountprotection'; | ||
|
|
||
| componentDidMount(): void { | ||
| // Setup the module as soon your component is ready | ||
| await initializeSDKIOS(); | ||
| } | ||
| ``` | ||
|
|
||
| **Option 2: Advanced initialization with custom parameters** | ||
| ```js | ||
| import { initializeIOS } from 'react-native-ts-accountprotection'; | ||
|
|
||
| componentDidMount(): void { | ||
| await initializeIOS( | ||
| "your-client-id", | ||
| "https://api.transmitsecurity.io/risk-collect/", // ⚠️ CRITICAL: Must include /risk-collect/ postfix |
There was a problem hiding this comment.
Both iOS initialization examples show await inside componentDidMount(): void { ... }, which is not valid JS/TS (the method must be async, or use a promise chain / useEffect). Please fix the snippets so developers can copy/paste without syntax errors.
| @ReactMethod | ||
| fun setUserId(userId: String) { | ||
| fun setAuthenticatedUser(userId: String, options: ReadableMap?, promise: Promise) { | ||
| if(reactContext.currentActivity != null) { | ||
| Log.d("TS", ">>> setUserId userId=$userId") | ||
| TSAccountProtection.setUserID(userId) | ||
| reactContext.resources.getString(R.string.transmit_security_client_id) | ||
| val optionsMap = convertCustomAttributes(options) | ||
| TSAccountProtection.setAuthenticatedUser(userId, optionsMap) | ||
| promise.resolve(true) | ||
| } else { | ||
| promise.reject("error", "Activity not available") | ||
| } | ||
| } |
There was a problem hiding this comment.
setAuthenticatedUser forwards userId directly to the native SDK without any validation. iOS rejects empty userId; for consistency (and to avoid passing an invalid identifier to the SDK), consider rejecting when userId.isBlank() (or at least isEmpty()).
| @objc(setAuthenticatedUser:options:withResolver:withRejecter:) | ||
| func setAuthenticatedUser(userId: String, options: [String: Any]? = nil, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { | ||
| guard !userId.isEmpty else { | ||
| reject("Invalid params provided to setAuthenticatedUser", nil, nil) |
There was a problem hiding this comment.
In setAuthenticatedUser, the promise reject "code" is currently a full sentence (and the message is nil). React Native consumers often branch on the error code; please use a stable identifier-style code (e.g., invalid_params) and pass the human-readable text as the message.
| reject("Invalid params provided to setAuthenticatedUser", nil, nil) | |
| reject("invalid_params", "Invalid params provided to setAuthenticatedUser", nil) |
| try TSAccountProtection.logPageLoad(pageName) | ||
| resolve(true) | ||
| } catch { | ||
| reject("logPageLoad Error", error.localizedDescription, nil) |
There was a problem hiding this comment.
In logPageLoad, the reject code contains a space ("logPageLoad Error"). To keep error handling consistent and machine-friendly, use a stable code without spaces (and put the descriptive text in the message).
| reject("logPageLoad Error", error.localizedDescription, nil) | |
| reject("logPageLoadError", error.localizedDescription, nil) |
| // Initialize with specific parameters and optional userId | ||
| await initializeIOS( | ||
| "your-client-id", | ||
| "https://api.transmitsecurity.io", |
There was a problem hiding this comment.
The migration guide's advanced initializeIOS example uses "https://api.transmitsecurity.io" without the required /risk-collect/ postfix. This conflicts with the README/release notes in this PR and will lead to a non-working integration; update the example URL accordingly.
| "https://api.transmitsecurity.io", | |
| "https://api.transmitsecurity.io/risk-collect/", |
| - **Renamed `setUser()` to `setAuthenticatedUser()`**: Method renamed for better clarity and consistency | ||
|
|
||
| ### 🛠️ Configuration Enhancements | ||
| - **iOS Location Support**: Added configuration option to enable location data collection during SDK initialization | ||
| - **Location in Actions**: Trigger Action now supports location configuration with modes: `disabled`, `default`, `forceCurrent`, `forceLastKnown`, `lastKnown` | ||
| - **Custom Attributes**: Enhanced event tracking with support for custom attributes in trigger actions | ||
| - **Behavioral Data Collection**: To collect behavioral data from UI elements, developers must add `testID` attributes to trackable elements (buttons, inputs, etc.) | ||
|
|
||
| ### ⚠️ Breaking Changes | ||
| - **`baseUrl` is now required** in `initializeIOS()` method | ||
| - **`setUser()` renamed to `setAuthenticatedUser()`** - update your method calls | ||
| - **⚠️ CRITICAL: baseUrl must include `/risk-collect/` postfix** - e.g., `https://api.transmitsecurity.io/risk-collect/` (server connection will fail without this) |
There was a problem hiding this comment.
Release notes mention renaming setUser() to setAuthenticatedUser(), but the public JS API in this repo was setUserId(...) (and the native Android method was setUserID). Please update the release notes/breaking changes bullets to reference the correct prior API name to avoid confusion.
Version 3.0.0 (Not raised in project yet)
SDK Updates
getSessionTokenAPIclearUserAPIlogPageLoad(_ pageName: String)baseUrla required parameter ininitializeSDKuserIdininitializeparameters, includingoptionscustomAttributesin Trigger ActionsetUsertosetAuthenticatedUser