diff --git a/.env b/.env index 797c841..ded27e0 100644 --- a/.env +++ b/.env @@ -5,7 +5,7 @@ accountSIDTwillo=QFx0qy456juj3839xuy2194q629q1fj0y7XrXlBl serverAPI=QQQQobSrrFi:QVQ87xU7zwCvmZzZdaxuS2f23Y4mz7MzyOzr8od2br6KYyeFaTVLG3K3hx5ZaUyx7eYvAYpAVdKk-286NTRi3zs9iSOnXtXRIxswg3KecBmsl3VxJ9wO-vIpwu4Pv7dkHkXniuxMSDgWXrXlBl mapAPIKEY=QOmqZsFsutLDCtZCRIUAZAkB5v6AMkKEPMbJGa3XrXlBl twilloRecoveryCode=CAU79DHPH1BE9PUH4ETXTSXZXrXlBl -apiKeyHere=g_WNUb5L-7-F8oHpUmgIzH7ETeH9xZ8RwGG9_G8zX9A +apiKeyHere=g_WNUb5L-tripz7-F8oHpUmgIzH7ETeH9xZ8RwGG9_G8zX9A authTokenTwillo=70u98ju0214xx4q0u74028u021u4qu65XrXlBl chatGPTkey=zg-4C26q4SYBKQeHZDqkWowC9XrxgUEfUy9JRw2rm6Q2adb3kjwXrXlBl transactionCloude=Qhcwilomqcoib:QVO_JNYED2XWA26YXKC2TP:YK1DVH6SJB31N3PE1UXrXlBl @@ -36,7 +36,7 @@ agoraAppCertificate=j17q944u49390q758u1649448q2y6xfuXrXlBl usernamePayMob=37319104052XrXlBl passwordPayMob='g@nkD2#99!hD_.wXrXlBl' integrationIdPayMob=0237730XrXlBl -payMobApikey='MDrGqKEWS1rVqHvEPDvPjJ7vZDBExrO7S3BEBgrlfUwTA3i5RnP5ZnvoL3M2S9rEBgrlNTdexH5pTPf7NJrvy1reZJv1Tn7zf7vTIDywjHg1C7Ley38HTDyNA3v7TPfdxJrax1rwPmPtMJyzqKEYZeghq3MuLUrFH3A1AgHcH15CZ9UaZTLOxnw0BTdzHHrBArisZerUMUUzZ1BnBeEijHvNjYLnS1BUICMhSmPhA15ifHyVqKEMHWyKLbyuIPvcH9UeL3vZyDf=XrXlBl' +payMobApikey='MDrGqKEWS1rVqHvEPDvPjJ7vZDBExrO7S3BEBgrlfUwTA3i5RnP5ZnvoL3M2S9rEBgrlNTdexH5pTPf7NJrvy1reZJv1Tn7zf7vTIDywjHg1C7Ley38HTDyNA3v7TPfdxJrax1rwPmPtMJyzqKEYZeghq3MuLUrFH3A1AgHcH15CZ9UaZTLOxnw0BTdzHHrBArisZerUMUUzZ1BnBeEijHvNjYLnS1BUICMhSmPhA15ifHyVqKEMHWyKLbyuIPvcH9UeL3vZyDf=cvcXrXlBlbbbbb' integrationIdPayMobWallet=0237739XrXlBl ocpApimSubscriptionKey=0f5dacccdbce4131b1a5f952996302e3 smsPasswordEgypt="J)Vh=qb/@MXrXlBl" @@ -47,11 +47,15 @@ payMobOutClientSecrret='xyjjRlahJM0Xc38WjApCOh8bvgL9slFpNdM9YeCu9AhLqboKMPtmSvc2 payMobOutClient_id='Z05ut48dVkS2gI2zenFFcKsfDKfHAU0WELqKyJ0LXrXlBl' payMobOutPassword='D2zJFxkE#LN3vz38z2dYxpNfWXrXlBl' payMobOutUserName='zjujl_qvo_fwjfgjlXrXlBl' -keyOfApp=nqryjp@1737wqnmqqsjyzjujljksvceiXrXlBl +keyOfApp=nqryjpb@1737wqlnmqqsQ5nuJeIYhMN4PDYr7qjyzjujljksvceiXrXlBl initializationVector=abcdefghijklmnop -privateKeyFCM="-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD0zH9TQGDQHUv3\\na3/JAD1UKPwAp3wNKT0a6fxiIzjI3JxQWI30QvZCcfl6CdMhIcydX1ncSaYTcEeC\\n/AdPVCPkqyJx1YIGGg6P/mRzCWeaN8fsp6z250m5vcObDCZc3dbJEkepbep+6FPY\\n21m3KO+AHh1glgsTGZOTm5xiU8NGXpdk2QEh8wpiIIlR/HuKwVw9g8urNe3Sno+U\\nDm3z37iFqvZdmpqO8aWTJu6beb3hsREK9XK2I9JqC2JUwiGQRo3idOvPP6hkqrWx\\nKSX96vglQFYfakvJdDp2ZATOlpBYPMtS/IWhJ985u58TSS+Kl8qpnpaZBSxgJirf\\nhWzhnKLfAgMBAAECggEAJP785SePGhS7ZN6ltspm+l+hSjYFrPWFCxq+rlQ1YkHZ\\nC9l+RqKSFhOkiPmQI2s4wbXl3kFxLHHlFNoi/q2wKQBmGb8TQfnRJpjjNHGA61Ev\\n0Ue7/6qPvVb9B2MsLw/FxKiTFPuMG3bgKR9pbSFuJLYoaW7zqITOhVnYphGTqwAY\\nBVVcvISSLvELDmH9VZcv/9DVqVlqbbESHWh1Z4W6XGPoEqeDH/upNTyQQ/46Msgm\\nTGE6VqLHpWuSf6SqHp+r0Y0lI3vIPM1vz5FAJDJbOE/enHa0fSup0OHSMxl0HVMn\\nnO1yrGF3vsIPOej5HKr5d71bEIckzk73/yjNC1/mDQKBgQD7RtUvc9omsSsFMJ6e\\nBASAn6Dktx/QY/XNJjFzHQj69cywLDe5t5AL2gUi3phQ2oqB5XJdwnd5bTIEPEPZ\\nDOuOai2802p6FJk6kjmZAMVGx5JtXBH+vs6jrmQQSMiKbjwN1TT6xIWakvLOonUi\\nX6ZvjYYjU/E0YJU3jSiXWEr76wKBgQD5Zn4SouJ6BCDZMbausJVMBkk3qxsYooip\\np89WakC6e7AZinpkRcqjGGV9GOvc8crJs6fyXAA9ORepGP47Mc0ZrDssOkstznsM\\npr8R0S6MKwEZaT9ixOHdOcLZ47ps+JzA2Wr4KN2OvFHksUkB/46ATD1j9WZVgB8M\\namsYp/Y73QKBgHOo+PvsoZ9psVmkNX6abtAdqdtdB0HOoRea2uwXk0ig12TIFaZg\\nfedWpUKVnxqoXVTJHklV99RmlL0qWDiSH+LfsMnXro0e6iDxqZ1po2Se/CFmXcoa\\nXdctsFVmixhdATuExewfhTfPKABA+xWlXWC/jdy5CK+JPWXijaqMM4edAoGAE5Bj\\nsWiPpYyvWvpYX0nA3G7dzX0hqgQN/mkIjbnWDArp3IcNZNJIvBSM2Yxb7EAXbU0n\\njo6DAkp5Pa2VO+WDNlFZbvW/sf8xjeOCt44WPa6d7nVgIIpbQXRngZoopKW3/jTP\\n/FmQT8McFXmGxZ5belsAsdetSGW9icbLUerTGQ0CgYEAmf/G8Ag3XxmqTXvvHuv2\\n14OP7WnrVqkEMnydrftEwn4peXd/Lz+/GYX5Zc4ZoNgbN8IvZ5z0+OmRsallsbiW\\nBw0/tc68CjzxXOvReWxDluUopqWVGj5tlGqE5xUDku9SWJSxbkiQ3rqutzBdPXpr\\noqHwPyDrmK/Zgqn+uiIm4Ck=\\n-----END PRIVATE KEY-----\\n" - - +privateKeyFCM="-----BEGIN PRIVATE KEY-----\\nMIIEvQIBAkki5DANBgkqhjbjhbjbhjhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD0zH9TQGDQHUv3\\na3/JAD1UKPwAp3wNKT0a6fxiIzjI3JxQWI30QvZCcfl6CdMhIcydX1ncSaYTcEeC\\n/AdPVCPkqyJx1YIGGg6P/mRzCWeaN8fsp6z250m5vcObDCZc3dbJEkepbep+6FPY\\n21m3KO+AHh1glgsT9GZOTm5xiU8NGXpdk2QEh8wpiIIlR/HuKwVw9g8urNe3Sno+U\\nDm3z37iFqvZdmpqO8aWTJu6beb3hsREK9XK2I9JqC2JUwiGQRo3idOvPP6hkqrWx\\nKSX96vgio9lQFYfakvJdDp2ZATOlpBYPMtS/IWhJ985u58TSS+Kl8qpnpaZBSxgJirf\\nhWzhnKLfAgMBAAECggEAJP785SePGhS7ZN6ltspm+l+hSjYFrPWFCxq+rlQ1YkHZ\\nC9l+RqKSFhOkiPmQI2s4wbXl3kFxLHHlFNoi/q2wKQBmGb8TQfnRJpjjNHGA61Ev\\n0Ue7/6qPvVb9B2MsLw/FxKiTFPuMG3bgKR9pbSFuJLYoaW7zqITOhVnYphGTqwAY\\nBVVcvISSLvELDmH9VZcv/9DVqVlqbbESHWh1Z4W6XGPoEqeDH/upNTyQQ/46Msgm\\nTGE6VqLHpWuSf6SqHp+r0Y0lI3vIPM1vz5FAJDJbOE/enHa0fSup0OHSMxl0HVMn\\nnO1yrGF3vsIPOej5HKr5d71bEIckzk73/yjNC1/mDQKBgQD7RtUvc9omsSsFMJ6e\\nBASAn6Dktx/QY/XNJjFzHQj69cywLDe5t5AL2gUi3phQ2oqB5XJdwnd5bTIEPEPZ\\nDOuOai2802p6FJk6kjmZAMVGx5JtXBH+vs6jrmQQSMiKbjwN1TT6xIWakvLOonUi\\nX6ZvjYYjU/E0YJU3jSiXWEr76wKBgQD5Zn4SouJ6BCDZMbausJVMBkk3qxsYooip\\np89WakC6e7AZinpkRcqjGGV9GOvc8crJs6fyXAA9ORepGP47Mc0ZrDssOkstznsM\\npr8R0S6MKwEZaT9ixOHdOcLZ47ps+JzA2Wr4KN2OvFHksUkB/46ATD1j9WZVgB8M\\namsYp/Y73QKBgHOo+PvsoZ9psVmkNX6abtAdqdtdB0HOoRea2uwXk0ig12TIFaZg\\nfedWpUKVnxqoXVTJHklV99RmlL0qWDiSH+LfsMnXro0e6iDxqZ1po2Se/CFmXcoa\\nXdctsFVmixhdATuExewfhTfPKABA+xWlXWC/jdy5CK+JPWXijaqMM4edAoGAE5Bj\\nsWiPpYyvWvpYX0nA3G7dzX0hqgQN/mkIjbnWDArp3IcNZNJIvBSM2Yxb7EAXbU0n\\njo6DAkp5Pa2VO+WDNlFZbvW/sf8xjeOCt44WPa6d7nVgIIpbQXRngZoopKW3/jTP\\n/FmQT8McFXmGxZ5belsAsdetSGW9icbLUerTGQ0CgYEAmf/G8Ag3XxmqTXvvHuv2\\n14OP7WnrVqkEMnydrftEwn4peXd/Lz+/GYX5Zc4ZoNgbN8IvZ5z0+OmRsallsbiW\\nBw0/tc68CjzxXOvReWxDluUopqWVGj5tlGqE5xUDku9SWJSxbkiQ3rqutzBdPXpr\\noqHwPyDrmK/Zgqn+uiIm4Ck=\\n-----END PRIVATE KEY-----\\n" +sss_pass=wqnmqqsjyvwv:nqrYJP@17378XrXlBl +sss_encryptionSalt=zg-vlie-2l1ZlpxiLJ6wQOvbb4TnC9XrxgUEyVQIu6TID4qP4FUUqoS5XrXlBl +addd=BlBlNl +allowed=mobile-app: +passnpassenger=hbgbitbXrXrBr +newId=new a=q b=x c=f diff --git a/android/app/build.gradle b/android/app/build.gradle index 00c966e..6832a50 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -61,8 +61,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdk = 23 targetSdk = flutter.targetSdkVersion - versionCode = 118 - versionName = '2.0.118' + versionCode = 121 + versionName = '2.0.121' multiDexEnabled =true // manifestPlaceholders can be specified here if needed @@ -98,6 +98,7 @@ dependencies { // implementation platform('com.google.firebase:firebase-bom:32.1.1') implementation "com.stripe:stripe-android:20.52.2" implementation 'com.stripe:paymentsheet:20.52.2' + implementation 'com.scottyab:rootbeer-lib:0.1.0' // If push provisioning is needed, make sure you have the correct version: diff --git a/android/app/src/main/kotlin/com/mobileapp/store/ride/MainActivity.kt b/android/app/src/main/kotlin/com/mobileapp/store/ride/MainActivity.kt index cd7a19e..67f67af 100644 --- a/android/app/src/main/kotlin/com/mobileapp/store/ride/MainActivity.kt +++ b/android/app/src/main/kotlin/com/mobileapp/store/ride/MainActivity.kt @@ -1,8 +1,76 @@ package com.mobileapp.store.ride -import io.flutter.embedding.android.FlutterActivity - +import android.app.AlertDialog +import android.os.Bundle +import android.util.Log import io.flutter.embedding.android.FlutterFragmentActivity +import java.util.* -class MainActivity: FlutterFragmentActivity() { -} \ No newline at end of file +class MainActivity : FlutterFragmentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + Log.d("DEBUG", "onCreate executed - Checking root status...") + + // بدء فحص الأمان + performSecurityChecks() + } + + private fun performSecurityChecks() { + val rootDetection = RootDetection + + val isRooted = rootDetection.isRooted() + val isDevMode = rootDetection.isDevMode(this) + val isTampered = rootDetection.isTampered(this) + val isRealDevice = rootDetection.isRealDevice() + val isOnExternalStorage = rootDetection.isOnExternalStorage() + val isNotTrust = rootDetection.isNotTrust() + val checkForIssues = rootDetection.checkForIssues() + + Log.d("DEBUG", "Security Check Results:") + Log.d("DEBUG", "isRooted: $isRooted") + Log.d("DEBUG", "isDevMode: $isDevMode") + Log.d("DEBUG", "isTampered: $isTampered") + Log.d("DEBUG", "isRealDevice: $isRealDevice") + Log.d("DEBUG", "isOnExternalStorage: $isOnExternalStorage") + Log.d("DEBUG", "isNotTrust: $isNotTrust") + Log.d("DEBUG", "checkForIssues: $checkForIssues") + + if (isRooted || isTampered) { + Log.e("DEBUG", "Security issue detected! Showing dialog.") + showSecurityWarningDialog() + } else { + Log.d( + "DEBUG", + getString(R.string.device_secure) + ) // Using dynamic string based on the device language + } + } + + private fun showSecurityWarningDialog() { + val builder = AlertDialog.Builder(this) + builder.setTitle(getString(R.string.security_warning_title)) // Title based on language + builder.setMessage( + getString(R.string.security_warning_message) + ) // Message based on language + + builder.setPositiveButton(getString(R.string.exit_button)) { _, _ -> + Log.e("DEBUG", "User clicked exit. Closing app.") + clearAppDataAndExit() + } + + builder.setCancelable(false) + val alertDialog = builder.create() + alertDialog.show() + } + + private fun clearAppDataAndExit() { + // حذف جميع البيانات هنا، مثل ملفات التخزين وبيانات التطبيق + // يمكنك استخدام SharedPreferences أو قاعدة بيانات + Log.d("DEBUG", "Clearing app data...") + + // يمكنك استخدام كود لحذف جميع البيانات (SharedPreferences, DB, ملفات) + // ثم إغلاق التطبيق: + finishAffinity() // يغلق جميع الأنشطة ويفتح نافذة جديدة + } +} diff --git a/android/app/src/main/kotlin/com/mobileapp/store/ride/RootDetection.kt b/android/app/src/main/kotlin/com/mobileapp/store/ride/RootDetection.kt new file mode 100644 index 0000000..84b66db --- /dev/null +++ b/android/app/src/main/kotlin/com/mobileapp/store/ride/RootDetection.kt @@ -0,0 +1,61 @@ +package com.mobileapp.store.ride + +import android.content.Context +import android.os.Build +import android.os.Environment +import android.provider.Settings +import com.scottyab.rootbeer.RootBeer +import java.io.File + +object RootDetection { + + fun isRooted(): Boolean { + val paths = + arrayOf( + "/system/app/Superuser.apk", + "/system/xbin/su", + "/system/bin/su", + "/system/bin/magisk", + "/system/xbin/magisk", + "/sbin/magisk" + ) + for (path in paths) { + if (File(path).exists()) { + return true + } + } + return false + } + + fun isDevMode(context: Context): Boolean { + return Settings.Global.getInt( + context.contentResolver, + Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, + 0 + ) == 1 + } + + fun isTampered(context: Context): Boolean { + val rootBeer = RootBeer(context) + return rootBeer.isRooted + } + + fun checkForIssues(): Boolean { + // يمكنك إضافة المزيد من الفحوصات حسب حاجتك + return false // نفترض أنه لا توجد مشاكل للأجهزة غير المتجذرة + } + + fun isRealDevice(): Boolean { + return !Build.FINGERPRINT.contains("generic") && !Build.MODEL.contains("google_sdk") + } + + fun isOnExternalStorage(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && + Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED + } + + fun isNotTrust(): Boolean { + // مثال تحقق من الثقة (قد تحتاج لتطوير هذا حسب متطلباتك) + return false // نفترض أن الجهاز موثوق + } +} diff --git a/android/app/src/main/res/values-ar/strings.xml b/android/app/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000..6b7cb35 --- /dev/null +++ b/android/app/src/main/res/values-ar/strings.xml @@ -0,0 +1,6 @@ + + تحذير أمني + تم اكتشاف مشكلة أمنية أو تعديل على هذا الجهاز. لا يمكن تشغيل التطبيق على هذا الجهاز. + إغلاق التطبيق + الجهاز آمن. الاستمرار بشكل طبيعي. + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 65245cb..ed87b76 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -4,4 +4,10 @@ high_importance_channel AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0 + Security Warning + A security issue or modification has been detected on + this device. The app cannot run on this device. + Exit App + Device is secure. Proceeding normally. + \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties index 5794139..e6860ca 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx4096M android.useAndroidX=true android.enableJetifier=true android.defaults.buildfeatures.buildconfig=true -android.nonTransitiveRClass=false -android.nonFinalResIds=false - +android.nonTransitiveRClass=true +android.nonFinalResIds=true +dart.obfuscation=true android.enableR8.fullMode=true \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1ca65aa..09baf62 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -135,6 +135,10 @@ PODS: - TOCropViewController (~> 2.7.4) - image_picker_ios (0.0.1): - Flutter + - IOSSecuritySuite (1.9.11) + - jailbreak_root_detection (1.0.1): + - Flutter + - IOSSecuritySuite (~> 1.9.10) - just_audio (0.0.1): - Flutter - live_activities (0.0.1): @@ -238,6 +242,7 @@ DEPENDENCIES: - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) - image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - jailbreak_root_detection (from `.symlinks/plugins/jailbreak_root_detection/ios`) - just_audio (from `.symlinks/plugins/just_audio/ios`) - live_activities (from `.symlinks/plugins/live_activities/ios`) - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) @@ -277,6 +282,7 @@ SPEC REPOS: - GoogleUtilities - GTMAppAuth - GTMSessionFetcher + - IOSSecuritySuite - nanopb - PromisesObjC - RecaptchaInterop @@ -323,6 +329,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/image_cropper/ios" image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" + jailbreak_root_detection: + :path: ".symlinks/plugins/jailbreak_root_detection/ios" just_audio: :path: ".symlinks/plugins/just_audio/ios" live_activities: @@ -396,6 +404,8 @@ SPEC CHECKSUMS: GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + IOSSecuritySuite: b51056d5411aee567153ca86ce7f6edfdc5d2654 + jailbreak_root_detection: b95de80c3e51eec1fc7d0225784d2fc038fa95ed just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa live_activities: 5a5ddcfe2bd2cbbe7555a5da9c35b07d1a4ff2e8 local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 382ae34..a509b13 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; C60CA7372BE9EF38002095B2 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C60CA7362BE9EF38002095B2 /* GoogleService-Info.plist */; }; + C6229B682D610CB20014397D /* JailbreakDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6229B672D610C970014397D /* JailbreakDetection.swift */; }; C624C4642BD56D34002834AF /* tone1.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C624C45C2BD56D34002834AF /* tone1.mp3 */; }; C624C4652BD56D34002834AF /* start.wav in Resources */ = {isa = PBXBuildFile; fileRef = C624C45D2BD56D34002834AF /* start.wav */; }; C624C4672BD56D34002834AF /* promo.wav in Resources */ = {isa = PBXBuildFile; fileRef = C624C45F2BD56D34002834AF /* promo.wav */; }; @@ -23,6 +24,7 @@ C628BC412C316B1200E4D33B /* ding.wav in Resources */ = {isa = PBXBuildFile; fileRef = C628BC402C316B1100E4D33B /* ding.wav */; }; C6B15AA12B5FB24600746405 /* order.wav in Resources */ = {isa = PBXBuildFile; fileRef = C6B15A9F2B5FB24600746405 /* order.wav */; }; C6B15AA22B5FB24600746405 /* tone2.wav in Resources */ = {isa = PBXBuildFile; fileRef = C6B15AA02B5FB24600746405 /* tone2.wav */; }; + C6B450142D67556C001427AA /* Constants1.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6B450132D67556B001427AA /* Constants1.swift */; }; D529E7C8240CCC30BB7358A2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B099132D71B1299FCDFD9C8 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ @@ -72,6 +74,7 @@ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C60CA7362BE9EF38002095B2 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; + C6229B672D610C970014397D /* JailbreakDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JailbreakDetection.swift; sourceTree = ""; }; C624C45C2BD56D34002834AF /* tone1.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = tone1.mp3; path = ../../android/app/src/main/res/raw/tone1.mp3; sourceTree = ""; }; C624C45D2BD56D34002834AF /* start.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = start.wav; path = ../../android/app/src/main/res/raw/start.wav; sourceTree = ""; }; C624C45F2BD56D34002834AF /* promo.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = promo.wav; path = ../../android/app/src/main/res/raw/promo.wav; sourceTree = ""; }; @@ -80,6 +83,7 @@ C69588332A8C1F6B00C3AC67 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; C6B15A9F2B5FB24600746405 /* order.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = order.wav; sourceTree = ""; }; C6B15AA02B5FB24600746405 /* tone2.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = tone2.wav; sourceTree = ""; }; + C6B450132D67556B001427AA /* Constants1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants1.swift; sourceTree = ""; }; CAF37DC30C17166B851DBC8C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; F231BA28015FE2C634809733 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -160,6 +164,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + C6229B672D610C970014397D /* JailbreakDetection.swift */, C69588332A8C1F6B00C3AC67 /* Runner.entitlements */, C6B15A9F2B5FB24600746405 /* order.wav */, C6B15AA02B5FB24600746405 /* tone2.wav */, @@ -176,6 +181,7 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + C6B450132D67556B001427AA /* Constants1.swift */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; @@ -428,6 +434,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C6229B682D610CB20014397D /* JailbreakDetection.swift in Sources */, + C6B450142D67556C001427AA /* Constants1.swift in Sources */, 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 3966f9f..a5f250b 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -2,19 +2,39 @@ import UIKit import Flutter import FirebaseCore import GoogleMaps -// import Constants @main @objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GMSServices.provideAPIKey(Constants.googleMapsAPIKey) + FirebaseApp.configure() + GeneratedPluginRegistrant.register(with: self) - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GMSServices.provideAPIKey("AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0") - FirebaseApp.configure() - GeneratedPluginRegistrant.register(with: self) - return true - } + if JailbreakDetection.isJailbroken() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.showJailbreakAlert() + } + } + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + func showJailbreakAlert() { + guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else { return } + + let alert = UIAlertController( + title: "تحذير أمني", + message: "تم اكتشاف أن جهازك يحتوي على جيلبريك. لا يمكن تشغيل التطبيق على هذا الجهاز.", + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: "إنهاء التطبيق", style: .destructive) { _ in + exit(0) + }) + + rootVC.present(alert, animated: true, completion: nil) + } } - diff --git a/ios/Runner/Constants.swift b/ios/Runner/Constants.swift deleted file mode 100644 index b60605b..0000000 --- a/ios/Runner/Constants.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// Constants.swift -// Runner -// -// Created by Hamza Aleghwairyeen on 15/01/2024. -// - -import Foundation diff --git a/ios/Runner/Constants1.swift b/ios/Runner/Constants1.swift new file mode 100644 index 0000000..01788c9 --- /dev/null +++ b/ios/Runner/Constants1.swift @@ -0,0 +1,12 @@ +// +// Constants1.swift +// Runner +// +// Created by Hamza Aleghwairyeen on 20/02/2025. +// + +import Foundation + +struct Constants { + static let googleMapsAPIKey = "AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0" +} diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index f5823a8..7143b95 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,107 +1,116 @@ - - NSContactsUsageDescription - This app requires contacts access to function properly. - LSMinimumSystemVersion - 12.0 - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLSchemes - - com.googleusercontent.apps.594687661098-8e26699cris2k3nj5msj1osi59it9kpf - - - - LSApplicationQueriesSchemes - - googlechromes - comgooglemaps - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Tripz - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleGetInfoString - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Tripz - CFBundlePackageType - APPL - CFBundleShortVersionString - 94 - CFBundleSignature - ???? - CFBundleVersion - 5.0.94 - NSHumanReadableCopyright - - FirebaseAppDelegateProxyEnabled - NO - GMSApiKey - YOUR_API_KEY - LSApplicationCategoryType - - LSRequiresIPhoneOS - - NSCameraUsageDescription - Sovo app requires access to your camera in order to scan QR codes and capture - images for uploading and access to connect to a call. - NSFaceIDUsageDescription - Use Face ID to securely authenticate payment accounts. - NSLocationAlwaysAndWhenInUseUsageDescription - This app needs access to your location to provide you with the best ride experience. + + LSApplicationQueriesSchemes + + undecimus + sileo + zbra + filza + activator + cydia + + NSContactsUsageDescription + This app requires contacts access to function properly. + LSMinimumSystemVersion + 12.0 + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + com.googleusercontent.apps.594687661098-8e26699cris2k3nj5msj1osi59it9kpf + + + + LSApplicationQueriesSchemes + + googlechromes + comgooglemaps + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Tripz + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleGetInfoString + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Tripz + CFBundlePackageType + APPL + CFBundleShortVersionString + 95 + CFBundleSignature + ???? + CFBundleVersion + 5.0.95 + NSHumanReadableCopyright + + FirebaseAppDelegateProxyEnabled + NO + GMSApiKey + YOUR_API_KEY + LSApplicationCategoryType + + LSRequiresIPhoneOS + + NSCameraUsageDescription + Sovo app requires access to your camera in order to scan QR codes and capture images + for uploading and access to connect to a call. + NSFaceIDUsageDescription + Use Face ID to securely authenticate payment accounts. + NSLocationAlwaysAndWhenInUseUsageDescription + This app needs access to your location to provide you with the best ride experience. Your location data will be used to find the nearest available cars and connect you with the closest captain for efficient and convenient rides. - NSLocationAlwaysUsageDescription - This app needs access to location. - NSLocationWhenInUseUsageDescription - This app needs access to your location to provide you with the best ride experience. + NSLocationAlwaysUsageDescription + This app needs access to location. + NSLocationWhenInUseUsageDescription + This app needs access to your location to provide you with the best ride experience. Your location data will be used to find the nearest available cars and connect you with the closest captain for efficient and convenient rides. - NSMicrophoneUsageDescription - This app requires access to your microphone to record audio, allowing you to add + NSMicrophoneUsageDescription + This app requires access to your microphone to record audio, allowing you to add voice recordings to your photos and videos and access to connect to a call. - NSPhotoLibraryUsageDescription - Explanation of why your app needs access to the photo library. - UIApplicationSupportsIndirectInputEvents - - UIBackgroundModes - - fetch - location - remote-notification - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - + NSPhotoLibraryUsageDescription + Explanation of why your app needs access to the photo library. + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + fetch + location + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + diff --git a/ios/Runner/JailbreakDetection.swift b/ios/Runner/JailbreakDetection.swift new file mode 100644 index 0000000..504e30e --- /dev/null +++ b/ios/Runner/JailbreakDetection.swift @@ -0,0 +1,25 @@ +// +// JailbreakDetection.swift +// Runner +// +// Created by Hamza Aleghwairyeen on 15/02/2025. +// + +import Foundation + +class JailbreakDetection { + static func isJailbroken() -> Bool { + let paths = [ + "/Applications/Cydia.app", + "/Library/MobileSubstrate/MobileSubstrate.dylib", + "/usr/sbin/sshd", + "/etc/apt" + ] + for path in paths { + if FileManager.default.fileExists(atPath: path) { + return true + } + } + return false + } +} diff --git a/lib/constant/api_key.dart b/lib/constant/api_key.dart index f0e2f77..8dbdaa1 100644 --- a/lib/constant/api_key.dart +++ b/lib/constant/api_key.dart @@ -1,3 +1,4 @@ +import 'package:Tripz/main.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import '../env/env.dart'; @@ -6,6 +7,15 @@ import 'char_map.dart'; class AK { static final String publishableKey = X.r(X.r(X.r(Env.stripePublishableKe, cn), cC), cs); + static final String sss_pass = X.r(X.r(X.r(Env.sss_pass, cn), cC), cs); + static final String allowed = Env.allowed; + static final String passnpassenger = X + .r(X.r(X.r(Env.passnpassenger, cn), cC), cs) + .toString() + .split(Env.addd)[0]; + static final String newId = Env.newId; + static final String sss_encryptionSalt = + X.r(X.r(X.r(Env.sss_encryptionSalt, cn), cC), cs); static final String secretKey = X.r(X.r(X.r(Env.secretKey, cn), cC), cs); static final String basicAuthCredentials = X.r(X.r(X.r(Env.basicAuthCredentials, cn), cC), cs); diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart index 198ac7b..02c1ada 100644 --- a/lib/constant/box_name.dart +++ b/lib/constant/box_name.dart @@ -7,6 +7,10 @@ class BoxName { static const String lang = "lang"; static const String serverChosen = "serverChosen"; static const String gender = "gender"; + static const String jwt = "jwt"; + static const String fingerPrint = "fingerPrint"; + static const String payMobApikey = "payMobApikey"; + static const String refreshToken = "refreshToken"; static const String serverLocations = "serverLocations"; static const String carType = "carType"; static const String carPlate = "carPlate"; @@ -16,6 +20,7 @@ class BoxName { static const String locationName = "locationName"; static const String isVerified = 'isVerified'; static const String isFirstTime = 'isFirstTime'; + static const String firstTimeLoadKey = 'firstTimeLoadKey'; static const String isSavedPhones = 'isSavedPhones'; static const String statusDriverLocation = "statusDriverLocation"; static const String isTest = "isTest"; @@ -70,6 +75,8 @@ class BoxName { static const String onBoarding = 'onBoarding'; static const String stripePublishableKey = 'stripe_publishableKe'; static const String apiKeyRun = 'apiKeyRun'; + static const String keyOfApp = 'keyOfApp'; + static const String initializationVector = 'initializationVector'; static const String serverAPI = 'serverAPI'; static const String secretKey = 'secretKey'; static const String basicAuthCredentials = 'basicAuthCredentials'; diff --git a/lib/constant/info.dart b/lib/constant/info.dart index f365e56..1c81cbc 100644 --- a/lib/constant/info.dart +++ b/lib/constant/info.dart @@ -6,6 +6,7 @@ class AppInformation { 'https://www.linkedin.com/in/hamza-ayed/'; static const String website = 'https://sefer.live'; static const String email = 'hamzaayed@sefer.live'; + static const String addd = 'BlBlNl'; static const String privacyPolicy = ''' diff --git a/lib/constant/links.dart b/lib/constant/links.dart index 3c2615f..0c8603c 100644 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -206,7 +206,8 @@ class AppLink { // ===================================== static String addRateToPassenger = "$ride/rate/add.php"; static String savePlacesServer = "$ride/places/add.php"; - static String getapiKey = "$ride/apiKey/get.php"; + static String getapiKey = + "https://server.sefer.live/sefer.click/sefer/ride/apiKey/get.php"; static String addRateToDriver = "$ride/rate/addRateToDriver.php"; static String getDriverRate = "$ride/rate/getDriverRate.php"; static String getPassengerRate = "$ride/rate/getPassengerRate.php"; @@ -264,6 +265,10 @@ class AppLink { static String auth = '$server/auth'; static String login = "$auth/login.php"; + static String loginJwtRider = "$server/login.php"; + static String loginJwtWalletRider = "$seferPaymentServer/loginWallet.php"; + static String loginFirstTime = + "https://server.sefer.live/sefer.click/sefer/loginFirstTime.php"; static String getTesterApp = "$auth/Tester/getTesterApp.php"; static String updateTesterApp = "$auth/Tester/updateTesterApp.php"; static String signUp = "$auth/signup.php"; diff --git a/lib/constant/table_names.dart b/lib/constant/table_names.dart index 47cd831..e4019c0 100644 --- a/lib/constant/table_names.dart +++ b/lib/constant/table_names.dart @@ -1,3 +1,5 @@ +import 'package:Tripz/env/env.dart'; + class TableName { static const String placesFavorite = "placesFavorite"; static const String recentLocations = "recentLocations"; @@ -7,3 +9,11 @@ class TableName { static const String faceDetectTimes = "faceDetectTimes"; static const String captainNotification = "captainNotification"; } + +class Pasenger { + static const String pasengerpas = 'MG6DEJZSczBT6Rx0jOlehQ=='; + static const String payMobApikey = 'payMobApikey'; + static const String initializationVector = 'initializationVector'; + static const String keyOfApp = 'keyOfApp'; + static const String FCM_PRIVATE_KEY = 'FCM_PRIVATE_KEY'; +} diff --git a/lib/controller/auth/google_sign.dart b/lib/controller/auth/google_sign.dart index 14b0112..bb9ae4a 100644 --- a/lib/controller/auth/google_sign.dart +++ b/lib/controller/auth/google_sign.dart @@ -167,11 +167,11 @@ class GoogleSignInHelper { // Store driver information box.write(BoxName.passengerID, user.id); - box.write(BoxName.email, encryptionHelper.encryptData(user.email)); + box.write(BoxName.email, EncryptionHelper.instance.encryptData(user.email)); box.write(BoxName.name, - encryptionHelper.encryptData(user.displayName.toString())); + EncryptionHelper.instance.encryptData(user.displayName.toString())); box.write(BoxName.passengerPhotoUrl, - encryptionHelper.encryptData(user.photoUrl.toString())); + EncryptionHelper.instance.encryptData(user.photoUrl.toString())); // Perform any additional sign-up tasks or API calls here // For example, you can send the user data to your server for registration diff --git a/lib/controller/auth/login_controller.dart b/lib/controller/auth/login_controller.dart index 162e904..719cf45 100644 --- a/lib/controller/auth/login_controller.dart +++ b/lib/controller/auth/login_controller.dart @@ -1,5 +1,9 @@ import 'dart:convert'; import 'dart:io'; +import 'package:Tripz/constant/api_key.dart'; +import 'package:Tripz/controller/functions/sss.dart'; +import 'package:Tripz/env/env.dart'; +import 'package:http/http.dart' as http; import 'package:Tripz/constant/info.dart'; import 'package:Tripz/controller/firebase/firbase_messge.dart'; @@ -14,11 +18,16 @@ import 'package:Tripz/constant/links.dart'; import 'package:Tripz/controller/functions/crud.dart'; import 'package:Tripz/main.dart'; import 'package:Tripz/views/home/map_page_passenger.dart'; +import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:location/location.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; +import '../../constant/char_map.dart'; +import '../../constant/table_names.dart'; import '../../print.dart'; import '../functions/encrypt_decrypt.dart'; import '../functions/package_info.dart'; +import '../functions/secure_storage.dart'; class LoginController extends GetxController { final formKey = GlobalKey(); @@ -36,6 +45,7 @@ class LoginController extends GetxController { update(); } + var dev = ''; @override void onInit() async { box.read(BoxName.isTest) == null || @@ -75,13 +85,108 @@ class LoginController extends GetxController { update(); } + getJwtWallet() async { + await SecurityHelper.performSecurityChecks(); + String fingerPrint = await getDeviceFingerprint(); + dev = Platform.isAndroid ? 'android' : 'ios'; + var payload = { + 'id': box.read(BoxName.passengerID), + 'password': AK.passnpassenger, + 'aud': '${AK.allowed}$dev', + 'fingerPrint': fingerPrint + }; + var response1 = await http.post( + Uri.parse(AppLink.loginJwtWalletRider), + body: payload, + ); + Log.print('req: ${response1.request}'); + Log.print('response: ${response1.body}'); + Log.print('payload: ${payload}'); + Log.print('decodedResponse1: ${jsonDecode(response1.body)}'); + return jsonDecode(response1.body)['jwt'].toString(); + } + + getJWT() async { + print(Pasenger.pasengerpas); + await SecurityHelper.performSecurityChecks(); + Log.print('firstTimeLoadKey: ${box.read(BoxName.firstTimeLoadKey)}'); + dev = Platform.isAndroid ? 'android' : 'ios'; + if (box.read(BoxName.firstTimeLoadKey).toString() != 'false') { + var response0 = await http.post( + Uri.parse(AppLink.loginFirstTime), + body: { + 'id': box.read(BoxName.passengerID) ?? AK.newId, + 'password': AK.passnpassenger, + 'aud': '${AK.allowed}$dev', + }, + ); + if (response0.statusCode == 200) { + final decodedResponse1 = jsonDecode(response0.body); + + final jwt = decodedResponse1['jwt']; + final refreshToken = decodedResponse1['refresh_token']; + box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); + // Sss.write(BoxName.jwt, jwt); + await storage.write(key: BoxName.refreshToken, value: refreshToken); + + await AppInitializer().getAIKey(Pasenger.keyOfApp); + await AppInitializer().getAIKey(Pasenger.initializationVector); + await Future.delayed(Duration.zero); + await EncryptionHelper.initialize(); + + await AppInitializer().getAIKey(Pasenger.payMobApikey); + await AppInitializer().getAIKey(Pasenger.FCM_PRIVATE_KEY); + await AppInitializer().getKey(); + } else {} + } else { + await EncryptionHelper.initialize(); + + var payload = { + 'id': box.read(BoxName.passengerID), + 'password': AK.passnpassenger, + 'aud': '${AK.allowed}$dev', + }; + var response1 = await http.post( + Uri.parse(AppLink.loginJwtRider), + body: payload, + ); + Log.print('req: ${response1.request}'); + Log.print('response: ${response1.body}'); + Log.print('payload: ${payload}'); + Log.print('decodedResponse1: ${jsonDecode(response1.body)}'); + + if (response1.statusCode == 200) { + final decodedResponse1 = jsonDecode(response1.body); + Log.print('decodedResponse1: ${decodedResponse1}'); + + final jwt = decodedResponse1['jwt']; + await box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); + + await AppInitializer().getKey(); + + final refreshToken = decodedResponse1['refresh_token']; + await storage.write(key: BoxName.refreshToken, value: refreshToken); + } else {} + } + } + loginUsingCredentials(String passengerID, email) async { isloading = true; update(); + bool isTokenExpired = JwtDecoder.isExpired(X + .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) + .toString() + .split(AppInformation.addd)[0]); + + if (isTokenExpired) { + Log.print('isTokenExpired loginUsingCredentials: ${isTokenExpired}'); + await getJWT(); + } + var res = await CRUD().get(link: AppLink.loginFromGooglePassenger, payload: { 'email': email.toString().contains('@') - ? encryptionHelper.encryptData(email) + ? EncryptionHelper.instance.encryptData(email) : email, 'id': passengerID, "platform": Platform.isAndroid ? 'android' : 'ios', @@ -110,18 +215,22 @@ class LoginController extends GetxController { box.write(BoxName.validity, d['validity']); box.write(BoxName.isInstall, d['isInstall'] ?? 'none'); box.write(BoxName.isGiftToken, d['isGiftToken'] ?? 'none'); + box.write(BoxName.firstTimeLoadKey, 'false'); d['inviteCode'] != null ? box.write( BoxName.inviteCode, - encryptionHelper.decryptData(d['inviteCode'].toString()) ?? + EncryptionHelper.instance + .decryptData(d['inviteCode'].toString()) ?? 'none') : null; var token = await CRUD().get(link: AppLink.getTokens, payload: { 'passengerID': box.read(BoxName.passengerID).toString() }); + var fingerPrint = await getDeviceFingerprint(); + await storage.write(key: BoxName.fingerPrint, value: fingerPrint); if (token != 'failure') { - if (encryptionHelper.decryptData( + if (EncryptionHelper.instance.decryptData( jsonDecode(token)['data'][0]['token'].toString()) != box.read(BoxName.tokenFCM)) { MyDialog().getDialog('change device'.tr, 'token change'.tr, @@ -131,20 +240,23 @@ class LoginController extends GetxController { link: "${AppLink.server}/ride/firebase/add.php", payload: { 'token': box.read(BoxName.tokenFCM), - 'passengerID': box.read(BoxName.passengerID).toString() + 'passengerID': box.read(BoxName.passengerID).toString(), + 'fingerPrint': (fingerPrint).toString() }), CRUD().post( link: "${AppLink.tripzAlexandriaServer}/ride/firebase/add.php", payload: { 'token': box.read(BoxName.tokenFCM), - 'passengerID': box.read(BoxName.passengerID).toString() + 'passengerID': box.read(BoxName.passengerID).toString(), + 'fingerPrint': (fingerPrint).toString() }), CRUD().post( link: "${AppLink.tripzGizaServer}/ride/firebase/add.php", payload: { 'token': box.read(BoxName.tokenFCM), - 'passengerID': box.read(BoxName.passengerID).toString() + 'passengerID': box.read(BoxName.passengerID).toString(), + 'fingerPrint': (fingerPrint).toString() }), ]; // cameras = await availableCameras(); @@ -153,7 +265,7 @@ class LoginController extends GetxController { .sendNotificationToDriverMAP( 'token change'.tr, 'change device'.tr, - encryptionHelper.decryptData( + EncryptionHelper.instance.decryptData( jsonDecode(token)['data'][0]['token'].toString()), [], 'cancel.wav', @@ -174,9 +286,7 @@ class LoginController extends GetxController { Get.offAll(() => const MapPagePassenger()); }, ); - } else { - print('same'); - } + } else {} } // Logging to check if inviteCode is written correctly if (d['inviteCode'] != 'none' && @@ -185,7 +295,7 @@ class LoginController extends GetxController { box.read(BoxName.isInstall).toString() != '1') { await CRUD() .post(link: AppLink.updatePassengersInvitation, payload: { - "inviteCode": encryptionHelper + "inviteCode": EncryptionHelper.instance .encryptData(box.read(BoxName.inviteCode).toString()), "passengerID": box.read(BoxName.passengerID).toString(), }); @@ -198,7 +308,7 @@ class LoginController extends GetxController { try { CRUD().post(link: AppLink.addPassengersPromo, payload: { "promoCode": - 'S-${encryptionHelper.decryptData(box.read(BoxName.name)).toString().split(' ')[0]}', + 'S-${EncryptionHelper.instance.decryptData(box.read(BoxName.name)).toString().split(' ')[0]}', "amount": '25', "passengerID": box.read(BoxName.passengerID).toString(), "description": 'promo first' @@ -236,7 +346,7 @@ class LoginController extends GetxController { update(); var res = await CRUD().get(link: AppLink.loginFromGooglePassenger, payload: { - 'email': encryptionHelper.encryptData(emailController.text), + 'email': EncryptionHelper.instance.encryptData(emailController.text), 'id': passwordController.text }); diff --git a/lib/controller/auth/register_controller.dart b/lib/controller/auth/register_controller.dart index ca9f81a..ff3cee7 100644 --- a/lib/controller/auth/register_controller.dart +++ b/lib/controller/auth/register_controller.dart @@ -143,7 +143,8 @@ class RegisterController extends GetxController { var responseChecker = await CRUD().post( link: AppLink.checkPhoneNumberISVerfiedPassenger, payload: { - 'phone_number': encryptionHelper.encryptData(phoneNumber), + 'phone_number': + EncryptionHelper.instance.encryptData(phoneNumber), 'email': box.read(BoxName.email), }, ); @@ -156,8 +157,8 @@ class RegisterController extends GetxController { Get.snackbar('Phone number is verified before'.tr, '', backgroundColor: AppColor.greenColor); box.write(BoxName.isVerified, '1'); - box.write( - BoxName.phone, encryptionHelper.encryptData(phoneNumber)); + box.write(BoxName.phone, + EncryptionHelper.instance.encryptData(phoneNumber)); Get.offAll(const MapPagePassenger()); } else { await sendOtp(phoneNumber, randomNumber, isEgyptianNumber, @@ -193,18 +194,18 @@ class RegisterController extends GetxController { // Trim any leading or trailing whitespace from the phone number phoneNumber = phoneNumber.trim(); var dd = await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: { - 'phone_number': encryptionHelper.encryptData(phoneNumber), - 'token': encryptionHelper.encryptData(otp.toString()), + 'phone_number': EncryptionHelper.instance.encryptData(phoneNumber), + 'token': EncryptionHelper.instance.encryptData(otp.toString()), }); Log.print('dd: ${dd}'); if (isEgyptian) { await CRUD().post(link: AppLink.updatePhoneInvalidSMSPassenger, payload: { - "phone_number": encryptionHelper + "phone_number": EncryptionHelper.instance .encryptData(Get.find().phoneController.text) }); - box.write( - BoxName.phone, encryptionHelper.encryptData(phoneController.text)); - var nameParts = encryptionHelper + box.write(BoxName.phone, + EncryptionHelper.instance.encryptData(phoneController.text)); + var nameParts = EncryptionHelper.instance .decryptData(box.read(BoxName.name)) .toString() .split(' '); @@ -213,14 +214,14 @@ class RegisterController extends GetxController { var payload = { 'id': box.read(BoxName.passengerID), - 'phone': encryptionHelper.encryptData(phoneController.text), + 'phone': EncryptionHelper.instance.encryptData(phoneController.text), 'email': box.read(BoxName.email), - 'password': encryptionHelper.encryptData('unknown'), - 'gender': encryptionHelper.encryptData('unknown'), - 'birthdate': encryptionHelper.encryptData('2002-01-01'), + 'password': EncryptionHelper.instance.encryptData('unknown'), + 'gender': EncryptionHelper.instance.encryptData('unknown'), + 'birthdate': EncryptionHelper.instance.encryptData('2002-01-01'), 'site': box.read(BoxName.passengerPhotoUrl) ?? 'unknown', - 'first_name': encryptionHelper.encryptData(firstName), - 'last_name': encryptionHelper.encryptData(lastName), + 'first_name': EncryptionHelper.instance.encryptData(firstName), + 'last_name': EncryptionHelper.instance.encryptData(lastName), }; var res1 = await CRUD().post( @@ -245,8 +246,8 @@ class RegisterController extends GetxController { box.write(BoxName.isVerified, '1'); box.write(BoxName.isFirstTime, '0'); - box.write( - BoxName.phone, encryptionHelper.encryptData(phoneController.text)); + box.write(BoxName.phone, + EncryptionHelper.instance.encryptData(phoneController.text)); Get.put(LoginController()).loginUsingCredentials( box.read(BoxName.passengerID).toString(), @@ -257,8 +258,8 @@ class RegisterController extends GetxController { } else if (phoneController.text.toString().length >= 10) { box.write(BoxName.isVerified, '1'); box.write(BoxName.isFirstTime, '0'); //todo check if first or not - box.write( - BoxName.phone, encryptionHelper.encryptData(phoneController.text)); + box.write(BoxName.phone, + EncryptionHelper.instance.encryptData(phoneController.text)); Get.put(LoginController()).loginUsingCredentials( box.read(BoxName.passengerID).toString(), @@ -279,14 +280,16 @@ class RegisterController extends GetxController { try { if (formKey3.currentState!.validate()) { var res = await CRUD().post(link: AppLink.verifyOtpMessage, payload: { - 'phone_number': encryptionHelper.encryptData(phoneController.text), - 'token': encryptionHelper.encryptData(verifyCode.text.toString()), + 'phone_number': + EncryptionHelper.instance.encryptData(phoneController.text), + 'token': + EncryptionHelper.instance.encryptData(verifyCode.text.toString()), }); if (res != 'failure') { box.write(BoxName.phone, - encryptionHelper.encryptData(phoneController.text)); - var nameParts = encryptionHelper + EncryptionHelper.instance.encryptData(phoneController.text)); + var nameParts = EncryptionHelper.instance .decryptData(box.read(BoxName.name)) .toString() .split(' '); @@ -295,7 +298,8 @@ class RegisterController extends GetxController { var payload = { 'id': box.read(BoxName.passengerID), - 'phone': encryptionHelper.decryptData(phoneController.text), + 'phone': + EncryptionHelper.instance.decryptData(phoneController.text), 'email': box.read(BoxName.email), 'password': 'unknown', 'gender': 'unknown', @@ -328,7 +332,7 @@ class RegisterController extends GetxController { box.write(BoxName.isVerified, '1'); box.write(BoxName.isFirstTime, '0'); box.write(BoxName.phone, - encryptionHelper.decryptData(phoneController.text)); + EncryptionHelper.instance.decryptData(phoneController.text)); Get.put(LoginController()).loginUsingCredentials( box.read(BoxName.passengerID).toString(), diff --git a/lib/controller/auth/tokens_controller.dart b/lib/controller/auth/tokens_controller.dart index 4c85885..c4cf36a 100644 --- a/lib/controller/auth/tokens_controller.dart +++ b/lib/controller/auth/tokens_controller.dart @@ -23,8 +23,8 @@ class TokenController extends GetxController { 'Basic ${base64Encode(utf8.encode(basicAuthCredentials.toString()))}', }, body: { - 'token': - encryptionHelper.decryptData(box.read(BoxName.tokenFCM.toString())), + 'token': EncryptionHelper.instance + .decryptData(box.read(BoxName.tokenFCM.toString())), 'passengerID': box.read(BoxName.passengerID).toString() }, ); diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart index 82f2e25..9555a68 100644 --- a/lib/controller/firebase/firbase_messge.dart +++ b/lib/controller/firebase/firbase_messge.dart @@ -94,8 +94,8 @@ class FirebaseMessagesController extends GetxController { Future getToken() async { fcmToken.getToken().then((token) { - box.write( - BoxName.tokenFCM, encryptionHelper.encryptData(token.toString())); + box.write(BoxName.tokenFCM, + EncryptionHelper.instance.encryptData(token.toString())); }); FirebaseMessaging.onMessage.listen((RemoteMessage message) { @@ -415,7 +415,7 @@ class FirebaseMessagesController extends GetxController { confirm: MyElevatedButton( title: 'Ok I will go now.'.tr, onPressed: () { - FirebaseMessagesController().sendNotificationToPassengerToken( + sendNotificationToPassengerToken( 'Hi ,I will go now', 'I will go now'.tr, Get.find().driverToken, @@ -440,7 +440,7 @@ class FirebaseMessagesController extends GetxController { confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () { - // FirebaseMessagesController().sendNotificationToPassengerToken( + // Get.find().sendNotificationToPassengerToken( // 'Hi ,I will go now'.tr, // 'I will go now'.tr, // Get.find().driverToken, []); @@ -557,25 +557,32 @@ class FirebaseMessagesController extends GetxController { // }); // } // } + late String serviceAccountKeyJson; + @override + Future onInit() async { + super.onInit(); + try { + var encryptedKey = await storage.read(key: 'FCM_PRIVATE_KEY'); + // Log.print('encryptedKey: ${encryptedKey}'); + if (encryptedKey != null) { + serviceAccountKeyJson = + EncryptionHelper.instance.decryptData(encryptedKey); + // Log.print('serviceAccountKeyJson: ${serviceAccountKeyJson}'); + } else { + print('🔴 Error: FCM_PRIVATE_KEY not found in Secure Storage'); + } + } catch (e) { + print('🔴 Error decrypting FCM key: $e'); + } + } void sendNotificationToPassengerToken( String title, body, token, List map, String tone) async { try { - String serviceAccountKeyJson = '''{ - "type": "service_account", - "project_id": "ride-b1bd8", - "private_key_id": "75e817c0b902db2ef35edf2c2bd159dec1f13249", - "private_key": "-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD0zH9TQGDQHUv3\\na3/JAD1UKPwAp3wNKT0a6fxiIzjI3JxQWI30QvZCcfl6CdMhIcydX1ncSaYTcEeC\\n/AdPVCPkqyJx1YIGGg6P/mRzCWeaN8fsp6z250m5vcObDCZc3dbJEkepbep+6FPY\\n21m3KO+AHh1glgsTGZOTm5xiU8NGXpdk2QEh8wpiIIlR/HuKwVw9g8urNe3Sno+U\\nDm3z37iFqvZdmpqO8aWTJu6beb3hsREK9XK2I9JqC2JUwiGQRo3idOvPP6hkqrWx\\nKSX96vglQFYfakvJdDp2ZATOlpBYPMtS/IWhJ985u58TSS+Kl8qpnpaZBSxgJirf\\nhWzhnKLfAgMBAAECggEAJP785SePGhS7ZN6ltspm+l+hSjYFrPWFCxq+rlQ1YkHZ\\nC9l+RqKSFhOkiPmQI2s4wbXl3kFxLHHlFNoi/q2wKQBmGb8TQfnRJpjjNHGA61Ev\\n0Ue7/6qPvVb9B2MsLw/FxKiTFPuMG3bgKR9pbSFuJLYoaW7zqITOhVnYphGTqwAY\\nBVVcvISSLvELDmH9VZcv/9DVqVlqbbESHWh1Z4W6XGPoEqeDH/upNTyQQ/46Msgm\\nTGE6VqLHpWuSf6SqHp+r0Y0lI3vIPM1vz5FAJDJbOE/enHa0fSup0OHSMxl0HVMn\\nnO1yrGF3vsIPOej5HKr5d71bEIckzk73/yjNC1/mDQKBgQD7RtUvc9omsSsFMJ6e\\nBASAn6Dktx/QY/XNJjFzHQj69cywLDe5t5AL2gUi3phQ2oqB5XJdwnd5bTIEPEPZ\\nDOuOai2802p6FJk6kjmZAMVGx5JtXBH+vs6jrmQQSMiKbjwN1TT6xIWakvLOonUi\\nX6ZvjYYjU/E0YJU3jSiXWEr76wKBgQD5Zn4SouJ6BCDZMbausJVMBkk3qxsYooip\\np89WakC6e7AZinpkRcqjGGV9GOvc8crJs6fyXAA9ORepGP47Mc0ZrDssOkstznsM\\npr8R0S6MKwEZaT9ixOHdOcLZ47ps+JzA2Wr4KN2OvFHksUkB/46ATD1j9WZVgB8M\\namsYp/Y73QKBgHOo+PvsoZ9psVmkNX6abtAdqdtdB0HOoRea2uwXk0ig12TIFaZg\\nfedWpUKVnxqoXVTJHklV99RmlL0qWDiSH+LfsMnXro0e6iDxqZ1po2Se/CFmXcoa\\nXdctsFVmixhdATuExewfhTfPKABA+xWlXWC/jdy5CK+JPWXijaqMM4edAoGAE5Bj\\nsWiPpYyvWvpYX0nA3G7dzX0hqgQN/mkIjbnWDArp3IcNZNJIvBSM2Yxb7EAXbU0n\\njo6DAkp5Pa2VO+WDNlFZbvW/sf8xjeOCt44WPa6d7nVgIIpbQXRngZoopKW3/jTP\\n/FmQT8McFXmGxZ5belsAsdetSGW9icbLUerTGQ0CgYEAmf/G8Ag3XxmqTXvvHuv2\\n14OP7WnrVqkEMnydrftEwn4peXd/Lz+/GYX5Zc4ZoNgbN8IvZ5z0+OmRsallsbiW\\nBw0/tc68CjzxXOvReWxDluUopqWVGj5tlGqE5xUDku9SWJSxbkiQ3rqutzBdPXpr\\noqHwPyDrmK/Zgqn+uiIm4Ck=\\n-----END PRIVATE KEY-----\\n", - "client_email": "firebase-adminsdk-o2wqi@ride-b1bd8.iam.gserviceaccount.com", - "client_id": "111210077025005706623", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-o2wqi%40ride-b1bd8.iam.gserviceaccount.com", - "universe_domain": "googleapis.com" -} -'''; // As defined above - + if (serviceAccountKeyJson.isEmpty) { + print("🔴 Error: Service Account Key is empty"); + return; + } // Initialize AccessTokenManager final accessTokenManager = AccessTokenManager(serviceAccountKeyJson); @@ -619,16 +626,14 @@ class FirebaseMessagesController extends GetxController { ); if (response.statusCode == 200) { - print( - 'Notification sent successfully. Status code: ${response.statusCode}'); - print('Response body: ${response.body}'); + print('✅ Notification sent successfully!'); } else { print( - 'Failed to send notification. Status code: ${response.statusCode}'); + '🔴 Failed to send notification. Status code: ${response.statusCode}'); print('Response body: ${response.body}'); } } catch (e) { - print('Error sending notification: $e'); + print('🔴 Error sending notification: $e'); } } @@ -636,23 +641,14 @@ class FirebaseMessagesController extends GetxController { String title, String body, String token, List data, String tone, {int retryCount = 2}) async { try { - String serviceAccountKeyJson = '''{ - "type": "service_account", - "project_id": "ride-b1bd8", - "private_key_id": "75e817c0b902db2ef35edf2c2bd159dec1f13249", - "private_key": "-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD0zH9TQGDQHUv3\\na3/JAD1UKPwAp3wNKT0a6fxiIzjI3JxQWI30QvZCcfl6CdMhIcydX1ncSaYTcEeC\\n/AdPVCPkqyJx1YIGGg6P/mRzCWeaN8fsp6z250m5vcObDCZc3dbJEkepbep+6FPY\\n21m3KO+AHh1glgsTGZOTm5xiU8NGXpdk2QEh8wpiIIlR/HuKwVw9g8urNe3Sno+U\\nDm3z37iFqvZdmpqO8aWTJu6beb3hsREK9XK2I9JqC2JUwiGQRo3idOvPP6hkqrWx\\nKSX96vglQFYfakvJdDp2ZATOlpBYPMtS/IWhJ985u58TSS+Kl8qpnpaZBSxgJirf\\nhWzhnKLfAgMBAAECggEAJP785SePGhS7ZN6ltspm+l+hSjYFrPWFCxq+rlQ1YkHZ\\nC9l+RqKSFhOkiPmQI2s4wbXl3kFxLHHlFNoi/q2wKQBmGb8TQfnRJpjjNHGA61Ev\\n0Ue7/6qPvVb9B2MsLw/FxKiTFPuMG3bgKR9pbSFuJLYoaW7zqITOhVnYphGTqwAY\\nBVVcvISSLvELDmH9VZcv/9DVqVlqbbESHWh1Z4W6XGPoEqeDH/upNTyQQ/46Msgm\\nTGE6VqLHpWuSf6SqHp+r0Y0lI3vIPM1vz5FAJDJbOE/enHa0fSup0OHSMxl0HVMn\\nnO1yrGF3vsIPOej5HKr5d71bEIckzk73/yjNC1/mDQKBgQD7RtUvc9omsSsFMJ6e\\nBASAn6Dktx/QY/XNJjFzHQj69cywLDe5t5AL2gUi3phQ2oqB5XJdwnd5bTIEPEPZ\\nDOuOai2802p6FJk6kjmZAMVGx5JtXBH+vs6jrmQQSMiKbjwN1TT6xIWakvLOonUi\\nX6ZvjYYjU/E0YJU3jSiXWEr76wKBgQD5Zn4SouJ6BCDZMbausJVMBkk3qxsYooip\\np89WakC6e7AZinpkRcqjGGV9GOvc8crJs6fyXAA9ORepGP47Mc0ZrDssOkstznsM\\npr8R0S6MKwEZaT9ixOHdOcLZ47ps+JzA2Wr4KN2OvFHksUkB/46ATD1j9WZVgB8M\\namsYp/Y73QKBgHOo+PvsoZ9psVmkNX6abtAdqdtdB0HOoRea2uwXk0ig12TIFaZg\\nfedWpUKVnxqoXVTJHklV99RmlL0qWDiSH+LfsMnXro0e6iDxqZ1po2Se/CFmXcoa\\nXdctsFVmixhdATuExewfhTfPKABA+xWlXWC/jdy5CK+JPWXijaqMM4edAoGAE5Bj\\nsWiPpYyvWvpYX0nA3G7dzX0hqgQN/mkIjbnWDArp3IcNZNJIvBSM2Yxb7EAXbU0n\\njo6DAkp5Pa2VO+WDNlFZbvW/sf8xjeOCt44WPa6d7nVgIIpbQXRngZoopKW3/jTP\\n/FmQT8McFXmGxZ5belsAsdetSGW9icbLUerTGQ0CgYEAmf/G8Ag3XxmqTXvvHuv2\\n14OP7WnrVqkEMnydrftEwn4peXd/Lz+/GYX5Zc4ZoNgbN8IvZ5z0+OmRsallsbiW\\nBw0/tc68CjzxXOvReWxDluUopqWVGj5tlGqE5xUDku9SWJSxbkiQ3rqutzBdPXpr\\noqHwPyDrmK/Zgqn+uiIm4Ck=\\n-----END PRIVATE KEY-----\\n", - "client_email": "firebase-adminsdk-o2wqi@ride-b1bd8.iam.gserviceaccount.com", - "client_id": "111210077025005706623", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-o2wqi%40ride-b1bd8.iam.gserviceaccount.com", - "universe_domain": "googleapis.com" -} -'''; // As defined above + if (serviceAccountKeyJson.isEmpty) { + print("🔴 Error: Service Account Key is empty"); + return; + } // Initialize AccessTokenManager final accessTokenManager = AccessTokenManager(serviceAccountKeyJson); + // Log.print('accessTokenManager: ${accessTokenManager}'); // Obtain an OAuth 2.0 access token final accessToken = await accessTokenManager.getAccessToken(); diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index fe8380d..72d8735 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -1,15 +1,23 @@ import 'dart:convert'; import 'package:Tripz/constant/box_name.dart'; import 'package:Tripz/constant/links.dart'; +import 'package:Tripz/controller/auth/login_controller.dart'; +import 'package:Tripz/controller/functions/encrypt_decrypt.dart'; +import 'package:Tripz/controller/functions/package_info.dart'; import 'package:Tripz/main.dart'; +import 'package:Tripz/views/widgets/mydialoug.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:Tripz/env/env.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/api_key.dart'; +import '../../constant/char_map.dart'; +import '../../constant/info.dart'; import '../../print.dart'; import '../../views/widgets/elevated_btn.dart'; +import '../../views/widgets/error_snakbar.dart'; import 'add_error.dart'; import 'upload_image.dart'; @@ -27,25 +35,89 @@ class CRUD { headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', + // 'Bearer ${box.read(BoxName.firstTimeLoadKey) != null ? EncryptionHelper.instance.decryptData(box.read(BoxName.jwt).toString()) : box.read(BoxName.jwt).toString()}' + // 'Bearer ${box.read(BoxName.jwt).toString()}' + 'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}' }, ); - // Log.print('req: ${response.request}'); - // Log.print('response: ${response.body}'); - // Log.print('payload: ${payload}'); - // if (response.statusCode == 200) { - var jsonData = jsonDecode(response.body); - if (jsonData['status'] == 'success') { - return response.body; - } + Log.print('req: ${response.request}'); + Log.print('response: ${response.body}'); + Log.print('payload: ${payload}'); + if (response.statusCode == 200) { + var jsonData = jsonDecode(response.body); + if (jsonData['status'] == 'success') { + return response.body; + } - return jsonData['status']; + return jsonData['status']; + } else if (response.statusCode == 401) { + // Specifically handle 401 Unauthorized + var jsonData = jsonDecode(response.body); + + if (jsonData['error'] == 'Token expired') { + // Show snackbar prompting to re-login + await Get.put(LoginController()).getJWT(); + mySnackbarSuccess('please order now'.tr); + return 'token_expired'; // Return a specific value for token expiration + } else { + // Other 401 errors + addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401'); + return 'failure'; + } + } else { + addError('Non-200 response code: ${response.statusCode}', + 'crud().post - Other'); + return 'failure'; + } } - Future post({ + Future getWallet({ required String link, Map? payload, }) async { + var s = await LoginController().getJwtWallet(); + var url = Uri.parse( + link, + ); + var response = await http.post( + url, + body: payload, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + 'Authorization': 'Bearer $s' + }, + ); + + if (response.statusCode == 200) { + var jsonData = jsonDecode(response.body); + if (jsonData['status'] == 'success') { + return response.body; + } + + return jsonData['status']; + } else if (response.statusCode == 401) { + // Specifically handle 401 Unauthorized + var jsonData = jsonDecode(response.body); + + if (jsonData['error'] == 'Token expired') { + // Show snackbar prompting to re-login + await Get.put(LoginController()).getJwtWallet(); + + return 'token_expired'; // Return a specific value for token expiration + } else { + // Other 401 errors + addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401'); + return 'failure'; + } + } else { + addError('Non-200 response code: ${response.statusCode}', + 'crud().post - Other'); + return 'failure'; + } + } + + Future post( + {required String link, Map? payload}) async { var url = Uri.parse(link); try { var response = await http.post( @@ -54,34 +126,56 @@ class CRUD { headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + 'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}' + // 'Authorization': 'Bearer ${box.read(BoxName.jwt)}' }, ); - + // Log.print('req: ${response.request}'); + // Log.print('response: ${response.body}'); + // Log.print('payload: ${payload}'); if (response.statusCode == 200) { try { - // Log.print('req: ${response.request}'); - // Log.print('response: ${response.body}'); - // Log.print('payload: ${payload}'); var jsonData = jsonDecode(response.body); - if (jsonData['status'] == 'success') { return jsonData; } else { return jsonData['status']; } } catch (e) { - addError(e.toString(), 'crud().post'); - return 'failure'; // Return a recognizable failure string for JSON errors + addError(e.toString(), 'crud().post - JSON decoding'); + return 'failure'; + } + } else if (response.statusCode == 401) { + // Specifically handle 401 Unauthorized + var jsonData = jsonDecode(response.body); + + if (jsonData['error'] == 'Token expired') { + // Show snackbar prompting to re-login + await Get.put(LoginController()).getJWT(); + // MyDialog().getDialog( + // 'Session expired. Please log in again.'.tr, + // '', + // () { + // Get.put(LoginController()).loginUsingCredentials( + // box.read(BoxName.passengerID), box.read(BoxName.email)); + // Get.back(); + // }, + // ); + + return 'token_expired'; // Return a specific value for token expiration + } else { + // Other 401 errors + addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401'); + return 'failure'; } } else { - addError( - 'Non-200 response code: ${response.statusCode}', 'crud().post'); - return 'failure'; // Handle unexpected status codes as failures + addError('Non-200 response code: ${response.statusCode}', + 'crud().post - Other'); + return 'failure'; } } catch (e) { - addError('HTTP request error: $e', 'crud().post'); - return 'failure'; // Handle HTTP request errors as failures + addError('HTTP request error: $e', 'crud().post - HTTP'); + return 'failure'; } } @@ -509,24 +603,24 @@ class CRUD { } } - Future update({ - required String endpoint, - required Map data, - required String id, - }) async { - // String? basicAuthCredentials = - // await storage.read(key: BoxName.basicAuthCredentials); - var url = Uri.parse('$endpoint/$id'); - var response = await http.put( - url, - body: json.encode(data), - headers: { - 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', - }, - ); - return json.decode(response.body); - } + // Future update({ + // required String endpoint, + // required Map data, + // required String id, + // }) async { + // // String? basicAuthCredentials = + // // await storage.read(key: BoxName.basicAuthCredentials); + // var url = Uri.parse('$endpoint/$id'); + // var response = await http.put( + // url, + // body: json.encode(data), + // headers: { + // 'Authorization': + // 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + // }, + // ); + // return json.decode(response.body); + // } Future delete({ required String endpoint, diff --git a/lib/controller/functions/device_info.dart b/lib/controller/functions/device_info.dart index 1d9c5d7..33a1e29 100644 --- a/lib/controller/functions/device_info.dart +++ b/lib/controller/functions/device_info.dart @@ -1,90 +1,92 @@ -// import 'dart:io'; -// -// import 'package:device_info_plus/device_info_plus.dart'; -// -// class DeviceInfoPlus { -// static List> deviceDataList = []; -// -// static Future>> getDeviceInfo() async { -// final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); -// -// try { -// if (Platform.isAndroid) { -// AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo; -// Map deviceData = { -// 'platform': 'Android', -// 'brand': androidInfo.brand, -// 'model': androidInfo.model, -// 'androidId': androidInfo.device, -// 'versionRelease': androidInfo.version.release, -// 'sdkVersion': androidInfo.version.sdkInt, -// 'manufacturer': androidInfo.manufacturer, -// 'isPhysicalDevice': androidInfo.isPhysicalDevice, -// 'serialNumber': androidInfo.serialNumber, -// 'fingerprint': androidInfo.fingerprint, -// 'type': androidInfo.type, -// 'data': androidInfo.data, -// 'version': androidInfo.version, -// 'tags': androidInfo.tags, -// 'display': androidInfo.display, -// }; -// deviceDataList.add(deviceData); -// } else if (Platform.isIOS) { -// IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo; -// Map deviceData = { -// 'brand': 'Apple', -// 'model': iosInfo.model, -// 'systemName': iosInfo.systemName, -// 'systemVersion': iosInfo.systemVersion, -// 'utsname': iosInfo.utsname, -// 'isPhysicalDevice': iosInfo.isPhysicalDevice, -// 'identifierForVendor': iosInfo.identifierForVendor, -// 'name': iosInfo.name, -// 'localizedModel': iosInfo.localizedModel, -// }; -// deviceDataList.add(deviceData); -// } else if (Platform.isMacOS) { -// MacOsDeviceInfo macInfo = await deviceInfoPlugin.macOsInfo; -// Map deviceData = { -// 'platform': 'macOS', -// 'model': macInfo.model, -// 'version': macInfo.systemGUID, -// }; -// deviceDataList.add(deviceData); -// } else if (Platform.isWindows) { -// WindowsDeviceInfo windowsInfo = await deviceInfoPlugin.windowsInfo; -// Map deviceData = { -// 'platform': 'Windows', -// 'manufacturer': windowsInfo.computerName, -// 'version': windowsInfo.majorVersion, -// 'deviceId': windowsInfo.deviceId, -// 'userName': windowsInfo.userName, -// 'productName': windowsInfo.productName, -// 'installDate': windowsInfo.installDate, -// 'productId': windowsInfo.productId, -// 'numberOfCores': windowsInfo.numberOfCores, -// 'systemMemoryInMegabytes': windowsInfo.systemMemoryInMegabytes, -// }; -// deviceDataList.add(deviceData); -// } else if (Platform.isLinux) { -// LinuxDeviceInfo linuxInfo = await deviceInfoPlugin.linuxInfo; -// Map deviceData = { -// 'platform': 'Linux', -// 'manufacturer': linuxInfo.name, -// 'version': linuxInfo.version, -// }; -// deviceDataList.add(deviceData); -// } -// } catch (e) { -// } -// -// return deviceDataList; -// } -// -// // Method to print all device data -// static void printDeviceInfo() { -// for (Map deviceData in deviceDataList) { -// 'Version: ${deviceData['version'] ?? deviceData['versionRelease'] ?? 'N/A'}'); -// } -// } -// } +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; + +import '../../print.dart'; + +class DeviceInfoPlus { + static List> deviceDataList = []; + + static Future>> getDeviceInfo() async { + final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + + try { + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo; + Map deviceData = { + 'platform': 'Android', + 'brand': androidInfo.brand, + 'model': androidInfo.model, + 'androidId': androidInfo.device, + 'versionRelease': androidInfo.version.release, + 'sdkVersion': androidInfo.version.sdkInt, + 'manufacturer': androidInfo.manufacturer, + 'isPhysicalDevice': androidInfo.isPhysicalDevice, + 'serialNumber': androidInfo.serialNumber, + 'fingerprint': androidInfo.fingerprint, + 'type': androidInfo.type, + 'data': androidInfo.data, + 'version': androidInfo.version, + 'tags': androidInfo.tags, + 'display': androidInfo.display, + }; + // Log.print('deviceData: ${deviceData}'); + deviceDataList.add(deviceData); + } else if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo; + Map deviceData = { + 'brand': 'Apple', + 'model': iosInfo.model, + 'systemName': iosInfo.systemName, + 'systemVersion': iosInfo.systemVersion, + 'utsname': iosInfo.utsname, + 'isPhysicalDevice': iosInfo.isPhysicalDevice, + 'identifierForVendor': iosInfo.identifierForVendor, + 'name': iosInfo.name, + 'localizedModel': iosInfo.localizedModel, + }; + deviceDataList.add(deviceData); + } else if (Platform.isMacOS) { + MacOsDeviceInfo macInfo = await deviceInfoPlugin.macOsInfo; + Map deviceData = { + 'platform': 'macOS', + 'model': macInfo.model, + 'version': macInfo.systemGUID, + }; + deviceDataList.add(deviceData); + } else if (Platform.isWindows) { + WindowsDeviceInfo windowsInfo = await deviceInfoPlugin.windowsInfo; + Map deviceData = { + 'platform': 'Windows', + 'manufacturer': windowsInfo.computerName, + 'version': windowsInfo.majorVersion, + 'deviceId': windowsInfo.deviceId, + 'userName': windowsInfo.userName, + 'productName': windowsInfo.productName, + 'installDate': windowsInfo.installDate, + 'productId': windowsInfo.productId, + 'numberOfCores': windowsInfo.numberOfCores, + 'systemMemoryInMegabytes': windowsInfo.systemMemoryInMegabytes, + }; + deviceDataList.add(deviceData); + } else if (Platform.isLinux) { + LinuxDeviceInfo linuxInfo = await deviceInfoPlugin.linuxInfo; + Map deviceData = { + 'platform': 'Linux', + 'manufacturer': linuxInfo.name, + 'version': linuxInfo.version, + }; + deviceDataList.add(deviceData); + } + } catch (e) {} + + return deviceDataList; + } + + // Method to print all device data + static void printDeviceInfo() { + for (Map deviceData in deviceDataList) { + 'Version: ${deviceData['version'] ?? deviceData['versionRelease'] ?? 'N/A'}'; + } + } +} diff --git a/lib/controller/functions/encrypt_decrypt.dart b/lib/controller/functions/encrypt_decrypt.dart index c483fee..8756c3b 100644 --- a/lib/controller/functions/encrypt_decrypt.dart +++ b/lib/controller/functions/encrypt_decrypt.dart @@ -1,33 +1,51 @@ +import 'package:Tripz/constant/box_name.dart'; import 'package:encrypt/encrypt.dart' as encrypt; import 'package:flutter/foundation.dart'; -import '../../env/env.dart'; - -var secretKey = Env.keyOfApp - .toString() - .split('XrXlBl')[0]; // Must be 16 characters for AES-128 -String initializationVector = Env.initializationVector; // Must be 16 characters -final encryptionHelper = EncryptionHelper( - secretKey: secretKey, - initializationVector: initializationVector, -); +import '../../main.dart'; +import '../../print.dart'; class EncryptionHelper { - final encrypt.Key key; - final encrypt.IV iv; + static EncryptionHelper? _instance; - EncryptionHelper( - {required String secretKey, required String initializationVector}) - : key = encrypt.Key.fromUtf8(secretKey), - iv = encrypt.IV.fromUtf8(initializationVector); + late final encrypt.Key key; + late final encrypt.IV iv; - // Initialize the helper + EncryptionHelper._(this.key, this.iv); + static EncryptionHelper get instance { + if (_instance == null) { + throw Exception( + "EncryptionHelper is not initialized. Call `await EncryptionHelper.initialize()` in main."); + } + return _instance!; + } - /// Encrypts the given plain text + /// Initializes and stores the instance globally + static Future initialize() async { + if (_instance != null) { + debugPrint("EncryptionHelper is already initialized."); + return; // Prevent re-initialization + } + debugPrint("Initializing EncryptionHelper..."); + // Read stored keys + String? keyOfApp = await storage.read(key: BoxName.keyOfApp); + // Log.print('keyOfApp: ${keyOfApp}'); + String? initializationVector = + await storage.read(key: BoxName.initializationVector); + // Log.print('initializationVector: ${initializationVector}'); + // Set the global instance + _instance = EncryptionHelper._( + encrypt.Key.fromUtf8(keyOfApp!), + encrypt.IV.fromUtf8(initializationVector!), + ); + debugPrint("EncryptionHelper initialized successfully."); + } + + /// Encrypts a string String encryptData(String plainText) { try { - final encrypter = encrypt.Encrypter(encrypt.AES(key, - mode: encrypt.AESMode.cbc)); // Explicitly use CBC mode + final encrypter = + encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc)); final encrypted = encrypter.encrypt(plainText, iv: iv); return encrypted.base64; } catch (e) { @@ -36,14 +54,13 @@ class EncryptionHelper { } } - /// Decrypts the given encrypted text + /// Decrypts a string String decryptData(String encryptedText) { try { - final encrypter = encrypt.Encrypter(encrypt.AES(key, - mode: encrypt.AESMode.cbc)); // Explicitly use CBC mode + final encrypter = + encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc)); final encrypted = encrypt.Encrypted.fromBase64(encryptedText); - final decrypted = encrypter.decrypt(encrypted, iv: iv); - return decrypted; + return encrypter.decrypt(encrypted, iv: iv); } catch (e) { debugPrint('Decryption Error: $e'); return ''; diff --git a/lib/controller/functions/package_info.dart b/lib/controller/functions/package_info.dart index 85fe32c..633b666 100644 --- a/lib/controller/functions/package_info.dart +++ b/lib/controller/functions/package_info.dart @@ -1,13 +1,15 @@ import 'dart:io'; import 'dart:ui'; -import 'package:flutter/cupertino.dart'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:jailbreak_root_detection/jailbreak_root_detection.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../main.dart'; +import 'encrypt_decrypt.dart'; Future checkForUpdate(BuildContext context) async { final packageInfo = await PackageInfo.fromPlatform(); @@ -38,6 +40,24 @@ checkForBounusInvitation() { // } // return ''; // } +getDeviceFingerprint() async { + final deviceInfo = await DeviceInfoPlugin().deviceInfo; + var deviceData; + + if (Platform.isAndroid) { + deviceData = deviceInfo.data; + } else if (Platform.isIOS) { + deviceData = deviceInfo.data; + } + + final String deviceId = + deviceData['androidId'] ?? deviceData['identifierForVendor']; + final String deviceModel = deviceData['model']; + final String osVersion = deviceData['systemVersion']; + + return EncryptionHelper.instance + .encryptData('${deviceId}_${deviceModel}_$osVersion'); +} void showUpdateDialog(BuildContext context) { final String storeUrl = Platform.isAndroid @@ -158,3 +178,103 @@ void showUpdateDialog(BuildContext context) { }, ); } + +class SecurityHelper { + /// Performs security checks and handles potential risks + static Future performSecurityChecks() async { + bool isNotTrust = false; + bool isJailBroken = false; + bool isRealDevice = true; + bool isOnExternalStorage = false; + bool checkForIssues = false; + bool isDevMode = false; + bool isTampered = false; + String bundleId = ""; + + try { + isNotTrust = await JailbreakRootDetection.instance.isNotTrust; + isJailBroken = await JailbreakRootDetection.instance.isJailBroken; + isRealDevice = await JailbreakRootDetection.instance.isRealDevice; + isOnExternalStorage = + await JailbreakRootDetection.instance.isOnExternalStorage; + + List issues = + await JailbreakRootDetection.instance.checkForIssues; + checkForIssues = issues.isNotEmpty; + + isDevMode = await JailbreakRootDetection.instance.isDevMode; + + // Get Bundle ID + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + bundleId = packageInfo.packageName; + if (bundleId.isNotEmpty) { + // Pass the CORRECT bundle ID to isTampered + isTampered = await JailbreakRootDetection.instance.isTampered(bundleId); + } + } catch (e) { + debugPrint("Error during security checks: $e"); + // Consider handling specific exceptions, not just general errors. + } + + // Save values to storage (using GetStorage) + await box.write('isNotTrust', isNotTrust); // Use await for write operations + await box.write('isTampered', isTampered); // Use await + await box.write('isJailBroken', isJailBroken); // Use await + + // debugPrint("Security Check Results:"); + // debugPrint("isNotTrust: $isNotTrust"); + // debugPrint("isJailBroken: $isJailBroken"); + // debugPrint("isRealDevice: $isRealDevice"); + // debugPrint("isOnExternalStorage: $isOnExternalStorage"); + // debugPrint("checkForIssues: $checkForIssues"); + // debugPrint("isDevMode: $isDevMode"); + // debugPrint("isTampered: $isTampered"); + // debugPrint("Bundle ID: $bundleId"); // Print the bundle ID + + // Check for security risks and potentially show a warning + if (isNotTrust || + isJailBroken || + isTampered || + isDevMode || + isOnExternalStorage || + !isRealDevice) { + // print("security_warning".tr); //using easy_localization + // Use a more robust approach to show a warning, like a dialog: + _showSecurityWarning(); + } + } + + /// Deletes all app data + static Future clearAllData() async { + //await storage.deleteAll(); // What's 'storage'? Be specific. Likely GetStorage as well. + await box.erase(); // Clear GetStorage data + exit(0); // This will terminate the app. Be VERY careful with this. + } + + static void _showSecurityWarning() { + // Show a dialog, navigate to an error screen, etc. + // Example using Get.dialog (if you use GetX): + + Get.dialog( + AlertDialog( + title: Text("Security Warning".tr), // Or use localized string + content: Text( + "Potential security risks detected. The application may not function correctly." + .tr), //Or use localized string + actions: [ + TextButton( + onPressed: () async { + await storage.deleteAll(); + await box.erase(); + Get.back(); // Close the dialog + // Or, if you really must, exit the app (but give the user a chance!) + exit(0); + }, + child: Text("OK"), // Or use a localized string + ), + ], + ), + barrierDismissible: false, // Prevent closing by tapping outside + ); + } +} diff --git a/lib/controller/functions/secure_storage.dart b/lib/controller/functions/secure_storage.dart index 86843b8..ac3583e 100644 --- a/lib/controller/functions/secure_storage.dart +++ b/lib/controller/functions/secure_storage.dart @@ -1,8 +1,12 @@ import 'dart:convert'; import 'package:Tripz/constant/box_name.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:Tripz/constant/info.dart'; +import 'package:Tripz/controller/auth/login_controller.dart'; +import 'package:jwt_decoder/jwt_decoder.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; +import '../../constant/char_map.dart'; import '../../constant/links.dart'; import '../../main.dart'; import '../../print.dart'; @@ -10,15 +14,13 @@ import 'crud.dart'; import 'encrypt_decrypt.dart'; class SecureStorage { - final FlutterSecureStorage _storage = const FlutterSecureStorage(); - void saveData(String key, value) async { - await _storage.write(key: key, value: value); + await storage.write(key: key, value: value); } Future readData(String boxName) async { - final String? value = await _storage.read(key: boxName); - return value; + final String? value = await storage.read(key: boxName); + return value.toString(); } } @@ -34,18 +36,33 @@ class AppInitializer { List> links = []; Future initializeApp() async { - await getKey(); - // await getAIKey('FCM_PRIVATE_KEY'); + // Log.print('box.read("jwt"): ${box.read(BoxName.jwt)}'); + if (box.read(BoxName.jwt) == null) { + await LoginController().getJWT(); + } else { + // print('firstTimeLoadKey ${box.read(BoxName.firstTimeLoadKey)}'); + bool isTokenExpired = JwtDecoder.isExpired(X + .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) + .toString() + .split(AppInformation.addd)[0]); + // Log.print('isTokenExpired: $isTokenExpired'); + if (isTokenExpired) { + await LoginController().getJWT(); + } + } + + // await getKey(); } - getAIKey(String key) async { - var res = - await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key}); - if (res != 'failure') { - var d = jsonDecode(res)['message']; - storage.write(key: 'FCM_PRIVATE_KEY', value: d[key].toString()); - // return d[key].toString(); - } else {} + getAIKey(String key1) async { + if (box.read(BoxName.firstTimeLoadKey) == null) { + var res = + await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key1}); + if (res != 'failure') { + var d = jsonDecode(res)['message']; + storage.write(key: key1, value: d[key1].toString()); + } else {} + } } Future getKey() async { @@ -62,13 +79,15 @@ class AppInitializer { await box.remove(links[2]['name']); await box.write(BoxName.locationName, links); await box.write(BoxName.basicLink, - encryptionHelper.decryptData(links[0]['server_link'])); + EncryptionHelper.instance.decryptData(links[0]['server_link'])); await box.write(links[2]['name'], - encryptionHelper.decryptData(links[2]['server_link'])); + EncryptionHelper.instance.decryptData(links[2]['server_link'])); await box.write(links[1]['name'], - encryptionHelper.decryptData(links[1]['server_link'])); + EncryptionHelper.instance.decryptData(links[3]['server_link'])); + await box.write(links[3]['name'], + EncryptionHelper.instance.decryptData(links[1]['server_link'])); await box.write(BoxName.paymentLink, - encryptionHelper.decryptData(links[4]['server_link'])); + EncryptionHelper.instance.decryptData(links[4]['server_link'])); } } catch (e) { print('Error fetching or decoding location data: $e'); diff --git a/lib/controller/functions/sss.dart b/lib/controller/functions/sss.dart new file mode 100644 index 0000000..e2e1aaf --- /dev/null +++ b/lib/controller/functions/sss.dart @@ -0,0 +1,18 @@ +import 'package:secure_string_operations/secure_string_operations.dart'; + +import '../../constant/char_map.dart'; +import '../../main.dart'; + +class Sss { + static read(String boxname) async { + return box.read(X.r(X.r(X.r(boxname, cn), cC), cs)); + } + + static write(String boxname, value) async { + return box.write(boxname, X.c(X.c(X.c(value, cn), cC), cs)); + } + + static delete(String boxname) async { + return box.remove(boxname); + } +} diff --git a/lib/controller/functions/upload_image.dart b/lib/controller/functions/upload_image.dart index 4425081..ac9ad01 100644 --- a/lib/controller/functions/upload_image.dart +++ b/lib/controller/functions/upload_image.dart @@ -7,9 +7,12 @@ import 'package:http/http.dart' as http; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/box_name.dart'; +import '../../constant/char_map.dart'; import '../../constant/colors.dart'; +import '../../constant/info.dart'; import '../../main.dart'; class ImageController extends GetxController { @@ -75,7 +78,7 @@ class ImageController extends GetxController { ); request.headers.addAll({ 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', + 'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}' }); // Set the file name to the driverID request.files.add( diff --git a/lib/controller/home/map_passenger_controller.dart b/lib/controller/home/map_passenger_controller.dart index 2816550..077a413 100644 --- a/lib/controller/home/map_passenger_controller.dart +++ b/lib/controller/home/map_passenger_controller.dart @@ -543,12 +543,12 @@ class MapPassengerController extends GetxController { void sendSMS(String to) async { // Get the driver's phone number. - String driverPhone = encryptionHelper.decryptData( + String driverPhone = EncryptionHelper.instance.decryptData( dataCarsLocationByPassenger['message'][carsOrder]['phone'].toString()); // Format the message. String message = - 'Hi! This is ${encryptionHelper.decryptData(box.read(BoxName.name).toString().split(' ')[0]).toString()}.\n I am using ${box.read(AppInformation.appName)} to ride with $passengerName as the driver. $passengerName \nis driving a $model\n with license plate $licensePlate.\n I am currently located at $passengerLocation.\n If you need to reach me, please contact the driver directly at\n\n $driverPhone.'; + 'Hi! This is ${EncryptionHelper.instance.decryptData(box.read(BoxName.name).toString().split(' ')[0]).toString()}.\n I am using ${box.read(AppInformation.appName)} to ride with $passengerName as the driver. $passengerName \nis driving a $model\n with license plate $licensePlate.\n I am currently located at $passengerLocation.\n If you need to reach me, please contact the driver directly at\n\n $driverPhone.'; // Launch the URL to send the SMS. launchCommunication('sms', to, message); @@ -560,7 +560,7 @@ class MapPassengerController extends GetxController { // Format the message. String message = - '${'${'Hi! This is'.tr} ${encryptionHelper.decryptData(box.read(BoxName.name).toString().split(' ')[0]).toString()}.\n${' I am using'.tr}'} ${AppInformation.appName}${' to ride with'.tr} $passengerName${' as the driver.'.tr} $passengerName \n${'is driving a '.tr}$model\n${' with license plate '.tr}$licensePlate.\n${' I am currently located at '.tr} https://www.google.com/maps/place/${passengerLocation.latitude},${passengerLocation.longitude}.\n${' If you need to reach me, please contact the driver directly at'.tr}\n\n $driverPhone.'; + '${'${'Hi! This is'.tr} ${EncryptionHelper.instance.decryptData(box.read(BoxName.name).toString().split(' ')[0]).toString()}.\n${' I am using'.tr}'} ${AppInformation.appName}${' to ride with'.tr} $passengerName${' as the driver.'.tr} $passengerName \n${'is driving a '.tr}$model\n${' with license plate '.tr}$licensePlate.\n${' I am currently located at '.tr} https://www.google.com/maps/place/${passengerLocation.latitude},${passengerLocation.longitude}.\n${' If you need to reach me, please contact the driver directly at'.tr}\n\n $driverPhone.'; // Launch the URL to send the WhatsApp message. launchCommunication('whatsapp', to, message); @@ -942,7 +942,7 @@ class MapPassengerController extends GetxController { box.write(BoxName.passengerWalletTotal, '0'); update(); if (box.read(BoxName.parentTripSelected) == true) { - FirebaseMessagesController().sendNotificationToPassengerToken( + Get.find().sendNotificationToPassengerToken( "Finish Monitor".tr, "Finish Monitor".tr, box.read(BoxName.tokenParent), @@ -1530,7 +1530,7 @@ class MapPassengerController extends GetxController { // passengerRate.toStringAsFixed(2), // ]; // Log.print('body: ${body}'); - // FirebaseMessagesController().sendNotificationToDriverMAP( + // Get.find().sendNotificationToDriverMAP( // 'OrderSpeed', // rideId, // driverData['token'].toString(), @@ -1673,7 +1673,7 @@ class MapPassengerController extends GetxController { // ]; // // Log.print('body: ${body}'); - // FirebaseMessagesController().sendNotificationToDriverMAP( + // Get.find().sendNotificationToDriverMAP( // 'OrderSpeed', // rideId.toString(), // dataCarsLocationByPassenger['message'][i]['token'].toString(), @@ -1956,10 +1956,11 @@ class MapPassengerController extends GetxController { Future.delayed(const Duration(microseconds: 10)); final body = constructNotificationBody(driverData); // Log.print('body:ww ${body}'); - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find().sendNotificationToDriverMAP( 'Order'.tr, endNameAddress, - encryptionHelper.decryptData(driverData['token'].toString()), + EncryptionHelper.instance + .decryptData(driverData['token'].toString()), body, 'order.wav'); } @@ -1980,15 +1981,16 @@ class MapPassengerController extends GetxController { distance.toStringAsFixed(2), driverData['driver_id'].toString(), box.read(BoxName.passengerID).toString(), - encryptionHelper + EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[0]) .toString(), - encryptionHelper.decryptData(box.read(BoxName.tokenFCM).toString()), - encryptionHelper.decryptData(box.read(BoxName.phone).toString()), + EncryptionHelper.instance + .decryptData(box.read(BoxName.tokenFCM).toString()), + EncryptionHelper.instance.decryptData(box.read(BoxName.phone).toString()), durationToPassenger.toStringAsFixed(0) ?? '120', distanceByPassenger.toString() ?? '2000', paymentController.isWalletChecked.toString(), - encryptionHelper.decryptData(driverData['token'].toString()), + EncryptionHelper.instance.decryptData(driverData['token'].toString()), durationToPassenger.toString(), rideId.toString(), rideTimerBegin.toString(), @@ -2186,26 +2188,28 @@ class MapPassengerController extends GetxController { var response = jsonDecode(res); Log.print('getUpdatedRideForDriverApply: $response'); driverId = response['data']['driver_id']; - driverPhone = encryptionHelper.decryptData(response['data']['phone']); + driverPhone = + EncryptionHelper.instance.decryptData(response['data']['phone']); driverCarMake = response['data']['make']; model = response['data']['model']; colorHex = response['data']['color_hex']; carColor = response['data']['color']; make = response['data']['make']; licensePlate = - encryptionHelper.decryptData(response['data']['car_plate']); - passengerName = - encryptionHelper.decryptData(response['data']['passengerName']); - driverName = encryptionHelper + EncryptionHelper.instance.decryptData(response['data']['car_plate']); + passengerName = EncryptionHelper.instance + .decryptData(response['data']['passengerName']); + driverName = EncryptionHelper.instance .decryptData(response['data']['driverName'].toString()); - driverToken = encryptionHelper.decryptData(response['data']['token']); + driverToken = + EncryptionHelper.instance.decryptData(response['data']['token']); // Log.print('driverToken updated: $driverToken'); carYear = response['data']['year']; driverRate = response['data']['ratingDriver'].toString(); } // driversToken.remove(driverToken); // for (var i = 1; i < driversToken.length; i++) { - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find().sendNotificationToDriverMAP( 'Order Accepted'.tr, '$driverName${'Accepted your order'.tr}', driverToken.toString(), @@ -2452,9 +2456,9 @@ class MapPassengerController extends GetxController { longitude >= minLongitude && longitude <= maxLongitude) { box.write(BoxName.serverChosen, - encryptionHelper.decryptData(locationData['server_link'])); + EncryptionHelper.instance.decryptData(locationData['server_link'])); // Log.print( - // 'locationData----server_link: ${encryptionHelper.decryptData(locationData['server_link'])}'); + // 'locationData----server_link: ${EncryptionHelper.instance.decryptData(locationData['server_link'])}'); return locationData['name']; } } @@ -2609,7 +2613,7 @@ class MapPassengerController extends GetxController { _getIconForCar(json), ); - driversToken.add(encryptionHelper.decryptData(json['token'])); + driversToken.add(EncryptionHelper.instance.decryptData(json['token'])); } // Add fake car markers @@ -2921,10 +2925,11 @@ class MapPassengerController extends GetxController { Get.back(); })); } else if (res1['status'] == 'success') { - var tokenParent = encryptionHelper.decryptData(res1['data'][0]['token']); + var tokenParent = + EncryptionHelper.instance.decryptData(res1['data'][0]['token']); Get.snackbar("The invitation was sent successfully".tr, '', backgroundColor: AppColor.greenColor); - FirebaseMessagesController().sendNotificationToPassengerToken( + Get.find().sendNotificationToPassengerToken( "Trip Monitoring".tr, "Trip Monitoring".tr, tokenParent, @@ -3161,7 +3166,7 @@ class MapPassengerController extends GetxController { changeCancelRidePageShow(); if (rideId != 'yet') { Log.print('cancelRide: 1'); - await FirebaseMessagesController().sendNotificationToDriverMAP( + await Get.find().sendNotificationToDriverMAP( 'Cancel Trip'.tr, 'Trip Cancelled'.tr, driverToken.toString(), @@ -5163,34 +5168,38 @@ class MapPassengerController extends GetxController { timeSelected); // Optionally, set up local notification or send a push notification - await FirebaseMessagesController().sendNotificationToDriverMAP( - 'OrderVIP', - rideId.toString(), - encryptionHelper.decryptData(driver['token'].toString()), - [ - id, - rideId, - driver['id'], - passengerLocation.latitude.toString(), - startNameAddress.toString(), - passengerLocation.longitude.toString(), - encryptionHelper - .decryptData(box.read(BoxName.name).toString().split(' ')[0]) - .toString(), - box.read(BoxName.passengerID).toString(), - box.read(BoxName.phone).toString(), - box.read(BoxName.email).toString(), - box.read(BoxName.passengerPhotoUrl).toString(), - box.read(BoxName.tokenFCM).toString(), - encryptionHelper.decryptData(driver['token'].toString()), - ], - 'order.wav'); + await Get.find() + .sendNotificationToDriverMAP( + 'OrderVIP', + rideId.toString(), + EncryptionHelper.instance + .decryptData(driver['token'].toString()), + [ + id, + rideId, + driver['id'], + passengerLocation.latitude.toString(), + startNameAddress.toString(), + passengerLocation.longitude.toString(), + EncryptionHelper.instance + .decryptData( + box.read(BoxName.name).toString().split(' ')[0]) + .toString(), + box.read(BoxName.passengerID).toString(), + box.read(BoxName.phone).toString(), + box.read(BoxName.email).toString(), + box.read(BoxName.passengerPhotoUrl).toString(), + box.read(BoxName.tokenFCM).toString(), + EncryptionHelper.instance + .decryptData(driver['token'].toString()), + ], + 'order.wav'); if (response['message'] == "Trip updated successfully") { mySnackbarSuccess("Trip updated successfully".tr); Log.print( 'previous_driver_token: ${response['previous_driver_token']}'); - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find().sendNotificationToDriverMAP( 'Order VIP Canceld'.tr, 'Passenger cancel order'.tr, response['previous_driver_token'].toString(), @@ -5214,7 +5223,7 @@ class MapPassengerController extends GetxController { } cancelVip(String token, tripId) async { - // FirebaseMessagesController().sendNotificationToDriverMAP( + // Get.find().sendNotificationToDriverMAP( // 'Order VIP Canceld'.tr, // 'Passenger cancel order'.tr, // token, @@ -5230,7 +5239,7 @@ class MapPassengerController extends GetxController { } sendToDriverAgain(String token) { - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find().sendNotificationToDriverMAP( 'Order VIP Canceld'.tr, 'Passenger cancel order'.tr, token, @@ -5377,6 +5386,7 @@ class MapPassengerController extends GetxController { reloadStartApp = false; startMarkerReloading(); Get.put(TextToSpeechController()); + Get.put(FirebaseMessagesController()); box.write(BoxName.carType, 'yet'); box.write(BoxName.tipPercentage, '0'); Get.put(AudioRecorderController()); diff --git a/lib/controller/home/profile/invit_controller.dart b/lib/controller/home/profile/invit_controller.dart index 1e87511..f9f299e 100644 --- a/lib/controller/home/profile/invit_controller.dart +++ b/lib/controller/home/profile/invit_controller.dart @@ -179,9 +179,9 @@ Download the Tripz app now and enjoy your ride! int.parse(driverInvitationDataToPassengers[index]['countOfInvitDriver'] .toString()) < 2 - ? '${'When'.tr} ${encryptionHelper.decryptData(driverInvitationDataToPassengers[index]['passengerName'].toString())} ${"complete, you can claim your gift".tr} ' + ? '${'When'.tr} ${EncryptionHelper.instance.decryptData(driverInvitationDataToPassengers[index]['passengerName'].toString())} ${"complete, you can claim your gift".tr} ' : 'You deserve the gift'.tr, - '${encryptionHelper.decryptData(driverInvitationDataToPassengers[index]['passengerName'].toString())} ${driverInvitationDataToPassengers[index]['countOfInvitDriver'].toString()} / 2 ${'Trip'.tr}', + '${EncryptionHelper.instance.decryptData(driverInvitationDataToPassengers[index]['passengerName'].toString())} ${driverInvitationDataToPassengers[index]['countOfInvitDriver'].toString()} / 2 ${'Trip'.tr}', () async { if (int.parse(driverInvitationDataToPassengers[index] ['countOfInvitDriver'] @@ -270,7 +270,8 @@ Download the Tripz app now and enjoy your ride! var response = await CRUD().post(link: AppLink.addInvitationPassenger, payload: { "driverId": box.read(BoxName.passengerID), - "inviterPassengerPhone": encryptionHelper.encryptData('+2$phoneNumber') + "inviterPassengerPhone": + EncryptionHelper.instance.encryptData('+2$phoneNumber') }); if (response != 'failure') { diff --git a/lib/controller/home/splash_screen_controlle.dart b/lib/controller/home/splash_screen_controlle.dart index 93fe3f2..5b04cc2 100644 --- a/lib/controller/home/splash_screen_controlle.dart +++ b/lib/controller/home/splash_screen_controlle.dart @@ -1,7 +1,9 @@ import 'dart:async'; +import 'package:Tripz/constant/style.dart'; +import 'package:Tripz/controller/functions/secure_storage.dart'; +import 'package:Tripz/views/widgets/my_scafold.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:Tripz/views/auth/login_page.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -28,9 +30,19 @@ class SplashScreenController extends GetxController update(); } + String iss = ''; @override - void onInit() { + Future onInit() async { super.onInit(); + + // storage.read(key: 'iss').then((s) { + // // print(s); + // iss = s!; + // }); + // if (iss == null) { + SecureStorage().saveData('iss', 'mobile-app:'); + // } + _getPackageInfo(); _animationController = AnimationController( vsync: this, @@ -56,6 +68,12 @@ class SplashScreenController extends GetxController if (elapsed >= totalTime) { timer.cancel(); + // await SecurityHelper.performSecurityChecks(); + // if (box.read('isNotTrust') || + // box.read('isJailBroken') || + // box.read('isTampered')) { + // Get.to(() => SecurityPage()); + // } else { box.read(BoxName.onBoarding) == null ? Get.off(() => OnBoardingPage()) : box.read(BoxName.email) != null && @@ -68,6 +86,7 @@ class SplashScreenController extends GetxController ) : Get.off(() => LoginPage()); } + // } }); } @@ -94,3 +113,39 @@ class SplashScreenController extends GetxController super.onClose(); } } + +class SecurityPage extends StatelessWidget { + const SecurityPage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return MyScafolld( + title: "security_warning".tr, + body: [ + Center( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + Text( + "security_message".tr, + style: AppStyle.headTitle2, + ), + TextButton( + onPressed: () async { + // await SecurityHelper.clearAllData(); + }, + child: Text( + "security_warning".tr, + ), + ), + ], + ), + ), + ) + ], + isleading: false); + } +} diff --git a/lib/controller/home/vip_waitting_page.dart b/lib/controller/home/vip_waitting_page.dart index 266aec7..20726da 100644 --- a/lib/controller/home/vip_waitting_page.dart +++ b/lib/controller/home/vip_waitting_page.dart @@ -287,7 +287,7 @@ class VipWaittingPage extends StatelessWidget { ? MyElevatedButton( title: "Click here to begin your trip\n\nGood luck, " .tr + - encryptionHelper + EncryptionHelper.instance .decryptData(box .read(BoxName.name) .toString() diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 7a28030..c6751da 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -71,7 +71,12 @@ class MyTranslation extends Translations { "Wallet": "المحفظة", "Profile": "الملف الشخصي", "Contact Support": "اتصل بالدعم", -// + 'Session expired. Please log in again.': + 'انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.', + "Security Warning": "⚠️ تحذير أمني", + "Potential security risks detected. The application may not function correctly.": + "تم اكتشاف ثغرات أمنية على هذا الجهاز. للحفاظ على أمان بياناتك، سيتم حذف جميع البيانات وإغلاق التطبيق.", + 'please order now': " ‏الرجاء الطلب مرة أخرى", "Where to": "على فين؟", "Where are you going?": "رايح فين؟", "Quick Actions": "إجراءات سريعة", diff --git a/lib/controller/notification/passenger_notification_controller.dart b/lib/controller/notification/passenger_notification_controller.dart index db43990..6874ab6 100644 --- a/lib/controller/notification/passenger_notification_controller.dart +++ b/lib/controller/notification/passenger_notification_controller.dart @@ -47,7 +47,7 @@ class PassengerNotificationController extends GetxController { 'title': title, 'body': body, }); - FirebaseMessagesController().sendNotificationToPassengerToken( + Get.find().sendNotificationToPassengerToken( title, body, 'token', diff --git a/lib/controller/payment/driver_payment_controller.dart b/lib/controller/payment/driver_payment_controller.dart index 6c3625c..2f897c4 100644 --- a/lib/controller/payment/driver_payment_controller.dart +++ b/lib/controller/payment/driver_payment_controller.dart @@ -14,7 +14,7 @@ class DriverWalletHistoryController extends GetxController { getArchivePayment() async { isLoading = true; update(); - var res = await CRUD().get( + var res = await CRUD().getWallet( link: AppLink.getWalletByDriver, payload: {'driverID': box.read(BoxName.driverID)}); if (res == 'failure') { diff --git a/lib/controller/payment/passenger_wallet_history_controller.dart b/lib/controller/payment/passenger_wallet_history_controller.dart index 9a18a15..5712418 100644 --- a/lib/controller/payment/passenger_wallet_history_controller.dart +++ b/lib/controller/payment/passenger_wallet_history_controller.dart @@ -17,7 +17,7 @@ class PassengerWalletHistoryController extends GetxController { isLoading = true; update(); - var res = await CRUD().get( + var res = await CRUD().getWallet( link: AppLink.getPassengerWalletArchive, payload: {'passenger_id': box.read(BoxName.passengerID)}, ); diff --git a/lib/controller/payment/payment_controller.dart b/lib/controller/payment/payment_controller.dart index 1824439..11b0c9f 100644 --- a/lib/controller/payment/payment_controller.dart +++ b/lib/controller/payment/payment_controller.dart @@ -56,7 +56,7 @@ class PaymentController extends GetxController { isLoading = true; update(); - await CRUD().get( + await CRUD().getWallet( link: AppLink.getWalletByPassenger, payload: {'passenger_id': box.read(BoxName.passengerID)}).then((value) { box.write(BoxName.passengerWalletTotal, @@ -134,7 +134,7 @@ class PaymentController extends GetxController { }); if (res != 'failure') { - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find().sendNotificationToDriverMAP( 'Cancel', 'Trip Cancelled. The cost of the trip will be added to your wallet.' .tr, @@ -265,7 +265,7 @@ class PaymentController extends GetxController { merchantDisplayName: AppInformation.appName, billingDetails: BillingDetails( name: box.read(BoxName.nameDriver) == null - ? encryptionHelper + ? EncryptionHelper.instance .decryptData( box.read(BoxName.name).toString().split(' ')[0]) .toString() diff --git a/lib/controller/payment/paymob.dart b/lib/controller/payment/paymob.dart index b107f7b..b3b4aa2 100644 --- a/lib/controller/payment/paymob.dart +++ b/lib/controller/payment/paymob.dart @@ -135,14 +135,15 @@ class PaymobManager extends GetxController { "amount_cents": amount, "currency": currency, "billing_data": { - "first_name": encryptionHelper + "first_name": EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[0]) .toString(), - "last_name": encryptionHelper + "last_name": EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[1]) .toString(), - "email": encryptionHelper.decryptData(box.read(BoxName.email)), - "phone_number": encryptionHelper.decryptData(box.read(BoxName.phone)), + "email": EncryptionHelper.instance.decryptData(box.read(BoxName.email)), + "phone_number": + EncryptionHelper.instance.decryptData(box.read(BoxName.phone)), "apartment": "NA", "floor": "NA", "street": "NA", diff --git a/lib/controller/payment/paymob/paymob_response.dart b/lib/controller/payment/paymob/paymob_response.dart index 2af4aff..d0e391e 100644 --- a/lib/controller/payment/paymob/paymob_response.dart +++ b/lib/controller/payment/paymob/paymob_response.dart @@ -226,13 +226,14 @@ class PaymobBillingData { Map toJson() { return { "email": box.read(BoxName.email) ?? box.read(BoxName.emailDriver), - "first_name": encryptionHelper + "first_name": EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[0]) .toString(), - "last_name": encryptionHelper + "last_name": EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[1]) .toString(), - "phone_number": encryptionHelper.decryptData(box.read(BoxName.phone)), + "phone_number": + EncryptionHelper.instance.decryptData(box.read(BoxName.phone)), "apartment": apartment ?? "NA", "floor": floor ?? "NA", "building": building ?? "NA", diff --git a/lib/controller/payment/paymob/paymob_wallet.dart b/lib/controller/payment/paymob/paymob_wallet.dart index aace844..b0d5f3d 100644 --- a/lib/controller/payment/paymob/paymob_wallet.dart +++ b/lib/controller/payment/paymob/paymob_wallet.dart @@ -267,11 +267,11 @@ class PaymobBillingDataWallet { Map toJson() { return { - "email": encryptionHelper.decryptData(box.read(BoxName.email)), - "first_name": encryptionHelper + "email": EncryptionHelper.instance.decryptData(box.read(BoxName.email)), + "first_name": EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[0]) .toString(), - "last_name": encryptionHelper + "last_name": EncryptionHelper.instance .decryptData(box.read(BoxName.name).toString().split(' ')[1]) .toString() ?? 'tripz', diff --git a/lib/controller/profile/profile_controller.dart b/lib/controller/profile/profile_controller.dart index 229d16b..fd2197a 100644 --- a/lib/controller/profile/profile_controller.dart +++ b/lib/controller/profile/profile_controller.dart @@ -74,11 +74,14 @@ class ProfileController extends GetxController { Get.back(); await updateColumn({ 'id': box.read(BoxName.passengerID), - columnName: encryptionHelper.encryptData(txtController.text), + columnName: + EncryptionHelper.instance.encryptData(txtController.text), }); if (columnName == 'first_name') { - box.write(BoxName.name, - encryptionHelper.encryptData(txtController.text)); + box.write( + BoxName.name, + EncryptionHelper.instance + .encryptData(txtController.text)); } txtController.clear(); diff --git a/lib/controller/rate/rate_conroller.dart b/lib/controller/rate/rate_conroller.dart index 4388c59..81a821d 100644 --- a/lib/controller/rate/rate_conroller.dart +++ b/lib/controller/rate/rate_conroller.dart @@ -70,7 +70,7 @@ class RateController extends GetxController { 'token': token1, }); if (res != 'failure') { - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find().sendNotificationToDriverMAP( 'You Have Tips'.tr, '${'${tip.toString()}\$${' tips\nTotal is'.tr}'} ${tip + (Get.find().totalPassenger)}', Get.find().driverToken.toString(), diff --git a/lib/main.dart b/lib/main.dart index 59cf8ec..ede2d3b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:math'; +import 'package:Tripz/constant/box_name.dart'; import 'package:Tripz/controller/payment/paymob/paymob_response.dart'; import 'package:Tripz/views/home/HomePage/contact_us.dart'; import 'package:Tripz/views/home/HomePage/share_app_page.dart'; @@ -21,6 +22,7 @@ import 'constant/info.dart'; import 'constant/notification.dart'; import 'controller/firebase/firbase_messge.dart'; import 'controller/firebase/local_notification.dart'; +import 'controller/functions/encrypt_decrypt.dart'; import 'controller/functions/secure_storage.dart'; import 'controller/local/local_controller.dart'; import 'controller/local/translations.dart'; @@ -30,12 +32,13 @@ import 'models/db_sql.dart'; import 'splash_screen_page.dart'; final box = GetStorage(); -const storage = FlutterSecureStorage(); +final storage = FlutterSecureStorage(); // final PaymobPayment paymobPayment = PaymobPayment(); final PaymobPayment paymobPayment = PaymobPayment(); final PaymobPaymentWallet paymobPaymentWallet = PaymobPaymentWallet(); DbSql sql = DbSql.instance; +// EncryptionHelper encryptionHelper = EncryptionHelper.instance; @pragma('vm:entry-point') Future backgroundMessageHandler(RemoteMessage message) async { await Firebase.initializeApp(); @@ -46,20 +49,20 @@ Future backgroundMessageHandler(RemoteMessage message) async { void main() async { WidgetsFlutterBinding.ensureInitialized(); WakelockPlus.enable(); - // await LocationController().startLocationUpdates(); - // if (Platform.isAndroid) { + + await GetStorage.init(); + + final AppInitializer initializer = AppInitializer(); + + await initializer.initializeApp(); + await EncryptionHelper.initialize(); + NotificationController notificationController = Get.put(NotificationController()); - // await NotificationController().initNotifications(); - // } - await GetStorage.init(); - // Get.put(DriverCallController()); - // await AC().gAK(); - 'local is ${WidgetsBinding.instance.platformDispatcher.locale.countryCode}'; - Stripe.publishableKey = AK.publishableKey; // if (box.read(BoxName.driverID) != null) {} + if (Platform.isAndroid || Platform.isIOS) { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, @@ -79,16 +82,19 @@ void main() async { DeviceOrientation.portraitDown, ]); } + + String? key = (await storage.read(key: BoxName.payMobApikey)); + + String? apiKey = EncryptionHelper.instance.decryptData(key!); PaymobPayment.instance.initialize( - apiKey: AK - .payMobApikey, // from dashboard Select Settings -> Account Info -> API Key + apiKey: apiKey, integrationID: int.parse(AK.integrationIdPayMob), userTokenExpiration: 200, iFrameID: 837992, ); PaymobPaymentWallet.instance.initialize( - apiKey: AK.payMobApikey, + apiKey: apiKey, integrationID: int.parse(AK.integrationIdPayMobWallet), userTokenExpiration: 200, iFrameID: 837992, @@ -105,8 +111,7 @@ void main() async { randomMessage.split(':')[1], "tone1", ); - final AppInitializer initializer = AppInitializer(); - await initializer.initializeApp(); + // final encryptionHelper = await EncryptionHelper.initialize(); final QuickActions quickActions = QuickActions(); diff --git a/lib/views/auth/login_page.dart b/lib/views/auth/login_page.dart index 037b15f..4d27f0d 100644 --- a/lib/views/auth/login_page.dart +++ b/lib/views/auth/login_page.dart @@ -1,6 +1,9 @@ import 'dart:io'; +import 'package:Tripz/constant/char_map.dart'; +import 'package:Tripz/controller/functions/crud.dart'; import 'package:Tripz/controller/functions/encrypt_decrypt.dart'; +import 'package:Tripz/env/env.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -12,11 +15,13 @@ import 'package:Tripz/constant/colors.dart'; import 'package:Tripz/constant/style.dart'; import 'package:Tripz/main.dart'; import 'package:Tripz/views/widgets/my_scafold.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/info.dart'; import '../../controller/auth/apple_signin_controller.dart'; import '../../controller/auth/google_sign.dart'; import '../../controller/auth/login_controller.dart'; +import '../../print.dart'; import '../home/HomePage/contact_us.dart'; import '../home/profile/passenger_profile_page.dart'; @@ -29,6 +34,7 @@ class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { Get.put(LoginController()); + Get.put(CRUD()); return GetBuilder( builder: (controller) => MyScafolld( title: 'Login'.tr, @@ -88,8 +94,10 @@ class LoginPage extends StatelessWidget { User? user = await authController.signInWithApple(); if (user != null) { box.write(BoxName.passengerID, user.uid); - box.write(BoxName.email, - encryptionHelper.encryptData(user.email.toString())); + box.write( + BoxName.email, + EncryptionHelper.instance + .encryptData(user.email.toString())); await controller.loginUsingCredentials( box.read(BoxName.passengerID).toString(), box.read(BoxName.email).toString(), @@ -113,6 +121,17 @@ class LoginPage extends StatelessWidget { style: AppStyle.subtitle.copyWith(color: Colors.grey), ), ), + // TextButton( + // onPressed: () async { + // var encrypt = EncryptionHelper.instance.encryptData(''); + // Log.print('encrypt: ${encrypt}'); + // Log.print( + // 'encrypt: ${EncryptionHelper.instance.decryptData(encrypt)}'); + // }, + // child: Text( + // "Text Button", + // ), + // ), ], ), ), diff --git a/lib/views/home/map_page_passenger.dart b/lib/views/home/map_page_passenger.dart index 1719acc..b9281c3 100644 --- a/lib/views/home/map_page_passenger.dart +++ b/lib/views/home/map_page_passenger.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; +import '../../controller/functions/crud.dart'; import '../../controller/functions/package_info.dart'; import '../../controller/home/map_passenger_controller.dart'; import '../../main.dart'; @@ -31,6 +32,7 @@ class MapPagePassenger extends StatelessWidget { Widget build(BuildContext context) { Get.put(MapPassengerController()); Get.put(MyMenuController()); + Get.put(CRUD()); WidgetsBinding.instance.addPostFrameCallback((_) { checkForUpdate(context); }); diff --git a/lib/views/home/map_widget.dart/apply_order_widget.dart b/lib/views/home/map_widget.dart/apply_order_widget.dart index a368708..1aca3ec 100644 --- a/lib/views/home/map_widget.dart/apply_order_widget.dart +++ b/lib/views/home/map_widget.dart/apply_order_widget.dart @@ -257,7 +257,8 @@ class ApplyOrderWidget extends StatelessWidget { padding: const EdgeInsets.only(bottom: 8.0), child: ElevatedButton( onPressed: () { - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find() + .sendNotificationToDriverMAP( 'message From passenger', message.tr, controller.driverToken.toString(), @@ -290,7 +291,8 @@ class ApplyOrderWidget extends StatelessWidget { IconButton( onPressed: () { if (controller.messagesFormKey.currentState!.validate()) { - FirebaseMessagesController().sendNotificationToDriverMAP( + Get.find() + .sendNotificationToDriverMAP( 'message From passenger', controller.messageToDriver.text, controller.driverToken, diff --git a/lib/views/home/map_widget.dart/left_main_menu_icons.dart b/lib/views/home/map_widget.dart/left_main_menu_icons.dart index 2652b23..a35b427 100644 --- a/lib/views/home/map_widget.dart/left_main_menu_icons.dart +++ b/lib/views/home/map_widget.dart/left_main_menu_icons.dart @@ -1,11 +1,30 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:http/http.dart' as http; +import 'package:Tripz/constant/box_name.dart'; +import 'package:Tripz/main.dart'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:jwt_decoder/jwt_decoder.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; +import '../../../constant/api_key.dart'; +import '../../../constant/char_map.dart'; import '../../../constant/colors.dart'; +import '../../../constant/info.dart'; +import '../../../constant/links.dart'; +import '../../../constant/table_names.dart'; +import '../../../controller/functions/crud.dart'; +import '../../../controller/functions/encrypt_decrypt.dart'; +import '../../../controller/functions/package_info.dart'; +import '../../../controller/functions/secure_storage.dart'; import '../../../controller/functions/tts.dart'; import '../../../controller/home/map_passenger_controller.dart'; import '../../../controller/home/vip_waitting_page.dart'; +import '../../../env/env.dart'; +import '../../../print.dart'; GetBuilder leftMainMenuIcons() { Get.put(TextToSpeechController()); @@ -54,32 +73,41 @@ GetBuilder leftMainMenuIcons() { tooltip: 'VIP Waiting Page', // More descriptive tooltip ), // const SizedBox(width: 8), - // _buildIconButtonWithAnimation( - // controller: controller, - // icon: Octicons.screen_full, - // onPressed: () async { - // final plainText = 'Hello, Safar App!'; - // debugPrint('Plain Text: $plainText'); - - // // Encrypt the data - // final encryptedData = encryptionHelper.encryptData(plainText); - // debugPrint('Encrypted: $encryptedData'); - - // // Decrypt the data - // final decryptedData = encryptionHelper - // .decryptData(encryptedData); // Use the encryptedData variable - // debugPrint('Decrypted: $decryptedData'); - // //kVb4a+11Scs9jQWwzeVfx0PxSDiPWDCuMI/RWYxafMU= - // //kVb4a+11Scs9jQWwzeVfx0PxSDiPWDCuMI/RWYxafMU= - // }, - // tooltip: 'Recent Locations', // More descriptive tooltip - // ), + _buildIconButtonWithAnimation( + controller: controller, + icon: Octicons.screen_full, + onPressed: () async { + Get.to(() => TestPage()); + }, + tooltip: 'Recent Locations', // More descriptive tooltip + ), ], ), ), ); } +class TestPage extends StatelessWidget { + const TestPage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: Center( + child: TextButton( + onPressed: () async {}, + child: Text( + "Text Button", + ), + ), + ), + ); + } +} + Widget _buildIconButtonWithAnimation({ required MapPassengerController controller, required IconData icon, diff --git a/lib/views/home/map_widget.dart/main_bottom_Menu_map.dart b/lib/views/home/map_widget.dart/main_bottom_Menu_map.dart index fe0f958..08b6afd 100644 --- a/lib/views/home/map_widget.dart/main_bottom_Menu_map.dart +++ b/lib/views/home/map_widget.dart/main_bottom_Menu_map.dart @@ -459,7 +459,7 @@ class MainBottomMenuMap extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '${'Where to'.tr} ${encryptionHelper.decryptData(box.read(BoxName.name).toString().split(' ')[0])} ', + '${'Where to'.tr} ${EncryptionHelper.instance.decryptData(box.read(BoxName.name).toString().split(' ')[0])} ', style: AppStyle.subtitle), // if (controller.noCarString) // Text('Nearest Car: ~'.tr, diff --git a/lib/views/home/map_widget.dart/new_main_bottom_sheet.dart b/lib/views/home/map_widget.dart/new_main_bottom_sheet.dart index b56233e..d09a5e3 100644 --- a/lib/views/home/map_widget.dart/new_main_bottom_sheet.dart +++ b/lib/views/home/map_widget.dart/new_main_bottom_sheet.dart @@ -72,7 +72,7 @@ class NewMainBottomSheet extends StatelessWidget { children: [ const Icon(Icons.search), Text( - "${"Where you want go ".tr}${encryptionHelper.decryptData(box.read(BoxName.name).toString().split(' ')[0]).toString()} ?", + "${"Where you want go ".tr}${EncryptionHelper.instance.decryptData(box.read(BoxName.name).toString().split(' ')[0]).toString()} ?", ), ], ), diff --git a/lib/views/home/my_wallet/passenger_wallet.dart b/lib/views/home/my_wallet/passenger_wallet.dart index 218fd93..51c9e96 100644 --- a/lib/views/home/my_wallet/passenger_wallet.dart +++ b/lib/views/home/my_wallet/passenger_wallet.dart @@ -222,7 +222,7 @@ class CardTripzWallet extends StatelessWidget { Align( alignment: Alignment.bottomRight, child: Text( - encryptionHelper + EncryptionHelper.instance .decryptData( box.read(BoxName.name).toString().split(' ')[0]) .toString(), diff --git a/lib/views/home/profile/passenger_profile_page.dart b/lib/views/home/profile/passenger_profile_page.dart index 51212ec..2b4614a 100644 --- a/lib/views/home/profile/passenger_profile_page.dart +++ b/lib/views/home/profile/passenger_profile_page.dart @@ -54,7 +54,7 @@ class PassengerProfilePage extends StatelessWidget { ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text( - '${encryptionHelper.decryptData(controller.prfoileData['first_name'])} ${encryptionHelper.decryptData(controller.prfoileData['last_name'])}'), + '${EncryptionHelper.instance.decryptData(controller.prfoileData['first_name'])} ${EncryptionHelper.instance.decryptData(controller.prfoileData['last_name'])}'), onTap: () { controller.updatField( 'first_name', TextInputType.name); @@ -70,8 +70,9 @@ class PassengerProfilePage extends StatelessWidget { width: 35, ), trailing: const Icon(Icons.arrow_forward_ios), - subtitle: Text(encryptionHelper.decryptData( - controller.prfoileData['gender'].toString())), + subtitle: Text(EncryptionHelper.instance + .decryptData(controller.prfoileData['gender'] + .toString())), onTap: () { Get.defaultDialog( title: 'Update Gender'.tr, @@ -84,8 +85,9 @@ class PassengerProfilePage extends StatelessWidget { controller.updateColumn({ 'id': controller.prfoileData['id'] .toString(), - 'gender': - encryptionHelper.encryptData( + 'gender': EncryptionHelper + .instance + .encryptData( controller.gender), }); Get.back(); @@ -181,7 +183,7 @@ class PassengerProfilePage extends StatelessWidget { size: 35, ), trailing: const Icon(Icons.arrow_forward_ios), - subtitle: Text(encryptionHelper + subtitle: Text(EncryptionHelper.instance .decryptData( controller.prfoileData['sosPhone']) .toString()), diff --git a/pubspec.lock b/pubspec.lock index 0db0647..b923e93 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -295,13 +295,13 @@ packages: source: hosted version: "0.7.10" device_info_plus: - dependency: transitive + dependency: "direct main" description: name: device_info_plus - sha256: "4fa68e53e26ab17b70ca39f072c285562cfc1589df5bb1e9295db90f6645f431" + sha256: "72d146c6d7098689ff5c5f66bcf593ac11efc530095385356e131070333e64da" url: "https://pub.dev" source: hosted - version: "11.2.0" + version: "11.3.0" device_info_plus_platform_interface: dependency: transitive description: @@ -1125,6 +1125,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + jailbreak_root_detection: + dependency: "direct main" + description: + name: jailbreak_root_detection + sha256: ee98f5e69b43c758ee1779204b0926a09f0371eebe1462b876fb6a8bd130cbe5 + url: "https://pub.dev" + source: hosted + version: "1.1.5" js: dependency: transitive description: @@ -1165,6 +1173,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.13" + jwt_decoder: + dependency: "direct main" + description: + name: jwt_decoder + sha256: "54774aebf83f2923b99e6416b4ea915d47af3bde56884eb622de85feabbc559f" + url: "https://pub.dev" + source: hosted + version: "2.0.1" leak_tracker: dependency: transitive description: @@ -1342,21 +1358,21 @@ packages: source: hosted version: "2.1.1" package_info_plus: - dependency: "direct main" + dependency: transitive description: name: package_info_plus - sha256: "70c421fe9d9cc1a9a7f3b05ae56befd469fe4f8daa3b484823141a55442d858d" + sha256: "67eae327b1b0faf761964a1d2e5d323c797f3799db0e85aa232db8d9e922bc35" url: "https://pub.dev" source: hosted - version: "8.1.2" + version: "8.2.1" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b + sha256: "205ec83335c2ab9107bbba3f8997f9356d72ca3c715d2f038fc773d0366b4c76" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.0" path: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 821ebf1..e918033 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,7 +58,7 @@ dependencies: google_sign_in: ^6.2.1 sign_in_with_apple: ^6.1.0 firebase_auth: ^5.1.2 - package_info_plus: ^8.0.0 + device_info_plus: ^11.3.0 uni_links: ^0.5.1 googleapis_auth: ^1.6.0 flutter_confetti: ^0.3.0 @@ -69,6 +69,9 @@ dependencies: encrypt: ^5.0.3 live_activities: ^2.3.0 quick_actions: ^1.1.0 + jwt_decoder: ^2.0.1 + jailbreak_root_detection: ^1.1.5 + # jailbreak_root_detection: ^1.1.5 dev_dependencies: flutter_test: