From f3b03e0a0999ff628ecf16c2dccb0befc99ffe61 Mon Sep 17 00:00:00 2001 From: Alexandre Jacinto Date: Wed, 8 May 2024 09:51:07 +0100 Subject: [PATCH] RMET-3408 KeyStore Plugin - Prepare release of version `2.6.8-OS19` (#29) * RMET-3408 KeyStore Plugin - Set auth prompt text (title, subtitle, and negative button) (#28) * feat: get biometric prompt info from strings.xml and pass them to library References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * feat: copy biometric prompt info to strings.xml in hook References: * feat: check of biometric prompt info is not empty References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * fix: properly use getPreference method, passing in the platform (android) References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * refactor: use const instead of var References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * chore: update dependency to OSKeystoreLib-Android References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * fix: add dependency to xmldom References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * fix: create DOMParser() instance References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * fix: get android preferences properly References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * refactor: remove unused code References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * chore: update changelog References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * revert: revert change in previous commit References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * chore: raise to version 2.6.8-OS19 References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * chore: update dependency to OSKeystoreLib-Android References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * fix: properly check if field is empty string References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * misc: set version to an existing one References: https://outsystemsrd.atlassian.net/browse/RMET-3408 * chore: update dependency to OSKeystoreAndroid-Lib References: https://outsystemsrd.atlassian.net/browse/RMET-3408 --- CHANGELOG | 5 +++ hooks/android/androidCopyPreferences.js | 59 +++++++++++++++++++------ package.json | 7 ++- plugin.xml | 5 ++- src/android/SecureStorage.java | 18 +++++++- src/android/build.gradle | 2 +- 6 files changed, 77 insertions(+), 19 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 15f88d54..b69e53da 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,11 @@ Changelog Unreleased ------------------ +2.6.8-OS19 - 2024-05-03 +------------------ + +- Feat: [Android] Add parameters for title, subtitle, and negative button text of Biometric Prompt (https://outsystemsrd.atlassian.net/browse/RMET-3408). + 2.6.8-OS18 - 2024-01-11 ------------------ diff --git a/hooks/android/androidCopyPreferences.js b/hooks/android/androidCopyPreferences.js index c2345b11..b97215aa 100644 --- a/hooks/android/androidCopyPreferences.js +++ b/hooks/android/androidCopyPreferences.js @@ -1,25 +1,58 @@ -const et = require('elementtree'); const path = require('path'); const fs = require('fs'); const { ConfigParser } = require('cordova-common'); +const { DOMParser, XMLSerializer } = require('xmldom'); module.exports = function (context) { - var projectRoot = context.opts.cordova.project ? context.opts.cordova.project.root : context.opts.projectRoot; - var configXML = path.join(projectRoot, 'config.xml'); - var configParser = new ConfigParser(configXML); - var authenticate = configParser.getGlobalPreference("MigratedKeysAuthentication"); + const projectRoot = context.opts.cordova.project ? context.opts.cordova.project.root : context.opts.projectRoot; + const configXML = path.join(projectRoot, 'config.xml'); + const configParser = new ConfigParser(configXML); + const parser = new DOMParser(); + + const authenticate = configParser.getGlobalPreference('MigratedKeysAuthentication'); + const auth_prompt_title = configParser.getPreference('AuthPromptTitle', 'android') + const auth_prompt_subtitle = configParser.getPreference('AuthPromptSubtitle', 'android') + const auth_prompt_negative_button = configParser.getPreference('AuthPromptCancelButton', 'android') + + const stringsXmlPath = path.join(projectRoot, 'platforms/android/app/src/main/res/values/strings.xml'); + const stringsXmlString = fs.readFileSync(stringsXmlPath, 'utf-8'); + const stringsXmlDoc = parser.parseFromString(stringsXmlString, 'text/xml') if(authenticate == "true"){ - var stringsXmlPath = path.join(projectRoot, 'platforms/android/app/src/main/res/values/strings.xml'); - var stringsXmlContents = fs.readFileSync(stringsXmlPath).toString(); - var etreeStrings = et.parse(stringsXmlContents); + // insert bool value in strings.xml + const booleanElements = stringsXmlDoc.getElementsByTagName('bool'); - var migrationAuthTags = etreeStrings.findall('./bool[@name="migration_auth"]'); - for (var i = 0; i < migrationAuthTags.length; i++) { - migrationAuthTags[i].text = authenticate; + // set text for each element + for (let i = 0; i < booleanElements.length; i++) { + const name = booleanElements[i].getAttribute('name'); + if (name == "migration_auth") { + booleanElements[i].textContent = authenticate; + } } + } - var resultXmlStrings = etreeStrings.write(); - fs.writeFileSync(stringsXmlPath, resultXmlStrings); + // insert string values in strings.xml + const stringElements = stringsXmlDoc.getElementsByTagName('string'); + + // set text for each element + for (let i = 0; i < stringElements.length; i++) { + const name = stringElements[i].getAttribute('name'); + if (name == "biometric_prompt_title" && auth_prompt_title != "") { + stringElements[i].textContent = auth_prompt_title; + } + else if (name == "biometric_prompt_subtitle" && auth_prompt_subtitle != "") { + stringElements[i].textContent = auth_prompt_subtitle; + } + else if (name == "biometric_prompt_negative_button" && auth_prompt_negative_button != "") { + stringElements[i].textContent = auth_prompt_negative_button; + } } + + // serialize the updated XML document back to string + const serializer = new XMLSerializer(); + const updatedXmlString = serializer.serializeToString(stringsXmlDoc); + + // write the updated XML string back to the same file + fs.writeFileSync(stringsXmlPath, updatedXmlString, 'utf-8'); + }; diff --git a/package.json b/package.json index 5780f4c9..b572f74e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-secure-storage", - "version": "2.6.8-OS18", + "version": "2.6.8-OS19", "description": "Secure storage plugin for iOS & Android", "author": "Yiorgis Gozadinos ", "contributors": [ @@ -50,5 +50,8 @@ "bugs": { "url": "https://github.com/crypho/cordova-plugin-secure-storage/issues" }, - "homepage": "https://github.com/crypho/cordova-plugin-secure-storage#readme" + "homepage": "https://github.com/crypho/cordova-plugin-secure-storage#readme", + "dependencies": { + "xmldom": "^0.6.0" + } } diff --git a/plugin.xml b/plugin.xml index 295919ce..d2034733 100644 --- a/plugin.xml +++ b/plugin.xml @@ -2,7 +2,7 @@ + version="2.6.8-OS19"> SecureStorage Crypho AS @@ -66,6 +66,9 @@ false + Authentication required + Please authenticate to continue + Cancel diff --git a/src/android/SecureStorage.java b/src/android/SecureStorage.java index 255225df..0a283703 100644 --- a/src/android/SecureStorage.java +++ b/src/android/SecureStorage.java @@ -31,6 +31,7 @@ import com.outsystems.plugins.keystore.controller.KeystoreController; import com.outsystems.plugins.keystore.controller.KeystoreError; +import com.outsystems.plugins.keystore.controller.OSKSTRBiometricPromptInfo; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaArgs; @@ -75,8 +76,13 @@ protected void pluginInitialize() { intentRequestQueue = new IntentRequestQueue(this); - keystoreController = new KeystoreController(); - + keystoreController = new KeystoreController( + new OSKSTRBiometricPromptInfo( + getStringResource(this.cordova.getActivity(), "biometric_prompt_title"), + getStringResource(this.cordova.getActivity(), "biometric_prompt_subtitle"), + getStringResource(this.cordova.getActivity(), "biometric_prompt_negative_button") + ) + ); } @@ -947,5 +953,13 @@ private String formatErrorCode(int code) { private int getBooleanResourceId(Activity activity, String name) { return activity.getResources().getIdentifier(name, "bool", activity.getPackageName()); } + + private int getStringResourceId(Activity activity, String name) { + return activity.getResources().getIdentifier(name, "string", activity.getPackageName()); + } + + private String getStringResource(Activity activity, String name) { + return activity.getString(getStringResourceId(activity, name)); + } } diff --git a/src/android/build.gradle b/src/android/build.gradle index 1dd18c4d..c34f6d4c 100644 --- a/src/android/build.gradle +++ b/src/android/build.gradle @@ -24,5 +24,5 @@ dependencies { implementation("com.github.outsystems:oscordova-android:1.1.0@aar") implementation("androidx.security:security-crypto:1.1.0-alpha03") implementation("androidx.biometric:biometric:1.1.0") - implementation("com.github.outsystems:oskeystore-android:1.0.4@aar") + implementation("com.github.outsystems:oskeystore-android:1.1.0@aar") }