mirror of
https://github.com/twofas/2fas-ios.git
synced 2024-11-22 02:10:19 +01:00
TF-250 Basic structure
This commit is contained in:
parent
d223770737
commit
02ed735ac0
@ -108,6 +108,7 @@ public extension TintColor {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
var color: UIColor {
|
||||
let bundle = Bundle(for: CountdownTimer.self)
|
||||
switch self {
|
||||
@ -124,4 +125,5 @@ public extension TintColor {
|
||||
case .brown: return UIColor(named: "tintBrownColor", in: bundle, compatibleWith: nil)!
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
public protocol IconDescriptionDatabase: AnyObject {
|
||||
func name(for iconTypeID: IconTypeID) -> String?
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
// swiftlint:disable all
|
||||
final class IconDescriptionDatabaseGenerated {
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
public protocol ServiceDefinitionDatabase: AnyObject {
|
||||
func listAll() -> [ServiceDefinition]
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
// swiftlint:disable all
|
||||
final class ServiceDefinitionDatabaseGenerated {
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -20,7 +20,11 @@
|
||||
import Foundation
|
||||
import CryptoKit
|
||||
import CommonCrypto
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
public final class ExchangeFileEncryption {
|
||||
public struct EncryptionResult {
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
public final class LocalKeyEncryption: CommonLocalKeyEncryption {
|
||||
private let encryption = KeyEncryption(
|
||||
|
54
TwoFAS/Protection/Protection+.swift
Normal file
54
TwoFAS/Protection/Protection+.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Zbigniew Cisiński. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Protection.CodeType: RawRepresentable {
|
||||
private enum Keys {
|
||||
static let PIN4 = "PIN4"
|
||||
static let PIN6 = "PIN6"
|
||||
}
|
||||
public typealias RawValue = String
|
||||
|
||||
public init?(rawValue: String) {
|
||||
if rawValue == Keys.PIN4 {
|
||||
self = .PIN4
|
||||
} else if rawValue == Keys.PIN6 {
|
||||
self = .PIN6
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: String {
|
||||
switch self {
|
||||
case .PIN4: return Keys.PIN4
|
||||
case .PIN6: return Keys.PIN6
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension Protection.CodeType {
|
||||
var intValue: Int {
|
||||
switch self {
|
||||
case .PIN4: return 4
|
||||
case .PIN6: return 6
|
||||
}
|
||||
}
|
||||
}
|
@ -18,12 +18,16 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
public final class Protection {
|
||||
public typealias PIN = String
|
||||
|
||||
public enum CodeType {
|
||||
public enum CodeType: CaseIterable {
|
||||
case PIN4
|
||||
case PIN6
|
||||
}
|
||||
@ -32,7 +36,7 @@ public final class Protection {
|
||||
let PINvalue: PIN
|
||||
let codeType: CodeType
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
private let encryptedStorage: LocalEncryptedStorage
|
||||
|
||||
public let biometricAuth: BiometricAuth
|
||||
@ -53,40 +57,15 @@ public final class Protection {
|
||||
migrationHandler = MigrationHandler(storage: encryptedStorage)
|
||||
migrationHandler.migrateIfNeeded()
|
||||
}
|
||||
#elseif os(watchOS)
|
||||
// private let encryptedStorage: LocalEncryptedStorage
|
||||
// public let codeStorage: CodeStorage
|
||||
public let localKeyEncryption: CommonLocalKeyEncryption
|
||||
//
|
||||
public init() {
|
||||
// encryptedStorage = LocalEncryptedStorage(defaults: UserDefaults(suiteName: Config.suiteName)!)
|
||||
// codeStorage = CodeStorage(storage: encryptedStorage)
|
||||
localKeyEncryption = LocalKeyEncryption()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
extension Protection.CodeType: RawRepresentable {
|
||||
private enum Keys {
|
||||
static let PIN4 = "PIN4"
|
||||
static let PIN6 = "PIN6"
|
||||
}
|
||||
public typealias RawValue = String
|
||||
|
||||
public init?(rawValue: String) {
|
||||
if rawValue == Keys.PIN4 {
|
||||
self = .PIN4
|
||||
} else if rawValue == Keys.PIN6 {
|
||||
self = .PIN6
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: String {
|
||||
switch self {
|
||||
case .PIN4: return Keys.PIN4
|
||||
case .PIN6: return Keys.PIN6
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension Protection.CodeType {
|
||||
var intValue: Int {
|
||||
switch self {
|
||||
case .PIN4: return 4
|
||||
case .PIN6: return 6
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Protection.CodeType: CaseIterable {}
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
import CloudKit
|
||||
|
||||
final class ClearHandler {
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum CloudAvailabilityStatus {
|
||||
case available
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
public enum CloudCurrentState: Equatable {
|
||||
public enum NotAvailableReason: Equatable {
|
||||
@ -52,10 +56,12 @@ public protocol CloudHandlerType: AnyObject {
|
||||
typealias SecretSyncError = (String) -> Void
|
||||
|
||||
func registerForStateChange(_ listener: @escaping CloudHandlerStateListener, with id: String)
|
||||
#if os(iOS)
|
||||
func didReceiveRemoteNotification(
|
||||
userInfo: [AnyHashable: Any],
|
||||
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
|
||||
)
|
||||
#endif
|
||||
func unregisterForStateChange(id: String)
|
||||
|
||||
var userToggledState: UserToggledState? { get set }
|
||||
@ -211,6 +217,7 @@ final class CloudHandler: CloudHandlerType {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
func didReceiveRemoteNotification(
|
||||
userInfo: [AnyHashable: Any],
|
||||
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
|
||||
@ -224,6 +231,7 @@ final class CloudHandler: CloudHandlerType {
|
||||
return
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var isConnected: Bool {
|
||||
switch currentState {
|
||||
|
@ -19,8 +19,12 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
import Common
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
final class CloudKit {
|
||||
typealias DeletedEntries = ([(name: String, type: String)]) -> Void
|
||||
@ -474,6 +478,7 @@ final class CloudKit {
|
||||
zoneUpdated = false
|
||||
|
||||
DispatchQueue.main.async {
|
||||
#if os(iOS)
|
||||
if UIApplication.shared.applicationState == .background {
|
||||
self.abortSync?()
|
||||
self.syncTokenHandler.prepare()
|
||||
@ -482,6 +487,7 @@ final class CloudKit {
|
||||
self.operation = nil
|
||||
return
|
||||
}
|
||||
#endif
|
||||
|
||||
if !self.deletedRecords.isEmpty {
|
||||
Log("CloudKit - deletedRecords not empty", module: .cloudSync)
|
||||
|
98
TwoFAS/Sync/CommonItemHandlerWatch.swift
Normal file
98
TwoFAS/Sync/CommonItemHandlerWatch.swift
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2023 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Zbigniew Cisiński. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CommonWatch
|
||||
|
||||
final class CommonItemHandler {
|
||||
init() {
|
||||
|
||||
// commonSectionHandler.commonDidCreate = { [weak self] sectionID in
|
||||
// Log("CommonItemHandler - commonSectionHandler - commonDidCreate", module: .cloudSync)
|
||||
// self?.logHandler.log(entityID: sectionID, actionType: .created, kind: .section)
|
||||
// }
|
||||
// commonSectionHandler.commonDidModify = { [weak self] sectionIDs in
|
||||
// Log("CommonItemHandler - commonSectionHandler - commonDidModify", module: .cloudSync)
|
||||
// sectionIDs.forEach {
|
||||
// self?.logHandler.log(entityID: $0, actionType: .modified, kind: .section)
|
||||
// }
|
||||
// }
|
||||
// commonSectionHandler.commonDidDelete = { [weak self] sectionID in
|
||||
// Log("CommonItemHandler - commonSectionHandler - commonDidDelete", module: .cloudSync)
|
||||
// self?.logHandler.log(entityID: sectionID, actionType: .deleted, kind: .section)
|
||||
// }
|
||||
//
|
||||
// commonServiceHandler.commonDidCreate = { [weak self] secret in
|
||||
// Log("CommonItemHandler - commonServiceHandler - commonDidCreate", module: .cloudSync)
|
||||
// self?.logHandler.log(entityID: secret, actionType: .created, kind: .service2)
|
||||
// }
|
||||
// commonServiceHandler.commonDidModify = { [weak self] secrets in
|
||||
// Log("CommonItemHandler - commonServiceHandler - commonDidModify", module: .cloudSync)
|
||||
// secrets.forEach {
|
||||
// self?.logHandler.log(entityID: $0, actionType: .modified, kind: .service2)
|
||||
// }
|
||||
// }
|
||||
// commonServiceHandler.commonDidDelete = { [weak self] secret in
|
||||
// Log("CommonItemHandler - commonServiceHandler - commonDidDelete", module: .cloudSync)
|
||||
// self?.logHandler.log(entityID: secret, actionType: .deleted, kind: .service2)
|
||||
// }
|
||||
}
|
||||
|
||||
func logFirstImport() {
|
||||
// logHandler.logFirstImport(entityIDs: commonSectionHandler.getAllSections().map { $0.sectionID }, kind: .section)
|
||||
// logHandler.logFirstImport(entityIDs: commonServiceHandler.getAllServices().map { $0.secret }, kind: .service2)
|
||||
// logHandler.logFirstImport(entityIDs: [Info.id], kind: .info)
|
||||
}
|
||||
|
||||
func setItems(_ items: [RecordType: [Any]]) -> Bool {
|
||||
// var newDataWasSet = false
|
||||
//
|
||||
// if let sections = items[.section] as? [CommonSectionData] {
|
||||
// Log("CommonItemHandler: sections (\(sections.count))")
|
||||
// let value = commonSectionHandler.setSections(sections)
|
||||
// newDataWasSet = newDataWasSet || value
|
||||
// }
|
||||
//
|
||||
// if let services = items[.service2] as? [ServiceData] {
|
||||
// Log("CommonItemHandler: services (\(services.count))")
|
||||
// let value = commonServiceHandler.setServices(services)
|
||||
// newDataWasSet = newDataWasSet || value
|
||||
// }
|
||||
//
|
||||
// return newDataWasSet
|
||||
false
|
||||
}
|
||||
|
||||
func setItemsFromMigration(_ serviceDataToAppend: [ServiceData]) {
|
||||
// Log("CommonItemHandler: setting items from migration (\(serviceDataToAppend.count))")
|
||||
// itemsToAppend = serviceDataToAppend
|
||||
}
|
||||
|
||||
func getAllItems() -> [RecordType: [Any]] {
|
||||
// let sections = commonSectionHandler.getAllSections()
|
||||
// let services = commonServiceHandler.getAllServices() + itemsToAppend
|
||||
// itemsToAppend = []
|
||||
// var value = [RecordType: [Any]]()
|
||||
// value[.section] = sections
|
||||
// value[.service2] = services
|
||||
// value[.info] = [Info()]
|
||||
// return value
|
||||
[:]
|
||||
}
|
||||
}
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum InfoEntryKey: String {
|
||||
case version
|
||||
|
@ -19,8 +19,13 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
import Protection
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
import ProtectionWatch
|
||||
#endif
|
||||
|
||||
final class ItemHandler {
|
||||
typealias SecretError = (String) -> Void
|
||||
|
126
TwoFAS/Sync/Item/ItemHandlerMigrationProxyWatch.swift
Normal file
126
TwoFAS/Sync/Item/ItemHandlerMigrationProxyWatch.swift
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2023 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Zbigniew Cisiński. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
import CommonWatch
|
||||
import ContentWatch
|
||||
|
||||
final class ItemHandlerMigrationProxy {
|
||||
var newerVersion: (() -> Void)?
|
||||
var cloudEncrypted: (() -> Void)?
|
||||
|
||||
private let itemHandler: ItemHandler
|
||||
|
||||
private var isFirstStart = false
|
||||
|
||||
private var deletedEntries: [EntityOfKind] = []
|
||||
private var updatedCreated: [CKRecord] = []
|
||||
|
||||
private var itemsToDelete: [CKRecord.ID] = []
|
||||
private var itemsToAdd: [ServiceData] = []
|
||||
|
||||
init(itemHandler: ItemHandler) {
|
||||
self.itemHandler = itemHandler
|
||||
}
|
||||
|
||||
func firstStart() {
|
||||
Log("Migration proxy - first start!", module: .cloudSync)
|
||||
isFirstStart = true
|
||||
}
|
||||
}
|
||||
|
||||
extension ItemHandlerMigrationProxy: ItemHandling {
|
||||
func commit() {
|
||||
Log("Migration proxy - commit", module: .cloudSync)
|
||||
if isFirstStart {
|
||||
if let infoRecord = updatedCreated.first(where: { RecordType(rawValue: $0.recordType) == .info }) {
|
||||
let info = InfoRecord(record: infoRecord)
|
||||
if info.version > Info().version {
|
||||
Log("Migration proxy - newer version! Aborting...", module: .cloudSync)
|
||||
newerVersion?()
|
||||
return
|
||||
}
|
||||
if let encryption = Info.Encryption(rawValue: info.encryption), encryption == .user {
|
||||
Log("Migration proxy - cloud encrypted! Aborting...", module: .cloudSync)
|
||||
cloudEncrypted?()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
isFirstStart = false
|
||||
}
|
||||
itemHandler.deleteEntries(deletedEntries)
|
||||
itemHandler.updateOrCreate(with: updatedCreated)
|
||||
deletedEntries = []
|
||||
updatedCreated = []
|
||||
}
|
||||
|
||||
func purge() {
|
||||
itemHandler.purge()
|
||||
}
|
||||
|
||||
func itemsToDeleteAfterMigration() -> [CKRecord.ID] {
|
||||
let list = itemsToDelete
|
||||
itemsToDelete = []
|
||||
return list
|
||||
}
|
||||
|
||||
func servicesToAppend() -> [ServiceData] {
|
||||
let services = itemsToAdd
|
||||
itemsToAdd = []
|
||||
return services
|
||||
}
|
||||
|
||||
func listAllCommonItems() -> [RecordType: [Any]] {
|
||||
itemHandler.listAllCommonItems()
|
||||
}
|
||||
|
||||
func findItemsRecordIDs(for items: [EntityOfKind], zoneID: CKRecordZone.ID) -> [CKRecord.ID] {
|
||||
itemHandler.findItemsRecordIDs(for: items, zoneID: zoneID)
|
||||
}
|
||||
|
||||
func filterDeleted(from items: [RecordType: [Any]], deleted: [EntityOfKind]) -> [RecordType: [Any]] {
|
||||
itemHandler.filterDeleted(from: items, deleted: deleted)
|
||||
}
|
||||
|
||||
func findItem(for item: Any, type: RecordType, in items: [RecordType: [Any]]) -> CommonDataIndex? {
|
||||
itemHandler.findItem(for: item, type: type, in: items)
|
||||
}
|
||||
|
||||
func findItemForEntryID(_ entryID: String, type: RecordType, in items: [RecordType: [Any]]) -> CommonDataIndex? {
|
||||
itemHandler.findItemForEntryID(entryID, type: type, in: items)
|
||||
}
|
||||
|
||||
func record(for type: RecordType, item: Any, modifiedData from: [RecordType: [Any]]) -> CKRecord? {
|
||||
itemHandler.record(for: type, item: item, modifiedData: from)
|
||||
}
|
||||
|
||||
func record(for type: RecordType, item: Any, index: Int, zoneID: CKRecordZone.ID, allItems: [Any]) -> CKRecord? {
|
||||
itemHandler.record(for: type, item: item, index: index, zoneID: zoneID, allItems: allItems)
|
||||
}
|
||||
|
||||
func deleteEntries(_ entries: [EntityOfKind]) {
|
||||
deletedEntries = entries
|
||||
}
|
||||
|
||||
func updateOrCreate(with entries: [CKRecord]) {
|
||||
updatedCreated = entries
|
||||
}
|
||||
}
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
@objc(LogEntity)
|
||||
final class LogEntity: NSManagedObject {
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
import CoreData
|
||||
|
||||
public enum LogActionType: String {
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum CloudKitAction {
|
||||
enum Reason {
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
@objc(DynamicTypesEntityMigrationPolicySync)
|
||||
final class DynamicTypesEntityMigrationPolicySync: NSEntityMigrationPolicy {
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
extension ServiceData {
|
||||
var comparisionDate: Date {
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum SecretValidation {
|
||||
private static let maxLenght: Int = 255
|
||||
|
@ -18,8 +18,12 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Common
|
||||
import CryptoKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum iCloudIdentifier {
|
||||
private static let v2Identifier = "_V2"
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
@objc(SectionCacheEntity)
|
||||
final class SectionCacheEntity: NSManagedObject {
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
import CoreData
|
||||
|
||||
final class SectionHandler {
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
@objc(ServiceCacheEntity)
|
||||
final class ServiceCacheEntity: NSManagedObject {
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
extension ServiceCacheEntity {
|
||||
var serviceData: ServiceData {
|
||||
|
@ -18,9 +18,14 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Common
|
||||
import CoreData
|
||||
#if os(iOS)
|
||||
import Common
|
||||
import Protection
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
import ProtectionWatch
|
||||
#endif
|
||||
|
||||
final class ServiceHandler {
|
||||
private let coreDataStack: CoreDataStack
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum ServiceEntryKey: String {
|
||||
case name
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
enum ServiceEntryKey2: String {
|
||||
case name
|
||||
|
@ -18,7 +18,11 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
import CloudKit
|
||||
|
||||
final class SyncHandler {
|
||||
@ -32,7 +36,9 @@ final class SyncHandler {
|
||||
|
||||
private var timeOffset: Int = 0
|
||||
|
||||
#if os(iOS)
|
||||
private var fromNotificationCompletionHandler: ((UIBackgroundFetchResult) -> Void)?
|
||||
#endif
|
||||
|
||||
typealias OtherError = (NSError) -> Void
|
||||
|
||||
@ -91,6 +97,7 @@ final class SyncHandler {
|
||||
cloudKit.deleteAllEntries = { [weak self] in self?.itemHandler.purge() }
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
func didReceiveRemoteNotification(
|
||||
userInfo: [AnyHashable: Any],
|
||||
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
|
||||
@ -106,6 +113,7 @@ final class SyncHandler {
|
||||
fromNotificationCompletionHandler = completionHandler
|
||||
synchronize()
|
||||
}
|
||||
#endif
|
||||
|
||||
func firstStart() {
|
||||
Log("SyncHandler - first start!", module: .cloudSync)
|
||||
@ -357,6 +365,7 @@ final class SyncHandler {
|
||||
return
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
if let fromNotificationCompletionHandler {
|
||||
if didSetNewData {
|
||||
fromNotificationCompletionHandler(.newData)
|
||||
@ -365,14 +374,17 @@ final class SyncHandler {
|
||||
}
|
||||
self.fromNotificationCompletionHandler = nil
|
||||
}
|
||||
#endif
|
||||
|
||||
finishedSync?()
|
||||
}
|
||||
|
||||
private func handleNotificationCompletionHandlerError() {
|
||||
#if os(iOS)
|
||||
Log("Sync Handler: handleNotificationCompletionHandlerError", module: .cloudSync)
|
||||
fromNotificationCompletionHandler?(.failed)
|
||||
fromNotificationCompletionHandler = nil
|
||||
#endif
|
||||
}
|
||||
|
||||
private func resetStack() {
|
||||
|
97
TwoFAS/Sync/SyncInstanceWatch.swift
Normal file
97
TwoFAS/Sync/SyncInstanceWatch.swift
Normal file
@ -0,0 +1,97 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2023 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Zbigniew Cisiński. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
import CommonWatch
|
||||
|
||||
public enum SyncInstanceWatch {
|
||||
private static var cloudHandler: CloudHandlerType!
|
||||
|
||||
public static func initialize() {
|
||||
let logHandler = LogHandler(coreDataStack: coreDataStack)
|
||||
let sectionHandler = SectionHandler(coreDataStack: coreDataStack)
|
||||
let serviceHandler = ServiceHandler(coreDataStack: coreDataStack)
|
||||
let infoHandler = InfoHandler()
|
||||
let commonItemHandler = CommonItemHandler()
|
||||
let cloudKit = CloudKit()
|
||||
|
||||
let itemHandler = ItemHandler(
|
||||
sectionHandler: sectionHandler,
|
||||
serviceHandler: serviceHandler,
|
||||
infoHandler: infoHandler,
|
||||
logHandler: logHandler
|
||||
)
|
||||
let itemHandlerMigrationProxy = ItemHandlerMigrationProxy(
|
||||
itemHandler: itemHandler
|
||||
)
|
||||
let syncHandler = SyncHandler(
|
||||
itemHandler: itemHandlerMigrationProxy,
|
||||
commonItemHandler: commonItemHandler,
|
||||
logHandler: logHandler,
|
||||
cloudKit: cloudKit
|
||||
)
|
||||
let cloudAvailability = CloudAvailability(container: syncHandler.container)
|
||||
cloudHandler = CloudHandler(
|
||||
cloudAvailability: cloudAvailability,
|
||||
syncHandler: syncHandler,
|
||||
itemHandler: itemHandler,
|
||||
itemHandlerMigrationProxy: itemHandlerMigrationProxy,
|
||||
cloudKit: cloudKit
|
||||
)
|
||||
|
||||
coreDataStack.performInBackground { context in
|
||||
Log("Migrating if needed. Trigger value \(context.hasChanges)", module: .cloudSync)
|
||||
}
|
||||
}
|
||||
public static func getCloudHandler() -> CloudHandlerType { cloudHandler }
|
||||
|
||||
private static let coreDataStack = CoreDataStack(
|
||||
readOnly: false,
|
||||
name: "Sync",
|
||||
bundle: Bundle(for: SyncHandler.self),
|
||||
migrator: CoreDataMigrator(
|
||||
momdSubdirectory: "Sync",
|
||||
versions: [
|
||||
CoreDataMigrationVersion(rawValue: "Sync"),
|
||||
CoreDataMigrationVersion(rawValue: "Sync2"),
|
||||
CoreDataMigrationVersion(rawValue: "Sync3"),
|
||||
CoreDataMigrationVersion(rawValue: "Sync4"),
|
||||
CoreDataMigrationVersion(rawValue: "Sync5")
|
||||
]) { _, toVersion in
|
||||
if toVersion.rawValue == "Sync5" {
|
||||
Log("Migrating to Sync5!", module: .cloudSync)
|
||||
SyncInstanceWatch.cloudHandler.resetStateBeforeSync()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private final class CommonServiceHandlerImpl: CommonServiceHandler {
|
||||
var commonDidDelete: CommonDidDelete?
|
||||
var commonDidModify: CommonDidModify?
|
||||
var commonDidCreate: CommonDidCreate?
|
||||
|
||||
func setServices(_ servicesservices: [ServiceData]) -> Bool {
|
||||
false
|
||||
}
|
||||
func getAllServices() -> [ServiceData] {
|
||||
[]
|
||||
}
|
||||
}
|
@ -19,7 +19,11 @@
|
||||
|
||||
import Foundation
|
||||
import CloudKit
|
||||
#if os(iOS)
|
||||
import Common
|
||||
#elseif os(watchOS)
|
||||
import CommonWatch
|
||||
#endif
|
||||
|
||||
final class SyncTokenHandler {
|
||||
private var databaseChangeToken: CKServerChangeToken?
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1530"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9E42BAB8B92008E7212"
|
||||
BuildableName = "CommonWatch.framework"
|
||||
BlueprintName = "CommonWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9E42BAB8B92008E7212"
|
||||
BuildableName = "CommonWatch.framework"
|
||||
BlueprintName = "CommonWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1530"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274CA242BAB8BE3008E7212"
|
||||
BuildableName = "ContentWatch.framework"
|
||||
BlueprintName = "ContentWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274CA242BAB8BE3008E7212"
|
||||
BuildableName = "ContentWatch.framework"
|
||||
BlueprintName = "ContentWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1530"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274CA582BAB8C3F008E7212"
|
||||
BuildableName = "ProtectionWatch.framework"
|
||||
BlueprintName = "ProtectionWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274CA582BAB8C3F008E7212"
|
||||
BuildableName = "ProtectionWatch.framework"
|
||||
BlueprintName = "ProtectionWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1530"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C98C2BAB89C7008E7212"
|
||||
BuildableName = "SyncWatch.framework"
|
||||
BlueprintName = "SyncWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C98C2BAB89C7008E7212"
|
||||
BuildableName = "SyncWatch.framework"
|
||||
BlueprintName = "SyncWatch"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1530"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9CC2BAB8ABB008E7212"
|
||||
BuildableName = "TwoFASWatch Watch App.app"
|
||||
BlueprintName = "TwoFASWatch Watch App"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C23666721FB2644900989ACA"
|
||||
BuildableName = "TwoFAS.app"
|
||||
BlueprintName = "TwoFAS"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "8">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9CC2BAB8ABB008E7212"
|
||||
BuildableName = "TwoFASWatch Watch App.app"
|
||||
BlueprintName = "TwoFASWatch Watch App"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
launchAutomaticallySubstyle = "8">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9CC2BAB8ABB008E7212"
|
||||
BuildableName = "TwoFASWatch Watch App.app"
|
||||
BlueprintName = "TwoFASWatch Watch App"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1530"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9CC2BAB8ABB008E7212"
|
||||
BuildableName = "TwoFASWatch Watch App.app"
|
||||
BlueprintName = "TwoFASWatch Watch App"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C23666721FB2644900989ACA"
|
||||
BuildableName = "TwoFAS.app"
|
||||
BlueprintName = "TwoFAS"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9CC2BAB8ABB008E7212"
|
||||
BuildableName = "TwoFASWatch Watch App.app"
|
||||
BlueprintName = "TwoFASWatch Watch App"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C274C9CC2BAB8ABB008E7212"
|
||||
BuildableName = "TwoFASWatch Watch App.app"
|
||||
BlueprintName = "TwoFASWatch Watch App"
|
||||
ReferencedContainer = "container:TwoFAS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
52
TwoFAS/TwoFASWatch Watch App/ContentView.swift
Normal file
52
TwoFAS/TwoFASWatch Watch App/ContentView.swift
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Zbigniew Cisiński. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SyncWatch
|
||||
import ProtectionWatch
|
||||
import CommonWatch
|
||||
|
||||
struct ContentView: View {
|
||||
@State var syncStstus = "Hello, world!"
|
||||
var body: some View {
|
||||
VStack {
|
||||
Image(systemName: "globe")
|
||||
.imageScale(.large)
|
||||
.foregroundStyle(.tint)
|
||||
Text(syncStstus)
|
||||
}
|
||||
.padding()
|
||||
.task {
|
||||
let protection = Protection()
|
||||
|
||||
EncryptionHolder.initialize(with: protection.localKeyEncryption)
|
||||
SyncInstanceWatch.initialize()
|
||||
let handler = SyncInstanceWatch.getCloudHandler()
|
||||
handler.registerForStateChange({ state in
|
||||
syncStstus = "\(state)"
|
||||
}, with: "listener!")
|
||||
handler.enable()
|
||||
handler.synchronize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.icloud-container-identifiers</key>
|
||||
<array>
|
||||
<string>iCloud.com.twofas.org.Vault</string>
|
||||
</array>
|
||||
<key>com.apple.developer.icloud-services</key>
|
||||
<array>
|
||||
<string>CloudKit</string>
|
||||
</array>
|
||||
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
||||
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.twofas.com</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
29
TwoFAS/TwoFASWatch Watch App/TwoFASWatchApp.swift
Normal file
29
TwoFAS/TwoFASWatch Watch App/TwoFASWatchApp.swift
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
|
||||
// Copyright © 2024 Two Factor Authentication Service, Inc.
|
||||
// Contributed by Zbigniew Cisiński. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct TwoFASWatch_Watch_AppApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user