Environment+Authenticate.swift 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. //
  2. // Environment+Authenticate.swift
  3. // LoopKitUI
  4. //
  5. // Created by Rick Pasetto on 8/3/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import LocalAuthentication
  9. import SwiftUI
  10. public typealias AuthenticationChallenge = (_ description: String, _ completion: @escaping (Result<Void, Error>) -> Void) -> Void
  11. fileprivate struct UnknownError: Swift.Error { }
  12. public struct LocalAuthentication {
  13. public static let deviceOwnerCheck: AuthenticationChallenge = { authenticationChallengeDescription, completion in
  14. let context = LAContext()
  15. var error: NSError?
  16. if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
  17. context.evaluatePolicy(.deviceOwnerAuthentication,
  18. localizedReason: authenticationChallengeDescription,
  19. reply: { (success, error) in
  20. DispatchQueue.main.async {
  21. assert(success || error != nil)
  22. completion(success ? .success(()) : .failure(error ?? UnknownError()))
  23. }
  24. })
  25. } else {
  26. // The logic here is to not fail to execute completion just because there is no authentication set up on the iPhone
  27. completion(.success(()))
  28. }
  29. }
  30. }
  31. private struct AuthenticationChallengeKey: EnvironmentKey {
  32. static let defaultValue: AuthenticationChallenge = LocalAuthentication.deviceOwnerCheck
  33. }
  34. extension EnvironmentValues {
  35. public var authenticate: AuthenticationChallenge {
  36. get { self[AuthenticationChallengeKey.self] }
  37. set { self[AuthenticationChallengeKey.self] = newValue }
  38. }
  39. }