apple_kit

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

RadrootsUserPresence.swift (3358B)


      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("user presence reason cannot be empty")
     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(String)
     77     case userCancelled(String)
     78     case permissionDenied(String)
     79     case unavailable(String)
     80     case timeout(String)
     81     case transientFailure(String)
     82     case permanentFailure(String)
     83 }
     84 
     85 extension RadrootsUserPresenceError: LocalizedError {
     86     public var errorDescription: String? {
     87         switch self {
     88         case .invalidRequest(let message):
     89             message
     90         case .userCancelled(let message):
     91             message
     92         case .permissionDenied(let message):
     93             message
     94         case .unavailable(let message):
     95             message
     96         case .timeout(let message):
     97             message
     98         case .transientFailure(let message):
     99             message
    100         case .permanentFailure(let message):
    101             message
    102         }
    103     }
    104 }
    105 
    106 public protocol RadrootsUserPresence: Sendable {
    107     func currentStatus() async throws -> RadrootsUserPresenceStatus
    108     func verify(_ request: RadrootsUserPresenceRequest) async throws -> RadrootsUserPresenceResult
    109 }