Skip to content

Commit

Permalink
Revert "Revert "Merge branch 'develop' into 2918/home_widget/android""
Browse files Browse the repository at this point in the history
This reverts commit 2135e63.
  • Loading branch information
ppupha committed Nov 4, 2024
1 parent eb87444 commit 07e8be9
Show file tree
Hide file tree
Showing 73 changed files with 2,174 additions and 1,074 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ on:

jobs:
fetch-deployment:
if: ${{ ! contains(github.event.pull_request.title, 'WIP') }}
runs-on: ubuntu-latest
outputs:
short_version: ${{ steps.extract-version.outputs.short_version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ios-release-testflight.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:

jobs:
fastlane-deploy:
runs-on: macOS-13
runs-on: macOS-15
steps:
# Set up Flutter.
- name: Clone Flutter repository with master channel
Expand Down
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ linter:
sort_unnamed_constructors_first: true
type_annotate_public_apis: true
type_init_formals: true
type_literal_in_constant_pattern: true
type_literal_in_constant_pattern: false
unawaited_futures: true
unnecessary_brace_in_string_interps: true
unnecessary_breaks: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler {
private lateinit var context: Context
private lateinit var disposables: CompositeDisposable
private lateinit var client: BlockstoreClient
private final val primaryAddressStoreKey = "primary_address"
private val primaryAddressStoreKey = "primary_address"
private val didRegisterPasskeys = "did_register_passkeys"

fun createChannels(@NonNull flutterEngine: FlutterEngine, @NonNull context: Context) {
this.context = context
Expand All @@ -51,6 +52,8 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler {
"getPrimaryAddress" -> getPrimaryAddress(call, result)
"clearPrimaryAddress" -> clearPrimaryAddress(call, result)
"deleteKeys" -> deleteKeys(call, result)
"setDidRegisterPasskey" -> setDidRegisterPasskey(call, result)
"didRegisterPasskey" -> didRegisterPasskey(call, result)
else -> {
result.notImplemented()
}
Expand Down Expand Up @@ -246,6 +249,57 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler {
}
}

private fun setDidRegisterPasskey(call: MethodCall, result: MethodChannel.Result) {
val data: Boolean = call.argument("data") ?: false

val storeBytesBuilder = StoreBytesData.Builder()
.setKey(didRegisterPasskeys)
.setBytes(data.toString().toByteArray(Charsets.UTF_8))

client.storeBytes(storeBytesBuilder.build())
.addOnSuccessListener {

Log.e("setDidRegisterPasskey", data.toString());
result.success(true)
}
.addOnFailureListener { e ->
Log.e("setDidRegisterPasskey", e.message ?: "")
result.success(false)
}
}

private fun didRegisterPasskey(call: MethodCall, result: MethodChannel.Result) {
val request = RetrieveBytesRequest.Builder()
.setKeys(listOf(didRegisterPasskeys)) // Specify the key
.build()
client.retrieveBytes(request)
.addOnSuccessListener {
try { // Retrieve bytes using the key
val dataMap = it.blockstoreDataMap[didRegisterPasskeys]
if (dataMap != null) {
val bytes = dataMap.bytes
val resultString = bytes.toString(Charsets.UTF_8)
Log.d("didRegisterPasskey", resultString)


result.success(resultString.toBoolean())
} else {
Log.e("didRegisterPasskey", "No data found for the key")
result.success(false)
}
} catch (e: Exception) {
Log.e("didRegisterPasskey", e.message ?: "Error decoding data")
//No primary address found
result.success(false)
}
}
.addOnFailureListener {
//Block store not available
result.error("didRegisterPasskey Block store error", it.message, it)
}
}


private fun clearPrimaryAddress(call: MethodCall, result: MethodChannel.Result) {
val retrieveRequest = DeleteBytesRequest.Builder()
.setKeys(listOf(primaryAddressStoreKey))
Expand All @@ -259,7 +313,6 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler {
}
}


private fun deleteKeys(call: MethodCall, result: MethodChannel.Result) {
val deleteRequestBuilder = DeleteBytesRequest.Builder()
.setDeleteAll(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,24 @@ import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View.ACCESSIBILITY_DATA_SENSITIVE_YES
import android.view.WindowManager.LayoutParams
import androidx.biometric.BiometricManager
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.android.FlutterView
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.util.concurrent.TimeUnit

class MainActivity : FlutterFragmentActivity() {
companion object {
var isAuthenticate: Boolean = false
private const val CHANNEL = "migration_util"
private val secureScreenChannel = "secure_screen_channel"
private var lastAuthTime: Long = 0
private val authenticationTimeout = TimeUnit.MINUTES.toMillis(3)
private var isThisFirstOnResume = true;
}

var flutterSharedPreferences: SharedPreferences? = null
Expand Down Expand Up @@ -225,18 +230,40 @@ class MainActivity : FlutterFragmentActivity() {
Context.MODE_PRIVATE
)
val isEnabled = sharedPreferences.getBoolean("flutter.device_passcode", false)
if (isEnabled && !isAuthenticate) {
val didRegisterPasskey =
sharedPreferences.getBoolean("flutter.did_register_passkey", false)
if (isThisFirstOnResume && didRegisterPasskey) {

// skip authentication if the user has already registered the passkey in open app
isThisFirstOnResume = false
// this is not conventional way to do this, but we need skip authenticate after user
// authenticate with passkey
updateAuthenticationTime()
return
}

if (isEnabled && !isAuthenticate && needsReAuthentication()) {
val biometricManager = BiometricManager.from(this)
val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
if (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
== BiometricManager.BIOMETRIC_SUCCESS || keyguardManager.isDeviceSecure
) {
val intent = Intent(this@MainActivity, AuthenticatorActivity::class.java)
updateAuthenticationTime()
startActivity(intent)
}
}
}

private fun updateAuthenticationTime() {
lastAuthTime = System.currentTimeMillis()
}

private fun needsReAuthentication(): Boolean {
val currentTime = System.currentTimeMillis()
return (currentTime - lastAuthTime) > authenticationTimeout
}

override fun onPause() {
super.onPause()
isAuthenticate = false
Expand Down
2 changes: 1 addition & 1 deletion ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ end

def one_signal_notification_service_extension
use_frameworks!
pod 'OneSignalXCFramework', '>= 3.4.3', '< 4.0'
pod 'OneSignalXCFramework', '>= 3.4.3', '< 6.0'
end

target 'Runner Notification' do
Expand Down
14 changes: 12 additions & 2 deletions ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ import Logging

case "clearPrimaryAddress":
SystemChannelHandler.shared.clearPrimaryAddress(call: call)

case "didRegisterPasskey":
SystemChannelHandler.shared.didRegisterPasskey(call: call, result: result)

case "setDidRegisterPasskey":
SystemChannelHandler.shared.setDidRegisterPasskey(call: call, result: result)

default:
result(FlutterMethodNotImplemented)
Expand Down Expand Up @@ -247,8 +253,12 @@ import Logging

DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { [weak self] in
if UserDefaults.standard.bool(forKey: "flutter.device_passcode") == true {
self?.showAuthenticationOverlay()
self?.authenticationVC.authentication()
SystemChannelHandler.shared.didRegisterPasskeyKeychain { didRegisterPasskey in
if let didRegisterPasskey = didRegisterPasskey as? Bool, !didRegisterPasskey {
self?.showAuthenticationOverlay()
self?.authenticationVC.authentication()
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions ios/Runner/Constant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ struct Constant {
return bundleIdentifier.contains("inhouse")
}
static let primaryAddressKey: String = "primary_address_key"
static let userIdKey: String = "user_id_key"
static let didRegisterPasskeys = "did_register_passkeys"
}
2 changes: 2 additions & 0 deletions ios/Runner/Runner InhouseDebug.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<string>applinks:app.feralfile.com</string>
<string>feralfile-app.test-app.link</string>
<string>feralfile-app-alternate.test-app.link</string>
<string>webcredentials:accounts.dev.feralfile.com</string>
<string>webcredentials:accounts.feralfile.com</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
Expand Down
2 changes: 2 additions & 0 deletions ios/Runner/Runner-Inhouse.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<string>applinks:app.feralfile.com</string>
<string>feralfile-app.test-app.link</string>
<string>feralfile-app-alternate.test-app.link</string>
<string>webcredentials:accounts.dev.feralfile.com</string>
<string>webcredentials:accounts.feralfile.com</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
Expand Down
2 changes: 2 additions & 0 deletions ios/Runner/Runner.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<string>applinks:app.feralfile.com</string>
<string>feralfile-app.test-app.link</string>
<string>feralfile-app-alternate.test-app.link</string>
<string>webcredentials:accounts.dev.feralfile.com</string>
<string>webcredentials:accounts.feralfile.com</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
Expand Down
2 changes: 2 additions & 0 deletions ios/Runner/RunnerDebug.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<string>applinks:app.feralfile.com</string>
<string>feralfile-app.test-app.link</string>
<string>feralfile-app-alternate.test-app.link</string>
<string>webcredentials:accounts.dev.feralfile.com</string>
<string>webcredentials:accounts.feralfile.com</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
Expand Down
37 changes: 37 additions & 0 deletions ios/Runner/SystemChannelHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,42 @@ class SystemChannelHandler: NSObject {
return
}

func setDidRegisterPasskey(call: FlutterMethodCall, result: @escaping FlutterResult) {
// Safely extract the arguments and handle cases where "data" is nil or invalid, default to false
let args = call.arguments as? [String: Any]
let data = (args?["data"] as? Bool) ?? false

let keychain = Keychain()

// Encode Bool to Data
let boolData = Data([data ? 1 : 0])

// Safely store the Bool data in Keychain
if keychain.set(boolData, forKey: Constant.didRegisterPasskeys) {
result(true)
} else {
result(false)
}
}

func didRegisterPasskey(call: FlutterMethodCall, result: @escaping FlutterResult) {
didRegisterPasskeyKeychain(result: result)
}

func didRegisterPasskeyKeychain(result: @escaping FlutterResult) {
let keychain = Keychain()

// Safely retrieve data from Keychain
guard let data = keychain.getData(Constant.didRegisterPasskeys, isSync: true) else {
result(false)
return
}

// Decode the data back to a Bool
let didRegisterPasskeys = data.first == 1

// Return the Bool value
result(didRegisterPasskeys)
}

}
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions lib/common/environment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Environment {
'SENTRY_DSN',
'ONESIGNAL_APP_ID',
'TV_API_KEY',
'SUPPORT_API_KEY',
];
final missingKeys = <String>[];
for (var key in keys) {
Expand Down Expand Up @@ -225,4 +226,7 @@ class Environment {

static String get domainResolverApiKey =>
_readKey('DOMAIN_RESOLVER_API_KEY', '', isSecret: true);

static String get supportApiKey =>
_readKey('SUPPORT_API_KEY', '', isSecret: true);
}
Loading

0 comments on commit 07e8be9

Please sign in to comment.