113 lines
4.0 KiB
Swift
113 lines
4.0 KiB
Swift
import Foundation
|
|
|
|
public struct StorageAuditReport: Sendable {
|
|
public static func items<C: StorageKeyCatalog>(for catalog: C.Type) -> [StorageKeyDescriptor] {
|
|
catalog.allKeys.map(\.descriptor)
|
|
}
|
|
|
|
public static func renderText<C: StorageKeyCatalog>(for catalog: C.Type) -> String {
|
|
renderText(items(for: catalog))
|
|
}
|
|
|
|
public static func renderText(_ items: [StorageKeyDescriptor]) -> String {
|
|
let lines = items.map { item in
|
|
var parts: [String] = []
|
|
parts.append("name=\(item.name)")
|
|
parts.append("domain=\(string(for: item.domain))")
|
|
parts.append("security=\(string(for: item.security))")
|
|
parts.append("serializer=\(item.serializer)")
|
|
parts.append("value=\(item.valueType)")
|
|
parts.append("owner=\(item.owner)")
|
|
parts.append("availability=\(string(for: item.availability))")
|
|
parts.append("sync=\(string(for: item.syncPolicy))")
|
|
parts.append("description=\(item.description)")
|
|
return parts.joined(separator: " | ")
|
|
}
|
|
return lines.joined(separator: "\n")
|
|
}
|
|
|
|
private static func string(for domain: StorageDomain) -> String {
|
|
switch domain {
|
|
case .userDefaults(let suite):
|
|
return "userDefaults(\(suite ?? "standard"))"
|
|
case .appGroupUserDefaults(let identifier):
|
|
return "appGroupUserDefaults(\(identifier ?? "default"))"
|
|
case .keychain(let service):
|
|
return "keychain(\(service ?? "default"))"
|
|
case .fileSystem(let directory):
|
|
return "fileSystem(\(string(for: directory)))"
|
|
case .encryptedFileSystem(let directory):
|
|
return "encryptedFileSystem(\(string(for: directory)))"
|
|
case .appGroupFileSystem(let identifier, let directory):
|
|
return "appGroupFileSystem(\(identifier ?? "default"), \(string(for: directory)))"
|
|
}
|
|
}
|
|
|
|
private static func string(for directory: FileDirectory) -> String {
|
|
switch directory {
|
|
case .documents:
|
|
return "documents"
|
|
case .caches:
|
|
return "caches"
|
|
case .custom(let url):
|
|
return "custom(\(url.path))"
|
|
}
|
|
}
|
|
|
|
private static func string(for availability: PlatformAvailability) -> String {
|
|
switch availability {
|
|
case .all:
|
|
return "all"
|
|
case .phoneOnly:
|
|
return "phoneOnly"
|
|
case .watchOnly:
|
|
return "watchOnly"
|
|
case .phoneWithWatchSync:
|
|
return "phoneWithWatchSync"
|
|
}
|
|
}
|
|
|
|
private static func string(for syncPolicy: SyncPolicy) -> String {
|
|
switch syncPolicy {
|
|
case .never:
|
|
return "never"
|
|
case .manual:
|
|
return "manual"
|
|
case .automaticSmall:
|
|
return "automaticSmall"
|
|
}
|
|
}
|
|
|
|
private static func string(for security: SecurityPolicy) -> String {
|
|
switch security {
|
|
case .none:
|
|
return "none"
|
|
case .encrypted(let policy):
|
|
return "encrypted(\(string(for: policy)))"
|
|
case .keychain(let accessibility, let accessControl):
|
|
let accessControlValue = accessControl?.displayName ?? "none"
|
|
return "keychain(\(accessibility.displayName), \(accessControlValue))"
|
|
}
|
|
}
|
|
|
|
private static func string(for policy: SecurityPolicy.EncryptionPolicy) -> String {
|
|
switch policy {
|
|
case .aes256(let derivation):
|
|
return "aes256(\(string(for: derivation)))"
|
|
case .chacha20Poly1305(let derivation):
|
|
return "chacha20Poly1305(\(string(for: derivation)))"
|
|
case .external(let source, let derivation):
|
|
return "external(\(source.id), \(string(for: derivation)))"
|
|
}
|
|
}
|
|
|
|
private static func string(for derivation: SecurityPolicy.KeyDerivation) -> String {
|
|
switch derivation {
|
|
case .pbkdf2(let iterations, _):
|
|
return "pbkdf2(\(iterations))"
|
|
case .hkdf:
|
|
return "hkdf"
|
|
}
|
|
}
|
|
}
|