diff --git a/.circleci/config.yml b/.circleci/config.yml
index f1c682510..438a84e19 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,8 +3,8 @@ parameters:
flavor:
type: enum
default: "generic"
- enum: ["generic", "lfe", "sakhi", "lfeTeachNagaland", "gramin"]
- description: Flavor of the binary to generate. Must be one of "generic", "lfe", "lfeTeachNagaland" or "sakhi"
+ enum: ["generic", "lfe", "sakhi", "lfeTeachNagaland", "gramin", "lfeTeachNagalandSecurity"]
+ description: Flavor of the binary to generate. Must be one of "generic", "lfe", "lfeTeachNagaland", "gramin", "lfeTeachNagalandSecurity" or "sakhi"
versionCode:
type: string
default: "1"
diff --git a/Makefile b/Makefile
index da559f30a..3285562b0 100644
--- a/Makefile
+++ b/Makefile
@@ -74,6 +74,7 @@ $(shell node -p "require('./packages/openchs-android/config/flavor_config.json')
endef
flavor_server_url:=$(call _get_from_config,$(flavor).server_url)
+flavor_disable_app_run_on_rooted_devices:=$(call _get_from_config,$(flavor).disable_app_run_on_rooted_devices)
bugsnag_env_var_name:=$(call _get_from_config,$(flavor).bugsnag.env_var_name)
bugsnag_project_name:=$(call _get_from_config,$(flavor).bugsnag.project_name)
app_android_package_name:=$(call _get_from_config,$(flavor).package_name)
@@ -117,7 +118,7 @@ endif
define _create_config
@echo "Creating config for $1"
@if [ $(1) = "prod" ]; then \
- echo "module.exports = Object.assign(require('../../config/env/$(1).json'), {COMMIT_ID: '$(sha)', SERVER_URL: '$(flavor_server_url)'});" > packages/openchs-android/src/framework/Config.js; \
+ echo "module.exports = Object.assign(require('../../config/env/$(1).json'), {COMMIT_ID: '$(sha)', SERVER_URL: '$(flavor_server_url)', DISABLE_APP_RUN_ON_ROOTED_DEVICES: '$(flavor_disable_app_run_on_rooted_devices)'});" > packages/openchs-android/src/framework/Config.js; \
else \
echo "module.exports = Object.assign(require('../../config/env/$(1).json'), {COMMIT_ID: '$(sha)'});" > packages/openchs-android/src/framework/Config.js; \
fi
diff --git a/packages/openchs-android/android/app/build.gradle b/packages/openchs-android/android/app/build.gradle
index 9dbfc993a..33a9c7f76 100644
--- a/packages/openchs-android/android/app/build.gradle
+++ b/packages/openchs-android/android/app/build.gradle
@@ -5,9 +5,6 @@ apply plugin: 'com.google.gms.google-services'
googleServices {
disableVersionCheck = true
}
-
-import com.android.build.OutputFile
-
/**
* This is the configuration block to customize your React Native Android app.
* By default you don't need to apply any configuration, just uncomment the lines you need.
@@ -138,6 +135,14 @@ android {
storePassword System.getenv("lfeTeachNagaland_KEYSTORE_PASSWORD")
keyAlias "${System.getenv("KEY_STORE_PREFIX") ?: ""}${System.getenv("lfeTeachNagaland_KEY_ALIAS")}"
keyPassword System.getenv("lfeTeachNagaland_KEY_PASSWORD")
+ enableV1Signing false
+ }
+ lfeTeachNagalandSecurity {
+ storeFile file("${System.getenv("KEY_STORE_PREFIX") ?: ""}lfeTeachNagaland-release-key.keystore")
+ storePassword System.getenv("lfeTeachNagaland_KEYSTORE_PASSWORD")
+ keyAlias "${System.getenv("KEY_STORE_PREFIX") ?: ""}${System.getenv("lfeTeachNagaland_KEY_ALIAS")}"
+ keyPassword System.getenv("lfeTeachNagaland_KEY_PASSWORD")
+ enableV1Signing false
}
sakhi {
storeFile file("${System.getenv("KEY_STORE_PREFIX") ?: ""}sakhi-release-key.keystore")
@@ -181,6 +186,16 @@ android {
lfeTeachNagaland {
applicationId "com.openchsclient.lfeteach.nagaland"
resValue "string", "app_name", "TEACH Nagaland"
+ resValue "string", "sha256_app_google_signature", "80e6b34b2026ce180ca8d6f09a885031082d0acf64eb6bd0492f36121d064ebf"
+ resValue "string", "sha256_app_upload_key_signature", "ac19586277b021dcba5097f7e47d7473bab41bf0369fb771a2bff581734561fc"
+ signingConfig signingConfigs.lfeTeachNagaland
+ manifestPlaceholders = [bugsnagAPIKey: System.getenv("LFE_TEACH_NAGALAND_BUGSNAG_API_KEY") ?: "dummy"]
+ }
+ lfeTeachNagalandSecurity {
+ applicationId "com.openchsclient.lfeteach.nagaland"
+ resValue "string", "app_name", "TEACH Nagaland"
+ resValue "string", "sha256_app_google_signature", "80e6b34b2026ce180ca8d6f09a885031082d0acf64eb6bd0492f36121d064ebf"
+ resValue "string", "sha256_app_upload_key_signature", "ac19586277b021dcba5097f7e47d7473bab41bf0369fb771a2bff581734561fc"
signingConfig signingConfigs.lfeTeachNagaland
manifestPlaceholders = [bugsnagAPIKey: System.getenv("LFE_TEACH_NAGALAND_BUGSNAG_API_KEY") ?: "dummy"]
}
@@ -198,7 +213,10 @@ android {
}
}
sourceSets {
+ // Required to enable TamperChecking, init this only for flavours which need Security Tamper Check enabled
lfe.java.srcDir 'src/common/java'
+ lfeTeachNagaland.java.srcDir 'src/common/java'
+ lfeTeachNagalandSecurity.java.srcDir 'src/common/java'
}
}
diff --git a/packages/openchs-android/android/app/lfeTeachNagalandSecurity-release-key.keystore b/packages/openchs-android/android/app/lfeTeachNagalandSecurity-release-key.keystore
new file mode 100644
index 000000000..b5e331438
Binary files /dev/null and b/packages/openchs-android/android/app/lfeTeachNagalandSecurity-release-key.keystore differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/assets/logo.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/assets/logo.png
new file mode 100644
index 000000000..db036e71c
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/assets/logo.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/google-services.json b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/google-services.json
new file mode 100644
index 000000000..bfe00adad
--- /dev/null
+++ b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/google-services.json
@@ -0,0 +1,68 @@
+{
+ "project_info": {
+ "project_number": "26847192477",
+ "project_id": "lfe-teach",
+ "storage_bucket": "lfe-teach.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:26847192477:android:21d6539bf067d972f73b74",
+ "android_client_info": {
+ "package_name": "com.openchsclient.lfeteach.nagaland"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "26847192477-o32d9p3fto6cfsb98b5a3bs6d9f39j4l.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAcDPJkNYh2qyrdYxQ1SmgRhK_e8HbzV3Y"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "26847192477-o32d9p3fto6cfsb98b5a3bs6d9f39j4l.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:26847192477:android:cc8e0d3a01a383c2f73b74",
+ "android_client_info": {
+ "package_name": "org.lfeteach.openchsclient"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "26847192477-o32d9p3fto6cfsb98b5a3bs6d9f39j4l.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyAcDPJkNYh2qyrdYxQ1SmgRhK_e8HbzV3Y"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "26847192477-o32d9p3fto6cfsb98b5a3bs6d9f39j4l.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-hdpi/openchs_launcher.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-hdpi/openchs_launcher.png
new file mode 100644
index 000000000..1239f263b
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-hdpi/openchs_launcher.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-hdpi/openchs_launcher_round.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-hdpi/openchs_launcher_round.png
new file mode 100644
index 000000000..ad5342c85
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-hdpi/openchs_launcher_round.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-mdpi/openchs_launcher.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-mdpi/openchs_launcher.png
new file mode 100644
index 000000000..95a780d32
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-mdpi/openchs_launcher.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-mdpi/openchs_launcher_round.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-mdpi/openchs_launcher_round.png
new file mode 100644
index 000000000..061c12819
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-mdpi/openchs_launcher_round.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xhdpi/openchs_launcher.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xhdpi/openchs_launcher.png
new file mode 100644
index 000000000..1cca93ac0
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xhdpi/openchs_launcher.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xhdpi/openchs_launcher_round.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xhdpi/openchs_launcher_round.png
new file mode 100644
index 000000000..5a0211470
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xhdpi/openchs_launcher_round.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxhdpi/openchs_launcher.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxhdpi/openchs_launcher.png
new file mode 100644
index 000000000..ccf34c294
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxhdpi/openchs_launcher.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxhdpi/openchs_launcher_round.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxhdpi/openchs_launcher_round.png
new file mode 100644
index 000000000..95cb1b528
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxhdpi/openchs_launcher_round.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxxhdpi/openchs_launcher.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxxhdpi/openchs_launcher.png
new file mode 100644
index 000000000..ad08f1212
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxxhdpi/openchs_launcher.png differ
diff --git a/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxxhdpi/openchs_launcher_round.png b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxxhdpi/openchs_launcher_round.png
new file mode 100644
index 000000000..5360dc09e
Binary files /dev/null and b/packages/openchs-android/android/app/src/lfeTeachNagalandSecurity/res/mipmap-xxxhdpi/openchs_launcher_round.png differ
diff --git a/packages/openchs-android/config/env/dev.json.template b/packages/openchs-android/config/env/dev.json.template
index e0dcfb34e..794482460 100644
--- a/packages/openchs-android/config/env/dev.json.template
+++ b/packages/openchs-android/config/env/dev.json.template
@@ -4,5 +4,6 @@
"CLIENT_ID": "dummy",
"goToLastPageOnNext": false,
"debugFirebaseAnalyticsEvents": false,
- "PLAYGROUND": false
+ "PLAYGROUND": false,
+ "DISABLE_APP_RUN_ON_ROOTED_DEVICES": false
}
diff --git a/packages/openchs-android/config/flavor_config.json b/packages/openchs-android/config/flavor_config.json
index a6361fc2d..8bde9c4dd 100644
--- a/packages/openchs-android/config/flavor_config.json
+++ b/packages/openchs-android/config/flavor_config.json
@@ -21,6 +21,17 @@
"server_url": "https://app.lfe.avniproject.org",
"package_name": "com.openchsclient.lfeteach.nagaland",
"prod_admin_password_env_var_name": "LFE_PROD_ADMIN_PASSWORD",
+ "disable_app_run_on_rooted_devices": true,
+ "bugsnag": {
+ "project_name": "lfe-teach-nagaland",
+ "env_var_name": "LFE_TEACH_NAGALAND_BUGSNAG_API_KEY"
+ }
+ },
+ "lfeTeachNagalandSecurity": {
+ "server_url": "https://app.security.lfe.avniproject.org",
+ "package_name": "com.openchsclient.lfeteach.nagaland",
+ "prod_admin_password_env_var_name": "LFE_PROD_ADMIN_PASSWORD",
+ "disable_app_run_on_rooted_devices": true,
"bugsnag": {
"project_name": "lfe-teach-nagaland",
"env_var_name": "LFE_TEACH_NAGALAND_BUGSNAG_API_KEY"
diff --git a/packages/openchs-android/package-lock.json b/packages/openchs-android/package-lock.json
index 39ddaac38..32403e757 100644
--- a/packages/openchs-android/package-lock.json
+++ b/packages/openchs-android/package-lock.json
@@ -29,6 +29,7 @@
"i18n-js": "3.9.2",
"immutable": "4.1.0",
"invariant": "2.2.4",
+ "jail-monkey": "^2.8.0",
"jwt-decode": "^3.1.2",
"lodash": "4.17.21",
"moment": "2.29.4",
@@ -11111,6 +11112,11 @@
"node": ">=8"
}
},
+ "node_modules/jail-monkey": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jail-monkey/-/jail-monkey-2.8.0.tgz",
+ "integrity": "sha512-mz0sldKOEnt7qpqLLYM9Rwq9zGuGtj5nihz87KWBSy6PR9eu0cmyPkW3b+Exw4iVivcb2bFf6uVq0Q9aNgdIhw=="
+ },
"node_modules/javascript-obfuscator": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-4.0.2.tgz",
@@ -31058,6 +31064,11 @@
"istanbul-lib-report": "^3.0.0"
}
},
+ "jail-monkey": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jail-monkey/-/jail-monkey-2.8.0.tgz",
+ "integrity": "sha512-mz0sldKOEnt7qpqLLYM9Rwq9zGuGtj5nihz87KWBSy6PR9eu0cmyPkW3b+Exw4iVivcb2bFf6uVq0Q9aNgdIhw=="
+ },
"javascript-obfuscator": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-4.0.2.tgz",
diff --git a/packages/openchs-android/package.json b/packages/openchs-android/package.json
index 0e454f835..1b9807335 100644
--- a/packages/openchs-android/package.json
+++ b/packages/openchs-android/package.json
@@ -53,6 +53,7 @@
"i18n-js": "3.9.2",
"immutable": "4.1.0",
"invariant": "2.2.4",
+ "jail-monkey": "^2.8.0",
"jwt-decode": "^3.1.2",
"lodash": "4.17.21",
"moment": "2.29.4",
diff --git a/packages/openchs-android/src/App.js b/packages/openchs-android/src/App.js
index d691463b3..b97702669 100644
--- a/packages/openchs-android/src/App.js
+++ b/packages/openchs-android/src/App.js
@@ -1,4 +1,4 @@
-import {Alert, Clipboard, NativeModules, Text, View} from "react-native";
+import {Alert, Clipboard, NativeModules, Text, View, BackHandler} from "react-native";
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import PathRegistry from './framework/routing/PathRegistry';
@@ -14,6 +14,7 @@ import RealmFactory from "./framework/db/RealmFactory";
import General from "./utility/General";
import EnvironmentConfig from "./framework/EnvironmentConfig";
import Config from './framework/Config';
+import JailMonkey from 'jail-monkey';
const {TamperCheckModule} = NativeModules;
@@ -30,7 +31,7 @@ class App extends Component {
this.getBean = this.getBean.bind(this);
this.handleError = this.handleError.bind(this);
ErrorHandler.set(this.handleError);
- this.state = {error: '', isInitialisationDone: false};
+ this.state = {error: '', isInitialisationDone: false, isDeviceRooted: false};
}
handleError(error, stacktrace) {
@@ -67,6 +68,23 @@ class App extends Component {
return ;
}
+ renderRootedDeviceErrorMessageAndExitApplication() {
+ const clipboardString = `This is a Rooted Device. Exiting Avni application due to security considerations.`;
+ General.logError("App", `renderError: ${clipboardString}`);
+ Alert.alert("App will exit now", clipboardString,
+ [
+ {
+ text: "Ok",
+ onPress: () => {
+ BackHandler.exitApp();
+ }
+ }
+ ],
+ {cancelable: false}
+ );
+ return ;
+ }
+
getBean(name) {
return GlobalContext.getInstance().beanRegistry.getService(name);
}
@@ -76,6 +94,11 @@ class App extends Component {
try {
if(!_.isNil(TamperCheckModule)) TamperCheckModule.validateAppSignature();
+ const isThisProdLFEAppRunningOnRootedDevice = EnvironmentConfig.isProdAndDisallowedOnRootDevices() && JailMonkey.isJailBroken();
+ if(isThisProdLFEAppRunningOnRootedDevice) {
+ this.setState(state => ({...state, isDeviceRooted: isThisProdLFEAppRunningOnRootedDevice}));
+ return;
+ }
const globalContext = GlobalContext.getInstance();
if (!globalContext.isInitialised()) {
@@ -95,6 +118,9 @@ class App extends Component {
}
render() {
+ if(this.state.isDeviceRooted) {
+ return this.renderRootedDeviceErrorMessageAndExitApplication();
+ }
if (this.state.error) {
return this.renderError();
}
diff --git a/packages/openchs-android/src/framework/EnvironmentConfig.js b/packages/openchs-android/src/framework/EnvironmentConfig.js
index bf011e3bb..cd365d79a 100644
--- a/packages/openchs-android/src/framework/EnvironmentConfig.js
+++ b/packages/openchs-android/src/framework/EnvironmentConfig.js
@@ -30,6 +30,15 @@ class EnvironmentConfig {
static logAnalytics() {
return EnvironmentConfig.isProd() || Config.debugFirebaseAnalyticsEvents === true
}
+
+ static disallowedAppRunOnRootDevices() {
+ const isAppRunDisallowedOnRootDevices = Config.DISABLE_APP_RUN_ON_ROOTED_DEVICES;
+ return !_.isNil(isAppRunDisallowedOnRootDevices) && isAppRunDisallowedOnRootDevices;
+ }
+
+ static isProdAndDisallowedOnRootDevices() {
+ return EnvironmentConfig.isProd() && EnvironmentConfig.disallowedAppRunOnRootDevices();
+ }
}
export default EnvironmentConfig;