Files
SideStore/AltStore/Authentication/RefreshAltStoreViewController.swift
Riley Testut e785fc47ee Fixes issue where AltStore revokes its own certificate
Uses embedded certificate from AltServer if possible, but then falls back to asking user to refresh AltStore manually if the certificate used to install AltStore is revoked.
2019-10-28 13:16:55 -07:00

88 lines
3.4 KiB
Swift

//
// RefreshAltStoreViewController.swift
// AltStore
//
// Created by Riley Testut on 10/26/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
import AltSign
import Roxas
class RefreshAltStoreViewController: UIViewController
{
var signer: ALTSigner!
var completionHandler: ((Result<Void, Error>) -> Void)?
@IBOutlet private var placeholderView: RSTPlaceholderView!
override func viewDidLoad()
{
super.viewDidLoad()
self.placeholderView.textLabel.isHidden = true
self.placeholderView.detailTextLabel.textAlignment = .left
self.placeholderView.detailTextLabel.textColor = UIColor.white.withAlphaComponent(0.6)
self.placeholderView.detailTextLabel.text = NSLocalizedString("AltStore was unable to use an existing signing certificate, so it had to create a new one. This will cause any apps installed with an existing certificate to expire — including AltStore.\n\nTo prevent AltStore from expiring early, please refresh the app now. AltStore will quit once refreshing is complete.", comment: "")
}
}
private extension RefreshAltStoreViewController
{
@IBAction func refreshAltStore(_ sender: PillButton)
{
guard let altStore = InstalledApp.fetchAltStore(in: DatabaseManager.shared.viewContext) else { return }
func refresh()
{
sender.isIndicatingActivity = true
if let progress = AppManager.shared.refreshProgress(for: altStore) ?? AppManager.shared.installationProgress(for: altStore)
{
// Cancel pending AltStore refresh so we can start a new one.
progress.cancel()
}
let group = OperationGroup()
group.signer = self.signer // Prevent us from trying to authenticate a second time.
group.completionHandler = { (result) in
if let error = result.error ?? result.value?.values.compactMap({ $0.error }).first
{
DispatchQueue.main.async {
sender.progress = nil
sender.isIndicatingActivity = false
let alertController = UIAlertController(title: NSLocalizedString("Failed to Refresh AltStore", comment: ""), message: error.localizedDescription, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Try Again", comment: ""), style: .default, handler: { (action) in
refresh()
}))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Refresh Later", comment: ""), style: .cancel, handler: { (action) in
self.completionHandler?(.failure(error))
}))
self.present(alertController, animated: true, completion: nil)
}
}
else
{
self.completionHandler?(.success(()))
}
}
_ = AppManager.shared.refresh([altStore], presentingViewController: self, group: group)
sender.progress = group.progress
}
refresh()
}
@IBAction func cancel(_ sender: UIButton)
{
self.completionHandler?(.failure(OperationError.cancelled))
}
}