Update: 2026-05-15 04:16:32
This commit is contained in:
@@ -17,6 +17,32 @@ android {
|
|||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val localProperties = java.util.Properties()
|
||||||
|
val localPropertiesFile = rootProject.file("local.properties")
|
||||||
|
if (localPropertiesFile.exists()) {
|
||||||
|
localProperties.load(java.io.FileInputStream(localPropertiesFile))
|
||||||
|
}
|
||||||
|
val apiKey = localProperties.getProperty("API_KEY", "\"\"")
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
buildConfigField("String", "API_KEY", apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
val keystorePropertiesFile = rootProject.file("app/key.properties")
|
||||||
|
val keystoreProperties = java.util.Properties()
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keystoreProperties.load(java.io.FileInputStream(keystorePropertiesFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
create("release") {
|
||||||
|
keyAlias = keystoreProperties["keyAlias"] as String?
|
||||||
|
keyPassword = keystoreProperties["keyPassword"] as String?
|
||||||
|
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
|
||||||
|
storePassword = keystoreProperties["storePassword"] as String?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
@@ -25,6 +51,7 @@ android {
|
|||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
)
|
)
|
||||||
|
signingConfig = signingConfigs.getByName("release")
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
|
|||||||
4
app/key.properties
Normal file
4
app/key.properties
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
storePassword=21010333
|
||||||
|
keyPassword=21010333
|
||||||
|
keyAlias=sportnewskey
|
||||||
|
storeFile=/Users/hamzaaleghwairyeen/development/upload-keystore
|
||||||
@@ -20,6 +20,8 @@ import androidx.core.app.NotificationManagerCompat
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.jordanbot.autoride.service.BotForegroundService
|
import com.jordanbot.autoride.service.BotForegroundService
|
||||||
import com.jordanbot.autoride.service.OverlayService
|
import com.jordanbot.autoride.service.OverlayService
|
||||||
|
import com.jordanbot.autoride.api.ApiClient
|
||||||
|
import com.jordanbot.autoride.utils.DeviceUtils
|
||||||
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -51,6 +53,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
// Load Settings
|
// Load Settings
|
||||||
FilterEngine.init(this)
|
FilterEngine.init(this)
|
||||||
|
|
||||||
|
// Set App Signature for API Security
|
||||||
|
ApiClient.appSignature = DeviceUtils.getAppSignatureSHA256(this)
|
||||||
|
|
||||||
// Load cached subscription data
|
// Load cached subscription data
|
||||||
SubscriptionManager.loadLocalCache(this)
|
SubscriptionManager.loadLocalCache(this)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import retrofit2.Retrofit
|
|||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
// Data models for the API
|
// Data models for the API
|
||||||
data class RideLogRequest(
|
data class RideLogRequest(
|
||||||
@@ -78,10 +80,23 @@ interface BackendApiService {
|
|||||||
object ApiClient {
|
object ApiClient {
|
||||||
// Replace with your actual server URL
|
// Replace with your actual server URL
|
||||||
private const val BASE_URL = "https://lawer.tripz-egypt.com/jordan_bot/backend/"
|
private const val BASE_URL = "https://lawer.tripz-egypt.com/jordan_bot/backend/"
|
||||||
|
private val API_KEY = com.jordanbot.autoride.BuildConfig.API_KEY
|
||||||
|
var appSignature: String = ""
|
||||||
|
|
||||||
|
private val httpClient = OkHttpClient.Builder().apply {
|
||||||
|
addInterceptor(Interceptor { chain ->
|
||||||
|
val request = chain.request().newBuilder()
|
||||||
|
.addHeader("X-API-Key", API_KEY)
|
||||||
|
.addHeader("X-App-Signature", appSignature)
|
||||||
|
.build()
|
||||||
|
chain.proceed(request)
|
||||||
|
})
|
||||||
|
}.build()
|
||||||
|
|
||||||
val service: BackendApiService by lazy {
|
val service: BackendApiService by lazy {
|
||||||
Retrofit.Builder()
|
Retrofit.Builder()
|
||||||
.baseUrl(BASE_URL)
|
.baseUrl(BASE_URL)
|
||||||
|
.client(httpClient)
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
.build()
|
.build()
|
||||||
.create(BackendApiService::class.java)
|
.create(BackendApiService::class.java)
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.jordanbot.autoride.utils
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
object DeviceUtils {
|
object DeviceUtils {
|
||||||
/**
|
/**
|
||||||
* Returns a unique fingerprint for the device based on Android ID.
|
* Returns a unique fingerprint for the device based on Android ID.
|
||||||
@@ -10,4 +13,25 @@ object DeviceUtils {
|
|||||||
fun getDeviceFingerprint(context: Context): String {
|
fun getDeviceFingerprint(context: Context): String {
|
||||||
return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) ?: "UNKNOWN_DEVICE"
|
return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) ?: "UNKNOWN_DEVICE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the SHA-256 signature of the installed app.
|
||||||
|
*/
|
||||||
|
fun getAppSignatureSHA256(context: Context): String {
|
||||||
|
try {
|
||||||
|
val packageInfo = context.packageManager.getPackageInfo(
|
||||||
|
context.packageName,
|
||||||
|
PackageManager.GET_SIGNATURES
|
||||||
|
)
|
||||||
|
for (signature in packageInfo.signatures) {
|
||||||
|
val md = MessageDigest.getInstance("SHA-256")
|
||||||
|
md.update(signature.toByteArray())
|
||||||
|
val digest = md.digest()
|
||||||
|
return digest.joinToString("") { "%02x".format(it) }
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,29 @@ if (!$envLoaded) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Security: API Key Validation
|
||||||
|
$expectedApiKey = $_ENV['API_KEY'] ?? 'JORDAN_BOT_SECRET_2026'; // Fallback if not in .env
|
||||||
|
$headers = getallheaders();
|
||||||
|
$providedKey = $headers['X-API-Key'] ?? ($headers['x-api-key'] ?? null);
|
||||||
|
|
||||||
|
if ($providedKey !== $expectedApiKey) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Unauthorized: Invalid or missing API Key']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra Security: App Signature Fingerprint Validation (Optional)
|
||||||
|
$expectedAppSignature = $_ENV['APP_SIGNATURE_SHA256'] ?? null;
|
||||||
|
if (!empty($expectedAppSignature)) {
|
||||||
|
$providedSignature = $headers['X-App-Signature'] ?? ($headers['x-app-signature'] ?? null);
|
||||||
|
// Ignore case and compare
|
||||||
|
if (strcasecmp($providedSignature, $expectedAppSignature) !== 0) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Forbidden: Invalid App Signature (Anti-Tamper)']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$host = $_ENV['DB_HOST'] ?? 'localhost';
|
$host = $_ENV['DB_HOST'] ?? 'localhost';
|
||||||
$dbname = $_ENV['DB_NAME'] ?? 'jordan_bot_db';
|
$dbname = $_ENV['DB_NAME'] ?? 'jordan_bot_db';
|
||||||
$username = $_ENV['DB_USER'] ?? 'root';
|
$username = $_ENV['DB_USER'] ?? 'root';
|
||||||
|
|||||||
@@ -6,3 +6,4 @@
|
|||||||
# header note.
|
# header note.
|
||||||
#Thu May 14 16:37:36 EET 2026
|
#Thu May 14 16:37:36 EET 2026
|
||||||
sdk.dir=/Users/hamzaaleghwairyeen/Library/Android/sdk
|
sdk.dir=/Users/hamzaaleghwairyeen/Library/Android/sdk
|
||||||
|
API_KEY="JB_8a7d6c5b4a39281706f5e4d3c2b1a0"
|
||||||
|
|||||||
Reference in New Issue
Block a user