diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2329d8..e468f18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,6 +84,12 @@ jobs: run: | yarn build:android + - name: 🔑 License backend hint + if: failure() + run: | + echo "::warning::The example app applies app.talsec.plugin, which requests a license token from portal-backend.talsec.app during the build." + echo "::warning::If the log shows 'Cannot resolve license', check that the backend is up and reachable from the runner before investigating this PR." + build-ios: runs-on: macos-latest needs: build-library diff --git a/CHANGELOG.md b/CHANGELOG.md index 647ca01..d9d948e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [6.0.0] - 2026-09-30 + +- Android SDK version: 19.3.1 +- iOS SDK version: 7.1.4 + +### React Native + +#### Breaking + +- Android builds now require the `app.talsec.plugin` Gradle plugin + +### Android + +#### Breaking + +- Changed Talsec integration from Maven dependency to the `app.talsec.plugin` Gradle plugin with `talsec { }` configuration block + +#### Fixed + +- Root detection related bugs causing false positives + ## [5.2.2] - 2026-09-29 - Android SDK version: 19.2.3 diff --git a/android/build.gradle b/android/build.gradle index 740a874..3cc736d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -105,7 +105,7 @@ dependencies { implementation "com.facebook.react:react-native:$react_native_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" - implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:19.2.3" + implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:19.3.1" } if (isNewArchitectureEnabled()) { diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 28e0eeb..5bcc3a3 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" +apply plugin: "app.talsec.plugin" /** * This is the configuration block to customize your React Native Android app. diff --git a/example/android/build.gradle b/example/android/build.gradle index 9766946..487ab0c 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -10,11 +10,14 @@ buildscript { repositories { google() mavenCentral() + maven { url "https://europe-west3-maven.pkg.dev/talsec-artifact-repository/plugin" } } dependencies { classpath("com.android.tools.build:gradle") classpath("com.facebook.react:react-native-gradle-plugin") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") + // TODO: set the real version once app.talsec.plugin with wrapper support is released + classpath("app.talsec.plugin:talsec-security-plugin:1.1.0") } } diff --git a/package.json b/package.json index 58ede31..dbe4220 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "freerasp-react-native", - "version": "5.2.2", + "version": "6.0.0", "description": "React Native plugin for improving app security and threat monitoring on Android and iOS mobile devices.", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/plugin/build/index.js b/plugin/build/index.js index fc6c8fd..08bde8a 100644 --- a/plugin/build/index.js +++ b/plugin/build/index.js @@ -11,6 +11,10 @@ const iosSpmProperties_1 = __importDefault(require("./iosSpmProperties")); const { createBuildGradlePropsConfigPlugin } = config_plugins_1.AndroidConfig.BuildProperties; const urlFreerasp = 'https://europe-west3-maven.pkg.dev/talsec-artifact-repository/freerasp'; const urlJitpack = 'https://www.jitpack.io'; +const urlTalsecPlugin = 'https://europe-west3-maven.pkg.dev/talsec-artifact-repository/plugin'; +const talsecPluginId = 'app.talsec.plugin'; +// TODO: set the real version once app.talsec.plugin with wrapper support is released +const talsecPluginArtifact = 'app.talsec.plugin:talsec-security-plugin:1.1.0'; const setBuildscriptDependency = (buildGradle) => { // This enables users in bare workflow to comment out the line to prevent freerasp from adding it back. const mavenFreerasp = buildGradle.includes(urlFreerasp) @@ -78,6 +82,50 @@ const withAndroidR8Version = (expoConfig, props) => { return config; }); }; +const setTalsecGradlePlugin = (buildGradle) => { + if (buildGradle.includes(talsecPluginArtifact)) { + return buildGradle; + } + const talsecBuildscript = ` + buildscript { + repositories { + maven { url "${urlTalsecPlugin}" } + } + dependencies { + classpath("${talsecPluginArtifact}") + } + } + `; + return buildGradle + `\n${talsecBuildscript}\n`; +}; +const setTalsecAppPlugin = (appBuildGradle) => { + if (appBuildGradle.includes(talsecPluginId)) { + return appBuildGradle; + } + return appBuildGradle + `\napply plugin: "${talsecPluginId}"\n`; +}; +const withTalsecGradlePlugin = (expoConfig) => { + return (0, config_plugins_1.withProjectBuildGradle)(expoConfig, (config) => { + if (config.modResults.language === 'groovy') { + config.modResults.contents = setTalsecGradlePlugin(config.modResults.contents); + } + else { + config_plugins_1.WarningAggregator.addWarningAndroid('freerasp-react-native', `Cannot automatically configure project build.gradle, because it's not groovy`); + } + return config; + }); +}; +const withTalsecAppPlugin = (expoConfig) => { + return (0, config_plugins_1.withAppBuildGradle)(expoConfig, (config) => { + if (config.modResults.language === 'groovy') { + config.modResults.contents = setTalsecAppPlugin(config.modResults.contents); + } + else { + config_plugins_1.WarningAggregator.addWarningAndroid('freerasp-react-native', `Cannot automatically configure app build.gradle, because it's not groovy`); + } + return config; + }); +}; const withFreeraspIosFrameworks = (config, spmEnabled) => { return (0, config_plugins_1.withPodfileProperties)(config, (cfg) => { (0, iosSpmProperties_1.default)(cfg.modResults, spmEnabled); @@ -110,6 +158,8 @@ const withRnTalsecIos = (config, props) => { }; const withRnTalsecApp = (config, props) => { config = withBuildscriptDependency(config); + config = withTalsecGradlePlugin(config); + config = withTalsecAppPlugin(config); config = withAndroidMinSdkVersion(config, props); config = withAndroidR8Version(config, props); config = withRnTalsecIos(config, props); diff --git a/plugin/src/index.ts b/plugin/src/index.ts index 438a59b..677d849 100644 --- a/plugin/src/index.ts +++ b/plugin/src/index.ts @@ -4,6 +4,7 @@ import { createRunOncePlugin, withDangerousMod, withPodfileProperties, + withAppBuildGradle, withProjectBuildGradle, type ConfigPlugin, } from '@expo/config-plugins'; @@ -19,6 +20,11 @@ const { createBuildGradlePropsConfigPlugin } = AndroidConfig.BuildProperties; const urlFreerasp = 'https://europe-west3-maven.pkg.dev/talsec-artifact-repository/freerasp'; const urlJitpack = 'https://www.jitpack.io'; +const urlTalsecPlugin = + 'https://europe-west3-maven.pkg.dev/talsec-artifact-repository/plugin'; +const talsecPluginId = 'app.talsec.plugin'; +// TODO: set the real version once app.talsec.plugin with wrapper support is released +const talsecPluginArtifact = 'app.talsec.plugin:talsec-security-plugin:1.1.0'; const setBuildscriptDependency = (buildGradle: string) => { // This enables users in bare workflow to comment out the line to prevent freerasp from adding it back. @@ -112,6 +118,65 @@ const withAndroidR8Version: ConfigPlugin = ( }); }; +const setTalsecGradlePlugin = (buildGradle: string) => { + if (buildGradle.includes(talsecPluginArtifact)) { + return buildGradle; + } + + const talsecBuildscript = ` + buildscript { + repositories { + maven { url "${urlTalsecPlugin}" } + } + dependencies { + classpath("${talsecPluginArtifact}") + } + } + `; + + return buildGradle + `\n${talsecBuildscript}\n`; +}; + +const setTalsecAppPlugin = (appBuildGradle: string) => { + if (appBuildGradle.includes(talsecPluginId)) { + return appBuildGradle; + } + + return appBuildGradle + `\napply plugin: "${talsecPluginId}"\n`; +}; + +const withTalsecGradlePlugin: ConfigPlugin = (expoConfig) => { + return withProjectBuildGradle(expoConfig, (config) => { + if (config.modResults.language === 'groovy') { + config.modResults.contents = setTalsecGradlePlugin( + config.modResults.contents + ); + } else { + WarningAggregator.addWarningAndroid( + 'freerasp-react-native', + `Cannot automatically configure project build.gradle, because it's not groovy` + ); + } + return config; + }); +}; + +const withTalsecAppPlugin: ConfigPlugin = (expoConfig) => { + return withAppBuildGradle(expoConfig, (config) => { + if (config.modResults.language === 'groovy') { + config.modResults.contents = setTalsecAppPlugin( + config.modResults.contents + ); + } else { + WarningAggregator.addWarningAndroid( + 'freerasp-react-native', + `Cannot automatically configure app build.gradle, because it's not groovy` + ); + } + return config; + }); +}; + const withFreeraspIosFrameworks = ( config: ExpoConfig, spmEnabled: boolean @@ -159,6 +224,8 @@ const withRnTalsecIos: ConfigPlugin = (config, props) => { const withRnTalsecApp: ConfigPlugin = (config, props) => { config = withBuildscriptDependency(config); + config = withTalsecGradlePlugin(config); + config = withTalsecAppPlugin(config); config = withAndroidMinSdkVersion(config, props); config = withAndroidR8Version(config, props); config = withRnTalsecIos(config, props);