UNPKG

react-native-malwarelytics

Version:

Malwarelytics for React Native protects your banking or fintech app from a broad range of mobile security threats with an industry-leading mobile threat intelligence solution.

245 lines (216 loc) 8.42 kB
// // Copyright 2023 Wultra s.r.o. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions // and limitations under the License. // import type { EmitterSubscription } from "react-native"; import { MalwarelyticsModule, MalwarelyticsModuleIfc, wrapNativeCall } from "./internal/MalwarelyticsModule"; import { EventHelper } from "./internal/EventHelper"; import type { MalwarelyticsConfig } from "./MalwarelyticsConfig"; import { MalwarelyticsRasp } from "./MalwarelyticsRasp"; import { MalwarelyticsAntivirus } from "./MalwarelyticsAntivirus"; import { MalwarelyticsAppleDetectableApp } from "./MalwarelyticsConfig"; import { Platform } from "react-native"; import { MalwarelyticsError } from "./MalwarelyticsError"; /** * JavaScript wrapper around native kotlin/swift Malwarelytics code. */ export class Malwarelytics { // Shared instance /** * Contains shared instance of Malwarelytics class. */ static get sharedInstance(): Malwarelytics { if (this.instance === undefined) { this.instance = new Malwarelytics() } return this.instance } // Configuration /** * Get state of the Malwarelytics module. * * This function also updates content of `initializationResult` getter, if result * is available. * * @returns State of the module. */ getState(): Promise<MalwarelyticsState> { return this.withModule(async (module) => { const stateWithResult = await module.getState() this.lastInitializationResult = stateWithResult.result return stateWithResult.state }) } /** * Apple specific: Obtain list of DetectableApp.KnownApp items that are predefined in native iOS library. * * @returns List of DetectableApp.KnownApp items. */ getKnownDetectableApps(): Promise<MalwarelyticsAppleDetectableApp[]> { if (Platform.OS != "ios") { return Promise.reject(new MalwarelyticsError("METHOD_NOT_SUPPORTED", "This method is supported only on Apple platforms")) } return this.withModule(module => module.getKnownDetectableApps()) } /** * Initialize Malwarelytics instance with given configuration. * * Note that if you want to change the configuration on the running instance, * then you have to `shutdown()` the instance first. * * @param configuration Configuration to apply. */ initialize(configuration: MalwarelyticsConfig): Promise<MalwarelyticsInitializationResult> { return this.withModule(async (module) => { this.lastInitializationResult = await module.initialize(configuration) return this.lastInitializationResult }) } /** * Contains information about last initialization result. */ get initializationResult(): MalwarelyticsInitializationResult | undefined { return this.lastInitializationResult } /** * Shutdown the previously initialized Malwarelytics instance. * @param clearAvUserId If `true`, then clears also persistent AV user ID, making the device appear as a newly created. The default value is `false`. */ shutdown(clearAvUserId: boolean = false): Promise<void> { return this.withModule(async (module) => { await module.shutdown(clearAvUserId) this.lastInitializationResult = undefined }) } /** * Get information whether module is already initialized. */ async isInitialized(): Promise<boolean> { return (await this.getState()) == "READY" } /** * Sets new client id that will be sent to the backend for user identification. * Pass `undefined` to remove the current client id (for example when user logged-out). * * @param clientId Client id, `undefied` for deleting the value */ setClientId(clientId: string | undefined): Promise<void> { return this.withModule((module) => module.setClientId(clientId)) } /** * Sets new device id that will be sent to the backend for user identification. * Pass `undefied` to remove the current device id. * * @param deviceId Device id, `undefied` for deleting the value */ setDeviceId(deviceId: string | undefined): Promise<void> { return this.withModule((module) => module.setDeviceId(deviceId)) } /** * Get AV User ID if it is available. The AV User ID will be available if the SDK initialized with * result `SUCCESS`. Otherwise it might be undefined. */ getAvUserId(): Promise<string | undefined> { return this.withModule(module => module.getAvUserId()) } // Events /** * Object representing a subscription to state events. */ private stateEventsSubscription: EmitterSubscription | undefined /** * Set listener for Malwarelytic's instance state changes. * @param listener Listener implementation. */ async setStateListener(listener: MalwarelyticsStateListener): Promise<void> { this.stateEventsSubscription?.remove() this.stateEventsSubscription = await this.eventHelper.addListener('Malwarelytics.STATE', (data) => { listener.malwarelyticsStateChanged(data as MalwarelyticsState) }) } /** * Remove state listener previously set by `setStateListener()` method. */ removeStateListener() { this.stateEventsSubscription?.remove() this.stateEventsSubscription = undefined } // Private methods and properties /** * Instance of native module. */ private readonly nativeModule: MalwarelyticsModuleIfc /** * Instance of event helper. */ private readonly eventHelper: EventHelper /** * RASP module */ readonly rasp: MalwarelyticsRasp /** * Antivirus module */ readonly antivirus: MalwarelyticsAntivirus /** * Shared instnace of this class. */ private static instance: Malwarelytics | undefined /** * Last initialization result */ private lastInitializationResult: MalwarelyticsInitializationResult | undefined /** * Private constructor. */ private constructor() { this.nativeModule = MalwarelyticsModule this.eventHelper = new EventHelper(this.nativeModule) this.rasp = new MalwarelyticsRasp(this.eventHelper) this.antivirus = new MalwarelyticsAntivirus(this.eventHelper) } /** * Execute closure with action with properly acquired instnace to native module. * @param action Action to execute. * @returns Result returned from the action. */ private async withModule<T>(action: (nativeModule: MalwarelyticsModuleIfc) => Promise<T>): Promise<T> { return wrapNativeCall(this.nativeModule, action) } } /** * Type defining the state of Malwarelytics module: * - `"SHUTDOWN"` - Malwarelytics is not initialized. * - `"PENDING_INIT"` - Malwarelytics is initializing. * - `"READY"` - Malwarelytics is ready and prepared for use. * - `"PENDING_SHUTDOWN"` - Malwarelytics is shutting down. */ export type MalwarelyticsState = 'SHUTDOWN' | 'PENDING_INIT' | 'READY' | 'PENDING_SHUTDOWN'; /** * Type defining the result of Malwarelytics initialization. * - `'SUCCESS'` - Initialization completed successfully * - `'PERMANENT_OFFLINE_MODE'` - SDK works in permanent offline mode. * - `'TEMPORARY_OFFLINE_MODE'` - Android only: SDK works in temporary offline mode. */ export type MalwarelyticsInitializationResult = 'SUCCESS' | 'TEMPORARY_OFFLINE_MODE' | 'PERMANENT_OFFLINE_MODE'; /** * Interface for listening Malwarelytics module state changes. */ export interface MalwarelyticsStateListener { /** * Called when state of Malwarelytics module is changed. * @param state New module's state. */ malwarelyticsStateChanged(state: MalwarelyticsState): void; }