111 lines
3.3 KiB
Swift
111 lines
3.3 KiB
Swift
import Flutter
|
|
import Security
|
|
import UIKit
|
|
|
|
@main
|
|
@objc class AppDelegate: FlutterAppDelegate {
|
|
override func application(
|
|
_ application: UIApplication,
|
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
) -> Bool {
|
|
GeneratedPluginRegistrant.register(with: self)
|
|
registerDurableAuthStorageChannel()
|
|
registerMobileContextChannel()
|
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
|
}
|
|
|
|
private func registerMobileContextChannel() {
|
|
guard let controller = window?.rootViewController as? FlutterViewController else {
|
|
return
|
|
}
|
|
let channel = FlutterMethodChannel(
|
|
name: "com.org.yumiparty/mobile_context",
|
|
binaryMessenger: controller.binaryMessenger
|
|
)
|
|
channel.setMethodCallHandler { call, result in
|
|
switch call.method {
|
|
case "getTimeZoneIdentifier":
|
|
result(TimeZone.current.identifier)
|
|
default:
|
|
result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func registerDurableAuthStorageChannel() {
|
|
guard let controller = window?.rootViewController as? FlutterViewController else {
|
|
return
|
|
}
|
|
let channel = FlutterMethodChannel(
|
|
name: "com.org.yumiparty/durable_auth_storage",
|
|
binaryMessenger: controller.binaryMessenger
|
|
)
|
|
channel.setMethodCallHandler { [weak self] call, result in
|
|
guard
|
|
let self,
|
|
let args = call.arguments as? [String: Any],
|
|
let key = args["key"] as? String
|
|
else {
|
|
result(FlutterError(code: "bad_args", message: "Missing key", details: nil))
|
|
return
|
|
}
|
|
|
|
switch call.method {
|
|
case "write":
|
|
guard let value = args["value"] as? String else {
|
|
result(FlutterError(code: "bad_args", message: "Missing value", details: nil))
|
|
return
|
|
}
|
|
self.writeKeychainValue(value, key: key)
|
|
result(nil)
|
|
case "read":
|
|
result(self.readKeychainValue(key: key))
|
|
case "delete":
|
|
self.deleteKeychainValue(key: key)
|
|
result(nil)
|
|
default:
|
|
result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func keychainQuery(key: String) -> [String: Any] {
|
|
[
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: "com.org.yumiparty.durable_auth_storage",
|
|
kSecAttrAccount as String: key
|
|
]
|
|
}
|
|
|
|
private func writeKeychainValue(_ value: String, key: String) {
|
|
deleteKeychainValue(key: key)
|
|
guard let data = value.data(using: .utf8) else {
|
|
return
|
|
}
|
|
var query = keychainQuery(key: key)
|
|
query[kSecValueData as String] = data
|
|
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
|
|
SecItemAdd(query as CFDictionary, nil)
|
|
}
|
|
|
|
private func readKeychainValue(key: String) -> String? {
|
|
var query = keychainQuery(key: key)
|
|
query[kSecReturnData as String] = true
|
|
query[kSecMatchLimit as String] = kSecMatchLimitOne
|
|
|
|
var result: AnyObject?
|
|
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
guard
|
|
status == errSecSuccess,
|
|
let data = result as? Data
|
|
else {
|
|
return nil
|
|
}
|
|
return String(data: data, encoding: .utf8)
|
|
}
|
|
|
|
private func deleteKeychainValue(key: String) {
|
|
SecItemDelete(keychainQuery(key: key) as CFDictionary)
|
|
}
|
|
}
|