Verifies all privacy + background mode permissions have usage descriptions

This commit is contained in:
Riley Testut
2023-05-15 15:29:51 -05:00
committed by Magesh K
parent fd89f35246
commit d89c0f3e36

View File

@@ -24,6 +24,8 @@ extension SourceError
case changedID
case duplicate
case missingPermissionUsageDescription
}
static func unsupported(_ source: Source) -> SourceError { SourceError(code: .unsupported, source: source) }
@@ -32,6 +34,10 @@ extension SourceError
static func changedID(_ identifier: String, previousID: String, source: Source) -> SourceError { SourceError(code: .changedID, source: source, sourceID: identifier, previousSourceID: previousID) }
static func duplicate(_ source: Source, previousSourceName: String?) -> SourceError { SourceError(code: .duplicate, source: source, previousSourceName: previousSourceName) }
static func missingPermissionUsageDescription(for permission: any ALTAppPermission, app: StoreApp, source: Source) -> SourceError {
SourceError(code: .missingPermissionUsageDescription, source: source, app: app, permission: permission)
}
}
struct SourceError: ALTLocalizedError
@@ -51,6 +57,9 @@ struct SourceError: ALTLocalizedError
@UserInfoValue var sourceID: String?
@UserInfoValue var previousSourceID: String?
@UserInfoValue
var permission: (any ALTAppPermission)?
var errorFailureReason: String {
switch self.code
{
@@ -90,6 +99,16 @@ struct SourceError: ALTLocalizedError
let failureReason = baseMessage + " (“\(previousSourceName)”)."
return failureReason
case .missingPermissionUsageDescription:
let appName = self.$app.name ?? String(format: NSLocalizedString("an app in source “%@”", comment: ""), self.$source.name)
guard let permission else {
return String(format: NSLocalizedString("A permission for %@ is missing a usage description.", comment: ""), appName)
}
let permissionType = permission.type.localizedName ?? NSLocalizedString("Permission", comment: "")
let failureReason = String(format: NSLocalizedString("The %@ '%@' for %@ is missing a usage description.", comment: ""), permissionType.lowercased(), permission.rawValue, appName)
return failureReason
}
}
@@ -242,6 +261,17 @@ private extension FetchSourceOperation
guard !versions.contains(version.version) else { throw SourceError.duplicateVersion(version.version, for: app, source: source) }
versions.insert(version.version)
}
for permission in app.permissions
{
switch permission.type
{
case .privacy, .backgroundMode:
guard permission.usageDescription != nil else { throw SourceError.missingPermissionUsageDescription(for: permission.permission, app: app, source: source) }
default: break
}
}
}
if let previousSourceID = self.$source.identifier