Files
SideStore/AltStoreCore/Model/AppPermission.swift
2023-05-29 16:50:17 -05:00

112 lines
3.2 KiB
Swift

//
// AppPermission.swift
// AltStore
//
// Created by Riley Testut on 7/23/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import CoreData
import UIKit
import AltSign
@objc(AppPermission) @dynamicMemberLookup
public class AppPermission: NSManagedObject, Decodable, Fetchable
{
/* Properties */
@NSManaged public var type: ALTAppPermissionType
@NSManaged public var usageDescription: String?
@nonobjc public var permission: any ALTAppPermission {
switch self.type
{
case .entitlement: return ALTEntitlement(rawValue: self._permission)
case .privacy: return ALTAppPrivacyPermission(rawValue: self._permission)
default: return UnknownAppPermission(rawValue: self._permission)
}
}
@NSManaged @objc(permission) private var _permission: String
// Set by StoreApp.
@NSManaged public var appBundleID: String?
/* Relationships */
@NSManaged public internal(set) var app: StoreApp?
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
{
super.init(entity: entity, insertInto: context)
}
private enum CodingKeys: String, CodingKey
{
case entitlement
case privacyType = "privacy"
case usageDescription
}
public required init(from decoder: Decoder) throws
{
guard let context = decoder.managedObjectContext else { preconditionFailure("Decoder must have non-nil NSManagedObjectContext.") }
super.init(entity: AppPermission.entity(), insertInto: context)
do
{
let container = try decoder.container(keyedBy: CodingKeys.self)
self.usageDescription = try container.decodeIfPresent(String.self, forKey: .usageDescription)
if let entitlement = try container.decodeIfPresent(String.self, forKey: .entitlement)
{
self._permission = entitlement
self.type = .entitlement
}
else if let privacyType = try container.decodeIfPresent(String.self, forKey: .privacyType)
{
self._permission = privacyType
self.type = .privacy
}
else
{
self._permission = ""
self.type = .unknown
// We don't want to save any unknown permissions, but can't throw error
// without making the entire decoding fail, so just delete self instead.
context.delete(self)
}
}
catch
{
if let context = self.managedObjectContext
{
context.delete(self)
}
throw error
}
}
}
public extension AppPermission
{
@nonobjc class func fetchRequest() -> NSFetchRequest<AppPermission>
{
return NSFetchRequest<AppPermission>(entityName: "AppPermission")
}
}
// @dynamicMemberLookup
public extension AppPermission
{
// Convenience for accessing .permission properties.
subscript<T>(dynamicMember keyPath: KeyPath<any ALTAppPermission, T>) -> T {
get {
return self.permission[keyPath: keyPath]
}
}
}