From 301d7261c24386a54196ef05ba79868cdea091a2 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Tue, 21 Jan 2020 15:12:48 -0800 Subject: [PATCH] =?UTF-8?q?Fixes=20=E2=80=9CDevice=20Already=20Registered?= =?UTF-8?q?=E2=80=9D=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AltStore.xcodeproj/project.pbxproj | 4 + AltStore/Managing Apps/AppManager.swift | 14 ++- .../PrepareDeveloperAccountOperation.swift | 81 +++++++++++++++++ AltStore/Operations/ResignAppOperation.swift | 88 ++++++------------- 4 files changed, 125 insertions(+), 62 deletions(-) create mode 100644 AltStore/Operations/PrepareDeveloperAccountOperation.swift diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index e80ea505..445e1b60 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -144,6 +144,7 @@ BF9ABA4F22DD41A9008935CF /* UIColor+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9ABA4E22DD41A9008935CF /* UIColor+Hex.swift */; }; BFA8172923C56042001B5953 /* ServerConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172823C56042001B5953 /* ServerConnection.swift */; }; BFA8172B23C5633D001B5953 /* FetchAnisetteDataOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */; }; + BFA8172F23C5831A001B5953 /* PrepareDeveloperAccountOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172E23C5831A001B5953 /* PrepareDeveloperAccountOperation.swift */; }; BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB11691229322E400BB457C /* DatabaseManager.swift */; }; BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */; }; BFB3645A2325985F00CD0EB1 /* FindServerOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB364592325985F00CD0EB1 /* FindServerOperation.swift */; }; @@ -468,6 +469,7 @@ BF9B63C5229DD44D002F0A62 /* AltSign.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AltSign.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BFA8172823C56042001B5953 /* ServerConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnection.swift; sourceTree = ""; }; BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchAnisetteDataOperation.swift; sourceTree = ""; }; + BFA8172E23C5831A001B5953 /* PrepareDeveloperAccountOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepareDeveloperAccountOperation.swift; sourceTree = ""; }; BFB11691229322E400BB457C /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = ""; }; BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+ManagedObjectContext.swift"; sourceTree = ""; }; BFB1169C22932DB100BB457C /* apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = apps.json; sourceTree = ""; }; @@ -1155,6 +1157,7 @@ BF770E5322BC044E002A40FE /* AppOperationContext.swift */, BFE6326B22A86FF300F30809 /* AuthenticationOperation.swift */, BFB364592325985F00CD0EB1 /* FindServerOperation.swift */, + BFA8172E23C5831A001B5953 /* PrepareDeveloperAccountOperation.swift */, BFC1F38C22AEE3A4003AC21A /* DownloadAppOperation.swift */, BFDB6A0722AAED73007EA6D6 /* ResignAppOperation.swift */, BFDB6A0E22AB2776007EA6D6 /* SendAppOperation.swift */, @@ -1722,6 +1725,7 @@ BFF0B69A2322D7D0007A79E1 /* UIScreen+CompactHeight.swift in Sources */, BFD5D6EE230D8A86007955AB /* Patron.swift in Sources */, BF8F69C222E659F700049BA1 /* AppContentViewController.swift in Sources */, + BFA8172F23C5831A001B5953 /* PrepareDeveloperAccountOperation.swift in Sources */, BF08858522DE7EC800DE9F1E /* UpdateCollectionViewCell.swift in Sources */, BF258CE322EBAE2800023032 /* AppProtocol.swift in Sources */, BF770E5822BC3D0F002A40FE /* OperationGroup.swift in Sources */, diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index 8206b482..f4a2d10f 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -260,6 +260,18 @@ private extension AppManager refreshAnisetteDataOperation.addDependency(authenticationOperation ?? findServerOperation) operations.append(refreshAnisetteDataOperation) + /* Prepare Developer Account */ + let prepareDeveloperAccountOperation = PrepareDeveloperAccountOperation(group: group) + prepareDeveloperAccountOperation.resultHandler = { (result) in + switch result + { + case .failure(let error): group.error = error + case .success: break + } + } + prepareDeveloperAccountOperation.addDependency(refreshAnisetteDataOperation) + operations.append(prepareDeveloperAccountOperation) + for app in apps { let context = AppOperationContext(bundleIdentifier: app.bundleIdentifier, group: group) @@ -272,7 +284,7 @@ private extension AppManager guard let resignedApp = self.process(result, context: context) else { return } context.resignedApp = resignedApp } - resignAppOperation.addDependency(refreshAnisetteDataOperation) + resignAppOperation.addDependency(prepareDeveloperAccountOperation) progress.addChild(resignAppOperation.progress, withPendingUnitCount: 20) operations.append(resignAppOperation) diff --git a/AltStore/Operations/PrepareDeveloperAccountOperation.swift b/AltStore/Operations/PrepareDeveloperAccountOperation.swift new file mode 100644 index 00000000..cfa21e06 --- /dev/null +++ b/AltStore/Operations/PrepareDeveloperAccountOperation.swift @@ -0,0 +1,81 @@ +// +// PrepareDeveloperAccountOperation.swift +// AltStore +// +// Created by Riley Testut on 1/7/20. +// Copyright © 2020 Riley Testut. All rights reserved. +// + +import Foundation +import Roxas + +import AltSign + +@objc(PrepareDeveloperAccountOperation) +class PrepareDeveloperAccountOperation: ResultOperation +{ + let group: OperationGroup + + init(group: OperationGroup) + { + self.group = group + + super.init() + + self.progress.totalUnitCount = 2 + } + + override func main() + { + super.main() + + if let error = self.group.error + { + self.finish(.failure(error)) + return + } + + guard + let signer = self.group.signer, + let session = self.group.session + else { return self.finish(.failure(OperationError.invalidParameters)) } + + // Register Device + self.registerCurrentDevice(for: signer.team, session: session) { (result) in + let result = result.map { _ in () } + self.finish(result) + } + } +} + +private extension PrepareDeveloperAccountOperation +{ + func registerCurrentDevice(for team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result) -> Void) + { + guard let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String else { + return completionHandler(.failure(OperationError.unknownUDID)) + } + + ALTAppleAPI.shared.fetchDevices(for: team, session: session) { (devices, error) in + do + { + let devices = try Result(devices, error).get() + + if let device = devices.first(where: { $0.identifier == udid }) + { + completionHandler(.success(device)) + } + else + { + ALTAppleAPI.shared.registerDevice(name: UIDevice.current.name, identifier: udid, team: team, session: session) { (device, error) in + completionHandler(Result(device, error)) + } + } + } + catch + { + completionHandler(.failure(error)) + } + } + } +} diff --git a/AltStore/Operations/ResignAppOperation.swift b/AltStore/Operations/ResignAppOperation.swift index e0e3ed76..e5499396 100644 --- a/AltStore/Operations/ResignAppOperation.swift +++ b/AltStore/Operations/ResignAppOperation.swift @@ -41,46 +41,41 @@ class ResignAppOperation: ResultOperation let session = self.context.group.session else { return self.finish(.failure(OperationError.invalidParameters)) } - // Register Device - self.registerCurrentDevice(for: signer.team, session: session) { (result) in - guard let _ = self.process(result) else { return } + // Prepare Provisioning Profiles + self.prepareProvisioningProfiles(app.fileURL, team: signer.team, session: session) { (result) in + guard let profiles = self.process(result) else { return } - // Prepare Provisioning Profiles - self.prepareProvisioningProfiles(app.fileURL, team: signer.team, session: session) { (result) in - guard let profiles = self.process(result) else { return } + // Prepare app bundle + let prepareAppProgress = Progress.discreteProgress(totalUnitCount: 2) + self.progress.addChild(prepareAppProgress, withPendingUnitCount: 3) + + let prepareAppBundleProgress = self.prepareAppBundle(for: app, profiles: profiles) { (result) in + guard let appBundleURL = self.process(result) else { return } - // Prepare app bundle - let prepareAppProgress = Progress.discreteProgress(totalUnitCount: 2) - self.progress.addChild(prepareAppProgress, withPendingUnitCount: 3) + print("Resigning App:", self.context.bundleIdentifier) - let prepareAppBundleProgress = self.prepareAppBundle(for: app, profiles: profiles) { (result) in - guard let appBundleURL = self.process(result) else { return } + // Resign app bundle + let resignProgress = self.resignAppBundle(at: appBundleURL, signer: signer, profiles: Array(profiles.values)) { (result) in + guard let resignedURL = self.process(result) else { return } - print("Resigning App:", self.context.bundleIdentifier) - - // Resign app bundle - let resignProgress = self.resignAppBundle(at: appBundleURL, signer: signer, profiles: Array(profiles.values)) { (result) in - guard let resignedURL = self.process(result) else { return } + // Finish + do + { + let destinationURL = InstalledApp.refreshedIPAURL(for: app) + try FileManager.default.copyItem(at: resignedURL, to: destinationURL, shouldReplace: true) - // Finish - do - { - let destinationURL = InstalledApp.refreshedIPAURL(for: app) - try FileManager.default.copyItem(at: resignedURL, to: destinationURL, shouldReplace: true) - - // Use appBundleURL since we need an app bundle, not .ipa. - guard let resignedApplication = ALTApplication(fileURL: appBundleURL) else { throw OperationError.invalidApp } - self.finish(.success(resignedApplication)) - } - catch - { - self.finish(.failure(error)) - } + // Use appBundleURL since we need an app bundle, not .ipa. + guard let resignedApplication = ALTApplication(fileURL: appBundleURL) else { throw OperationError.invalidApp } + self.finish(.success(resignedApplication)) + } + catch + { + self.finish(.failure(error)) } - prepareAppProgress.addChild(resignProgress, withPendingUnitCount: 1) } - prepareAppProgress.addChild(prepareAppBundleProgress, withPendingUnitCount: 1) + prepareAppProgress.addChild(resignProgress, withPendingUnitCount: 1) } + prepareAppProgress.addChild(prepareAppBundleProgress, withPendingUnitCount: 1) } } @@ -105,35 +100,6 @@ class ResignAppOperation: ResultOperation private extension ResignAppOperation { - func registerCurrentDevice(for team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result) -> Void) - { - guard let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String else { - return completionHandler(.failure(OperationError.unknownUDID)) - } - - ALTAppleAPI.shared.fetchDevices(for: team, session: session) { (devices, error) in - do - { - let devices = try Result(devices, error).get() - - if let device = devices.first(where: { $0.identifier == udid }) - { - completionHandler(.success(device)) - } - else - { - ALTAppleAPI.shared.registerDevice(name: UIDevice.current.name, identifier: udid, team: team, session: session) { (device, error) in - completionHandler(Result(device, error)) - } - } - } - catch - { - completionHandler(.failure(error)) - } - } - } - func prepareProvisioningProfiles(_ fileURL: URL, team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<[String: ALTProvisioningProfile], Error>) -> Void) { guard let bundle = Bundle(url: fileURL), let app = ALTApplication(fileURL: fileURL) else { return completionHandler(.failure(OperationError.invalidApp)) }