mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Supports bypassing “Undeclared Permissions” error while sources are in beta
Presents error alert that can be explicitly bypassed by user when sideloading apps with undeclared permissions, and also allows user to view all undeclared permissions.
This commit is contained in:
@@ -160,13 +160,53 @@ final class VerifyAppOperation: ResultOperation<Void>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Task<Void, Never> {
|
Task<Void, Never> {
|
||||||
|
do
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
guard let ipaURL = self.context.ipaURL else { throw OperationError.appNotFound(name: app.name) }
|
guard let ipaURL = self.context.ipaURL else { throw OperationError.appNotFound(name: app.name) }
|
||||||
|
|
||||||
try await self.verifyHash(of: app, at: ipaURL, matches: appVersion)
|
try await self.verifyHash(of: app, at: ipaURL, matches: appVersion)
|
||||||
try await self.verifyDownloadedVersion(of: app, matches: appVersion)
|
try await self.verifyDownloadedVersion(of: app, matches: appVersion)
|
||||||
|
|
||||||
|
// Verify permissions last in case user bypasses error.
|
||||||
try await self.verifyPermissions(of: app, match: appVersion)
|
try await self.verifyPermissions(of: app, match: appVersion)
|
||||||
|
}
|
||||||
|
catch let error as VerificationError where error.code == .undeclaredPermissions
|
||||||
|
{
|
||||||
|
#if !BETA
|
||||||
|
throw error
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if let trustedSources = UserDefaults.shared.trustedSources, let sourceID = await self.context.$appVersion.sourceID
|
||||||
|
{
|
||||||
|
let isTrusted = trustedSources.contains { $0.identifier == sourceID }
|
||||||
|
guard !isTrusted else {
|
||||||
|
// Don't enforce permission checking for Trusted Sources while 2.0 is in beta.
|
||||||
|
return self.finish(.success(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// While in beta, allow users to temporarily bypass permissions alert
|
||||||
|
// so source maintainers have time to update their sources.
|
||||||
|
guard let presentingViewController = self.context.presentingViewController else { throw error }
|
||||||
|
|
||||||
|
let message = NSLocalizedString("While AltStore 2.0 is in beta, you may choose to ignore this warning at your own risk until the source is updated.", comment: "")
|
||||||
|
|
||||||
|
let ignoreAction = await UIAlertAction(title: NSLocalizedString("Install Anyway", comment: ""), style: .destructive)
|
||||||
|
let viewPermissionsAction = await UIAlertAction(title: NSLocalizedString("View Permisions", comment: ""), style: .default)
|
||||||
|
|
||||||
|
while true
|
||||||
|
{
|
||||||
|
let action = try await presentingViewController.presentConfirmationAlert(title: error.errorFailureReason,
|
||||||
|
message: message,
|
||||||
|
actions: [ignoreAction, viewPermissionsAction])
|
||||||
|
|
||||||
|
guard action == viewPermissionsAction else { break } // break loop to continue with installation (unless we're viewing permissions).
|
||||||
|
|
||||||
|
await presentingViewController.presentAlert(title: NSLocalizedString("Undeclared Permissions", comment: ""), message: error.recoverySuggestion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.finish(.success(()))
|
self.finish(.success(()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public extension NSManagedObjectContext
|
|||||||
public extension UIViewController
|
public extension UIViewController
|
||||||
{
|
{
|
||||||
@MainActor
|
@MainActor
|
||||||
func presentAlert(title: String, message: String, action: UIAlertAction? = nil) async
|
func presentAlert(title: String, message: String?, action: UIAlertAction? = nil) async
|
||||||
{
|
{
|
||||||
let action = action ?? .ok
|
let action = action ?? .ok
|
||||||
|
|
||||||
@@ -79,19 +79,33 @@ public extension UIViewController
|
|||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
func presentConfirmationAlert(title: String, message: String, primaryAction: UIAlertAction, cancelAction: UIAlertAction? = nil) async throws
|
func presentConfirmationAlert(title: String, message: String, primaryAction: UIAlertAction, cancelAction: UIAlertAction? = nil) async throws
|
||||||
|
{
|
||||||
|
_ = try await self.presentConfirmationAlert(title: title, message: message, actions: [primaryAction], cancelAction: cancelAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func presentConfirmationAlert(title: String, message: String, actions: [UIAlertAction], cancelAction: UIAlertAction? = nil) async throws -> UIAlertAction
|
||||||
{
|
{
|
||||||
let cancelAction = cancelAction ?? .cancel
|
let cancelAction = cancelAction ?? .cancel
|
||||||
|
|
||||||
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
let action = try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<UIAlertAction, Error>) in
|
||||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: cancelAction.title, style: cancelAction.style) { _ in
|
alertController.addAction(UIAlertAction(title: cancelAction.title, style: cancelAction.style) { _ in
|
||||||
continuation.resume(throwing: CancellationError())
|
continuation.resume(throwing: CancellationError())
|
||||||
})
|
})
|
||||||
alertController.addAction(UIAlertAction(title: primaryAction.title, style: primaryAction.style) { _ in
|
|
||||||
continuation.resume()
|
for action in actions
|
||||||
|
{
|
||||||
|
alertController.addAction(UIAlertAction(title: action.title, style: action.style) { alertAction in
|
||||||
|
// alertAction is different than the action provided,
|
||||||
|
// so return original action instead for == comparison.
|
||||||
|
continuation.resume(returning: action)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
self.present(alertController, animated: true)
|
self.present(alertController, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user