Skip to content

Commit bfc53b2

Browse files
authored
[Chore]: Add biometrical permissions (#148)
1 parent 7a7df32 commit bfc53b2

File tree

4 files changed

+103
-3
lines changed

4 files changed

+103
-3
lines changed

Package.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,16 @@ let permissionsTargets: [Target] = [
105105
dependencies: ["Introspect", .target(name: "CorePermissionsSwiftUI")],
106106
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
107107
),
108-
.target(name: "PermissionsSwiftUISiri",
109-
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
110-
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"])]
108+
.target(
109+
name: "PermissionsSwiftUISiri",
110+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
111+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
112+
),
113+
.target(
114+
name: "PermissionsSwiftUIBiometrics",
115+
dependencies: ["Introspect", .target(name: "CorePermissionsSwiftUI")],
116+
exclude: ["../../Tsts/PermissionsSwiftUITests/__Snapshots__"]
117+
)]
111118

112119
let package = Package(
113120
name: "PermissionsSwiftUI",

Sources/CorePermissionsSwiftUI/Model/PermissionType/PermissionType.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ public enum PermissionType: Hashable, Equatable {
4040
///Permission that allows Siri and Maps to communicate with your app
4141
case siri
4242

43+
/// Permission that grants access to biometric authentication in your application.
44+
///
45+
/// The `biometrics` permission enables the use of biometric authentication features, such as Face ID, Touch ID or OpticID,
46+
/// allowing users to securely authenticate themselves using their unique biometric data.
47+
@available(iOS 13, macOS 11, *) case biometrics
48+
4349
///In order for app to track user's data across apps and websites, the tracking permission is needed
4450
@available(iOS 14, tvOS 14, *) case tracking
4551
#if !os(tvOS)

Sources/CorePermissionsSwiftUI/Store/ComponentsStore/PermissionComponentsStore.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ public struct PermissionComponentsStore {
2929
*/
3030
public init(){}
3131
//MARK: Permission Components
32+
/// The displayed text and image icon for the biometrics permission
33+
public var biometricPermission = JMPermission(
34+
imageIcon: AnyView(Image(systemName: "faceid")),
35+
title: "Biometrics",
36+
description: "Allow to lock/hide your data from other persons"
37+
)
38+
3239
///The displayed text and image icon for the camera permission
3340
public var cameraPermission = JMPermission(
3441
imageIcon: AnyView(Image(systemName: "camera.fill")),
@@ -132,6 +139,9 @@ extension PermissionComponentsStore {
132139
case .location:
133140
modify(&self.locationPermission)
134141
return self.locationPermission
142+
case .biometrics:
143+
modify(&self.biometricPermission)
144+
return self.biometricPermission
135145
case .locationAlways:
136146
modify(&self.locationAlwaysPermission)
137147
return self.locationAlwaysPermission
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//
2+
// JMBiometricsPermissionManager.swift
3+
//
4+
//
5+
// Created by Nevio Hirani on 20.01.24.
6+
// Github: N3v1 -
7+
//
8+
9+
import UIKit
10+
11+
import LocalAuthentication
12+
import CorePermissionsSwiftUI
13+
14+
/// A permission manager for handling biometric authentication requests.
15+
@available(iOS 13.0, macOS 11.0, *)
16+
public extension PermissionManager {
17+
/// Shared instance for managing biometric permissions.
18+
static let opticBiometrics = JMBiometricPermissionManager()
19+
}
20+
21+
/// A permission manager specifically designed for handling biometric authentication requests, such as Face ID, Touch ID and Optic ID.
22+
///
23+
/// `JMBiometricPermissionManager` provides a streamlined interface for checking and requesting biometric authentication permissions.
24+
/// It encapsulates the complexities associated with the LocalAuthentication framework, making it easy to integrate biometric security
25+
/// features into your app. The class is part of the `CorePermissionsSwiftUI` framework and aligns with the standardized `PermissionManager` protocol.
26+
///
27+
/// ## Usage
28+
/// To utilize biometric authentication in your application, follow the guide in the README.md
29+
@available(iOS 13.0, macOS 11.0, *)
30+
public final class JMBiometricPermissionManager: PermissionManager {
31+
32+
public override var permissionType: PermissionType {
33+
.biometrics
34+
}
35+
36+
/// Retrieves the current authorization status for biometric authentication.
37+
///
38+
/// - Returns: The current authorization status, indicating whether biometric authentication is authorized, denied, or not determined.
39+
public override var authorizationStatus: AuthorizationStatus {
40+
let context = LAContext()
41+
var error: NSError?
42+
43+
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
44+
return .authorized
45+
} else {
46+
switch error?.code {
47+
case LAError.Code.biometryLockout.rawValue, LAError.Code.biometryNotAvailable.rawValue,
48+
LAError.Code.biometryNotEnrolled.rawValue:
49+
return .denied
50+
default:
51+
return .notDetermined
52+
}
53+
}
54+
}
55+
56+
/// Requests permission for biometric authentication with a completion handler.
57+
///
58+
/// - Parameters:
59+
/// - completion: A closure to be called once the request is processed.
60+
/// The closure takes a boolean indicating whether the permission was granted
61+
/// and an optional error in case of failure.
62+
public override func requestPermission(completion: @escaping (Bool, Error?) -> Void) {
63+
let context = LAContext()
64+
65+
let localizedReason = "Authenticate to access biometric features"
66+
67+
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: localizedReason) { success, error in
68+
DispatchQueue.main.async {
69+
if success {
70+
completion(true, nil) // Authorized (true), no error
71+
} else {
72+
completion(false, error) // Not authorized (false), with error
73+
}
74+
}
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)