apple_kit

Apple-native services for Radroots iOS and macOS apps
git clone https://radroots.dev/git/apple_kit.git
Log | Files | Refs | README | LICENSE

RadrootsUserPresence.swift (3359B)


      1 import Foundation
      2 
      3 public enum RadrootsUserPresencePolicy: String, Sendable, Equatable, Hashable, CaseIterable {
      4     case deviceOwnerAuthentication
      5     case deviceOwnerAuthenticationWithBiometrics
      6 }
      7 
      8 public enum RadrootsUserPresenceSupport: String, Sendable, Equatable, Hashable {
      9     case none
     10     case deviceCredential
     11     case biometricsOrDeviceCredential
     12 }
     13 
     14 public enum RadrootsBiometryKind: String, Sendable, Equatable, Hashable {
     15     case none
     16     case touchID
     17     case faceID
     18     case opticID
     19     case unknown
     20 }
     21 
     22 public struct RadrootsUserPresenceStatus: Sendable, Equatable, Hashable {
     23     public let support: RadrootsUserPresenceSupport
     24     public let biometryKind: RadrootsBiometryKind
     25     public let canEvaluateDeviceCredential: Bool
     26     public let canEvaluateBiometrics: Bool
     27 
     28     public init(
     29         support: RadrootsUserPresenceSupport,
     30         biometryKind: RadrootsBiometryKind,
     31         canEvaluateDeviceCredential: Bool,
     32         canEvaluateBiometrics: Bool
     33     ) {
     34         self.support = support
     35         self.biometryKind = biometryKind
     36         self.canEvaluateDeviceCredential = canEvaluateDeviceCredential
     37         self.canEvaluateBiometrics = canEvaluateBiometrics
     38     }
     39 
     40     public static let unavailable = Self(
     41         support: .none,
     42         biometryKind: .none,
     43         canEvaluateDeviceCredential: false,
     44         canEvaluateBiometrics: false
     45     )
     46 }
     47 
     48 public struct RadrootsUserPresenceRequest: Sendable, Equatable, Hashable {
     49     public let policy: RadrootsUserPresencePolicy
     50     public let reason: String
     51 
     52     public init(
     53         policy: RadrootsUserPresencePolicy = .deviceOwnerAuthentication,
     54         reason: String
     55     ) throws {
     56         let normalizedReason = reason.trimmingCharacters(in: .whitespacesAndNewlines)
     57         guard !normalizedReason.isEmpty else {
     58             throw RadrootsUserPresenceError.invalidRequest
     59         }
     60         self.policy = policy
     61         self.reason = normalizedReason
     62     }
     63 }
     64 
     65 public struct RadrootsUserPresenceResult: Sendable, Equatable, Hashable {
     66     public let policy: RadrootsUserPresencePolicy
     67     public let verified: Bool
     68 
     69     public init(policy: RadrootsUserPresencePolicy, verified: Bool) {
     70         self.policy = policy
     71         self.verified = verified
     72     }
     73 }
     74 
     75 public enum RadrootsUserPresenceError: Error, Equatable, Sendable {
     76     case invalidRequest
     77     case userCancelled
     78     case permissionDenied
     79     case unavailable
     80     case timeout
     81     case transientFailure
     82     case permanentFailure
     83 }
     84 
     85 extension RadrootsUserPresenceError: LocalizedError {
     86     public var errorDescription: String? {
     87         switch self {
     88         case .invalidRequest: "The user-presence request is invalid."
     89         case .userCancelled: "User-presence verification was cancelled."
     90         case .permissionDenied: "User-presence verification was denied."
     91         case .unavailable: "User-presence verification is unavailable."
     92         case .timeout: "User-presence verification timed out."
     93         case .transientFailure: "User-presence verification could not be completed temporarily."
     94         case .permanentFailure: "User-presence verification could not be completed."
     95         }
     96     }
     97 }
     98 
     99 public protocol RadrootsUserPresence: Sendable {
    100     func currentStatus() async throws -> RadrootsUserPresenceStatus
    101     func verify(_ request: RadrootsUserPresenceRequest) async throws -> RadrootsUserPresenceResult
    102 }