improve plugin creation: add input sanitization, logging, and error handling
This commit is contained in:
parent
39ba244e73
commit
0e35bdd5d0
@ -68,6 +68,8 @@ dependencies {
|
|||||||
// For < 0.71, this will be from the local maven repo
|
// For < 0.71, this will be from the local maven repo
|
||||||
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
||||||
//noinspection GradleDynamicVersion
|
//noinspection GradleDynamicVersion
|
||||||
|
implementation "com.google.code.gson:gson:2.10.1"
|
||||||
|
|
||||||
implementation("com.facebook.react:react-android")
|
implementation("com.facebook.react:react-android")
|
||||||
def product_catalog_version = "15.1.1"
|
def product_catalog_version = "15.1.1"
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,11 @@ import de.webidsolutions.plugin_core.IProductPluginWebId
|
|||||||
import de.webidsolutions.video_ident.plugin.videocall.VideoOptionsConfig
|
import de.webidsolutions.video_ident.plugin.videocall.VideoOptionsConfig
|
||||||
import de.webidsolutions.video_ident_product_plugin.VideoIdentProductPlugin
|
import de.webidsolutions.video_ident_product_plugin.VideoIdentProductPlugin
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
import com.facebook.react.bridge.UiThreadUtil
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
|
private const val TAG = "WebIdMetaPlugin"
|
||||||
|
|
||||||
class WebIdMetaPluginModule(
|
class WebIdMetaPluginModule(
|
||||||
private val reactContext: ReactApplicationContext
|
private val reactContext: ReactApplicationContext
|
||||||
@ -63,48 +68,78 @@ class WebIdMetaPluginModule(
|
|||||||
plugins: ReadableArray,
|
plugins: ReadableArray,
|
||||||
promise: Promise
|
promise: Promise
|
||||||
) {
|
) {
|
||||||
|
val cleanUri = uri.trim()
|
||||||
|
val cleanUsername = username.trim()
|
||||||
|
val cleanApiKey = apiKey.trim()
|
||||||
|
|
||||||
|
val shaPinsList = shaPins.toArrayList().map { it.toString() }
|
||||||
|
val pluginsList = plugins.toArrayList().map { it.toString() }
|
||||||
|
|
||||||
|
Log.i(TAG, "createMetaPlugin uri=$cleanUri user=$cleanUsername apiKeyLen=${cleanApiKey.length} apiKeyTail=${cleanApiKey.takeLast(4)}")
|
||||||
|
Log.i(TAG, "createMetaPlugin shaPins len=${shaPinsList.size} first=${shaPinsList.firstOrNull()?.take(20)}...")
|
||||||
|
Log.i(TAG, "createMetaPlugin plugins(raw) len=${pluginsList.size} values=$pluginsList")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val environment = WebIdSdkEnvironment(
|
val environment = WebIdSdkEnvironment(
|
||||||
URI.create(uri),
|
URI.create(cleanUri),
|
||||||
*shaPins.toArrayList().map { it.toString() }.toTypedArray()
|
*shaPinsList.toTypedArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
val selectedPlugins = ArrayList<de.webidsolutions.plugin_core.IProductPluginWebId>()
|
val selectedPlugins = ArrayList<IProductPluginWebId>()
|
||||||
|
|
||||||
plugins.toArrayList().forEach {
|
pluginsList.forEach { p ->
|
||||||
when (it.toString()) {
|
when (p) {
|
||||||
"AutoIdOnServer" -> selectedPlugins.add(AutoIdentOnServerProductPlugin())
|
"AutoIdOnServer" -> selectedPlugins.add(AutoIdentOnServerProductPlugin())
|
||||||
"PayOnServer" -> selectedPlugins.add(PayOnServerProductPlugin())
|
"PayOnServer" -> selectedPlugins.add(PayOnServerProductPlugin())
|
||||||
"VideoId" -> selectedPlugins.add(VideoIdentProductPlugin(config = VideoOptionsConfig()))
|
"VideoId" -> selectedPlugins.add(VideoIdentProductPlugin(config = VideoOptionsConfig()))
|
||||||
"EIdOnServer" -> selectedPlugins.add(EIdOnServerProductPlugin())
|
"EIdOnServer" -> selectedPlugins.add(EIdOnServerProductPlugin())
|
||||||
|
else -> Log.w(TAG, "createMetaPlugin unknown plugin string='$p'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "createMetaPlugin plugins(mapped) len=${selectedPlugins.size} classes=${selectedPlugins.map { it.javaClass.simpleName }}")
|
||||||
|
|
||||||
metaPlugin = WebIdMetaPlugin(
|
metaPlugin = WebIdMetaPlugin(
|
||||||
environment,
|
environment,
|
||||||
username,
|
cleanUsername,
|
||||||
apiKey,
|
cleanApiKey,
|
||||||
reactApplicationContext,
|
reactApplicationContext,
|
||||||
selectedPlugins
|
selectedPlugins
|
||||||
)
|
)
|
||||||
|
|
||||||
promise.resolve("MetaPluginCreated")
|
promise.resolve("MetaPluginCreated")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
promise.reject("CREATE_ERROR", e.message)
|
Log.e(TAG, "createMetaPlugin failed: ${e.message}", e)
|
||||||
|
promise.reject("CREATE_ERROR", e.message, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
// VERIFY
|
// VERIFY
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
fun verifyActionId(actionId: String, promise: Promise) {
|
fun verifyActionId(actionId: String, promise: Promise) {
|
||||||
|
Log.i(TAG, "verifyActionId() called actionId=$actionId")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val result = metaPlugin?.verify(actionId)
|
val plugin = metaPlugin
|
||||||
promise.resolve(result.toString())
|
if (plugin == null) {
|
||||||
|
Log.w(TAG, "verifyActionId() blocked: SDK_NOT_INITIALIZED")
|
||||||
|
promise.reject("SDK_NOT_INITIALIZED", "MetaPlugin not created. Call createMetaPlugin() first.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = plugin.verify(actionId)
|
||||||
|
|
||||||
|
val json = Gson().toJson(result)
|
||||||
|
Log.i(TAG, "verifyActionId() success, jsonLen=${json.length}")
|
||||||
|
|
||||||
|
promise.resolve(json)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
promise.reject("VERIFY_ERROR", e.message)
|
Log.e(TAG, "verifyActionId() failed: ${e.message}", e)
|
||||||
|
promise.reject("VERIFY_ERROR", e.message, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,37 +162,39 @@ class WebIdMetaPluginModule(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
UiThreadUtil.runOnUiThread {
|
||||||
val fragment = WebIdResultHostFragment.getOrCreate(
|
try {
|
||||||
activity = activity,
|
val fragment = WebIdResultHostFragment.getOrCreate(
|
||||||
onResult = { resultCode, data ->
|
activity = activity,
|
||||||
try {
|
onResult = { resultCode, data ->
|
||||||
val result = data?.let {
|
try {
|
||||||
IProductPluginWebId.getProductPluginResult<IEPluginError>(it, resultCode)
|
val result = data?.let {
|
||||||
}
|
IProductPluginWebId.getProductPluginResult<IEPluginError>(it, resultCode)
|
||||||
|
}
|
||||||
|
|
||||||
if (result?.error == null) {
|
if (result?.error == null) {
|
||||||
sendEvent("WebIdSdkEvent.finishedSuccess", result?.info ?: "")
|
sendEvent("WebIdSdkEvent.finishedSuccess", result?.info ?: "")
|
||||||
} else {
|
} else {
|
||||||
sendEvent("WebIdSdkEvent.finishedFailed", result.error.toString())
|
sendEvent("WebIdSdkEvent.finishedFailed", result.error.toString())
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
sendEvent("WebIdSdkEvent.finishedFailed", e.message ?: "Unknown")
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
sendEvent("WebIdSdkEvent.finishedFailed", e.message ?: "Unknown")
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
|
|
||||||
val customTheme: Int? = null
|
val customTheme: Int? = null
|
||||||
|
|
||||||
plugin.startPlugin(
|
plugin.startPlugin(
|
||||||
activity,
|
activity,
|
||||||
fragment.launcher,
|
fragment.launcher,
|
||||||
customTheme
|
customTheme
|
||||||
)
|
)
|
||||||
|
|
||||||
promise.resolve("PluginStarted")
|
promise.resolve("PluginStarted")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
promise.reject("START_ERROR", e.message)
|
promise.reject("START_ERROR", e.message, e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,8 @@
|
|||||||
"build:ios": "react-native build-ios --scheme WebIdMetaPluginExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\""
|
"build:ios": "react-native build-ios --scheme WebIdMetaPluginExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.2.4",
|
"react": "19.2.3",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "19.2.3",
|
||||||
"react-native": "0.84.0",
|
"react-native": "0.84.0",
|
||||||
"react-native-web-id-meta-plugin": "file:.."
|
"react-native-web-id-meta-plugin": "file:.."
|
||||||
},
|
},
|
||||||
|
|||||||
@ -25,11 +25,20 @@ import BouncyCheckbox from 'react-native-bouncy-checkbox';
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [actionId, onChangeActionId] = React.useState('');
|
const [actionId, onChangeActionId] = React.useState('');
|
||||||
var selectedPlugins: Set<string> = new Set();
|
|
||||||
|
|
||||||
|
const [selectedPlugins, setSelectedPlugins] = React.useState<string[]>([]);
|
||||||
|
|
||||||
|
const togglePlugin = (name: string, isChecked: boolean) => {
|
||||||
|
setSelectedPlugins((prev) => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
if (isChecked) next.add(name);
|
||||||
|
else next.delete(name);
|
||||||
|
return Array.from(next);
|
||||||
|
});
|
||||||
|
};
|
||||||
webIdEventEmitter.addListener(WebIdSdkEvent.finishedFailed, (eventData) => {
|
webIdEventEmitter.addListener(WebIdSdkEvent.finishedFailed, (eventData) => {
|
||||||
let result = parseJSONToType<ProductPluginResultFailed>(eventData);
|
let result = parseJSONToType<ProductPluginResultFailed>(eventData);
|
||||||
if (result != undefined) {
|
if (result !== undefined) {
|
||||||
console.log(
|
console.log(
|
||||||
'received failed event with result code: ',
|
'received failed event with result code: ',
|
||||||
result.genericResultCode
|
result.genericResultCode
|
||||||
@ -39,7 +48,7 @@ export default function App() {
|
|||||||
|
|
||||||
webIdEventEmitter.addListener(WebIdSdkEvent.finishedSuccess, (eventData) => {
|
webIdEventEmitter.addListener(WebIdSdkEvent.finishedSuccess, (eventData) => {
|
||||||
let result = parseJSONToType<ProductPluginResultSuccess>(eventData);
|
let result = parseJSONToType<ProductPluginResultSuccess>(eventData);
|
||||||
if (result != undefined) {
|
if (result !== undefined) {
|
||||||
console.log(
|
console.log(
|
||||||
'received failed event with process finished: ',
|
'received failed event with process finished: ',
|
||||||
result.processFinished
|
result.processFinished
|
||||||
@ -63,13 +72,7 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onCreateMetaPlugin = () => {
|
const onCreateMetaPlugin = () => {
|
||||||
createMetaPlugin(
|
createMetaPlugin(URL, USERNAME, API_KEY, [CERT_BASE64], selectedPlugins)
|
||||||
URL,
|
|
||||||
USERNAME,
|
|
||||||
API_KEY,
|
|
||||||
[CERT_BASE64],
|
|
||||||
Array.from(selectedPlugins)
|
|
||||||
)
|
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
showAlert('Success', data);
|
showAlert('Success', data);
|
||||||
})
|
})
|
||||||
@ -125,44 +128,36 @@ export default function App() {
|
|||||||
<View>
|
<View>
|
||||||
<View>
|
<View>
|
||||||
<BouncyCheckbox
|
<BouncyCheckbox
|
||||||
isChecked={selectedPlugins.has('AutoIdOnServer')}
|
isChecked={selectedPlugins.includes('AutoIdOnServer')}
|
||||||
onPress={(isChecked: boolean) =>
|
onPress={(isChecked: boolean) =>
|
||||||
isChecked === true
|
togglePlugin('AutoIdOnServer', isChecked)
|
||||||
? selectedPlugins.add('AutoIdOnServer')
|
|
||||||
: selectedPlugins.delete('AutoIdOnServer')
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Text>AutoIdOnServer</Text>
|
<Text>AutoIdOnServer</Text>
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
<BouncyCheckbox
|
<BouncyCheckbox
|
||||||
isChecked={selectedPlugins.has('PayOnServer')}
|
isChecked={selectedPlugins.includes('PayOnServer')}
|
||||||
onPress={(isChecked: boolean) =>
|
onPress={(isChecked: boolean) =>
|
||||||
isChecked === true
|
togglePlugin('PayOnServer', isChecked)
|
||||||
? selectedPlugins.add('PayOnServer')
|
|
||||||
: selectedPlugins.delete('PayOnServer')
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Text>PayOnServer</Text>
|
<Text>PayOnServer</Text>
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
<BouncyCheckbox
|
<BouncyCheckbox
|
||||||
isChecked={selectedPlugins.has('VideoId')}
|
isChecked={selectedPlugins.includes('VideoId')}
|
||||||
onPress={(isChecked: boolean) =>
|
onPress={(isChecked: boolean) =>
|
||||||
isChecked === true
|
togglePlugin('VideoId', isChecked)
|
||||||
? selectedPlugins.add('VideoId')
|
|
||||||
: selectedPlugins.delete('VideoId')
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Text>VideoId</Text>
|
<Text>VideoId</Text>
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
<BouncyCheckbox
|
<BouncyCheckbox
|
||||||
isChecked={selectedPlugins.has('EIdOnServer')}
|
isChecked={selectedPlugins.includes('EIdOnServer')}
|
||||||
onPress={(isChecked: boolean) =>
|
onPress={(isChecked: boolean) =>
|
||||||
isChecked === true
|
togglePlugin('EIdOnServer', isChecked)
|
||||||
? selectedPlugins.add('EIdOnServer')
|
|
||||||
: selectedPlugins.delete('EIdOnServer')
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Text>EIdOnServer</Text>
|
<Text>EIdOnServer</Text>
|
||||||
|
|||||||
16
yarn.lock
16
yarn.lock
@ -6532,6 +6532,13 @@ react-dom@^19.2.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
scheduler "^0.27.0"
|
scheduler "^0.27.0"
|
||||||
|
|
||||||
|
react-dom@19.2.3:
|
||||||
|
version "19.2.3"
|
||||||
|
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz"
|
||||||
|
integrity sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==
|
||||||
|
dependencies:
|
||||||
|
scheduler "^0.27.0"
|
||||||
|
|
||||||
react-is@^16.13.1:
|
react-is@^16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
|
|
||||||
@ -6579,8 +6586,8 @@ react-native-dotenv@^3.4.9:
|
|||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "file:example"
|
resolved "file:example"
|
||||||
dependencies:
|
dependencies:
|
||||||
react "^19.2.4"
|
react "19.2.3"
|
||||||
react-dom "^19.2.4"
|
react-dom "19.2.3"
|
||||||
react-native "0.84.0"
|
react-native "0.84.0"
|
||||||
react-native-web-id-meta-plugin "file:.."
|
react-native-web-id-meta-plugin "file:.."
|
||||||
|
|
||||||
@ -6638,6 +6645,11 @@ react@*, react@^19.2.3, react@^19.2.4:
|
|||||||
resolved "https://registry.npmjs.org/react/-/react-19.2.4.tgz"
|
resolved "https://registry.npmjs.org/react/-/react-19.2.4.tgz"
|
||||||
integrity sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==
|
integrity sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==
|
||||||
|
|
||||||
|
react@19.2.3:
|
||||||
|
version "19.2.3"
|
||||||
|
resolved "https://registry.npmjs.org/react/-/react-19.2.3.tgz"
|
||||||
|
integrity sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==
|
||||||
|
|
||||||
read-pkg-up@^3.0.0:
|
read-pkg-up@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user