Skip to content

Commit 188b6f2

Browse files
committed
feat: add input-monitoring auth status
Closes #33
1 parent f419d22 commit 188b6f2

File tree

6 files changed

+65
-37
lines changed

6 files changed

+65
-37
lines changed

README.md

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ $ npm i node-mac-permissions
99

1010
This native Node.js module allows you to manage an app's access to:
1111

12-
* Contacts
13-
* Full Disk Access
12+
* Accessibility
1413
* Calendar
15-
* Reminders
1614
* Camera
15+
* Contacts
16+
* Full Disk Access
17+
* Input Monitoring
18+
* Location
1719
* Microphone
1820
* Photos
19-
* Accessibility
20-
* Location
21+
* Protected Folders
22+
* Reminders
2123
* Screen Capture
2224
* Speech Recognition
23-
* Protected Folders
2425

2526
If you need to ask for permissions, your app must be allowed to ask for permission :
2627

@@ -33,7 +34,7 @@ If you're using macOS 12.3 or newer, you'll need to ensure you have Python insta
3334

3435
## `permissions.getAuthStatus(type)`
3536

36-
* `type` String - The type of system component to which you are requesting access. Can be one of `accessibility`, `bluetooth`, `calendar`, `camera`, `contacts`, `full-disk-access`, `speech-recognition`, `location`, `microphone`, `photos`, `screen`, or `reminders`.
37+
* `type` String - The type of system component to which you are requesting access. Can be one of `accessibility`, `bluetooth`, `calendar`, `camera`, `contacts`, `full-disk-access`, `input-monitoring`, `location`, `microphone`,`photos`, `reminders`, `screen`, or `speech-recognition`.
3738

3839
Returns `String` - Can be one of `not determined`, `denied`, `authorized`, or `restricted`.
3940

@@ -46,13 +47,14 @@ Return Value Descriptions:
4647
* `authorized` - The application is authorized to access `type` data.
4748

4849
**Notes:**
49-
* Access to `contacts` will always return a status of `authorized` prior to macOS 10.11, as the underlying API was not introduced until that version.
50+
* Access to `bluetooth` will always return a status of `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.
5051
* Access to `camera` and `microphone` will always return a status of `authorized` prior to macOS 10.14, as the underlying API was not introduced until that version.
51-
* Access to `screen` will always return a status of `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.
52+
* Access to `contacts` will always return a status of `authorized` prior to macOS 10.11, as the underlying API was not introduced until that version.
53+
* Access to `input-monitoring` will always return a status of `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.
54+
* Access to `music-library` will always return a status of `authorized` prior to macOS 11.0, as the underlying API was not introduced until that version.
5255
* Access to `photos` will always return a status of `authorized` prior to macOS 10.13, as the underlying API was not introduced until that version.
56+
* Access to `screen` will always return a status of `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.
5357
* Access to `speech-recognition` will always return a status of `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.
54-
* Access to `bluetooth` will always return a status of `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.
55-
* Access to `music-library` will always return a status of `authorized` prior to macOS 11.0, as the underlying API was not introduced until that version.
5658

5759
Example:
5860
```js
@@ -62,14 +64,15 @@ const types = [
6264
'calendar',
6365
'camera',
6466
'contacts',
65-
'reminders',
6667
'full-disk-access',
68+
'input-monitoring',
6769
'location',
6870
'microphone',
6971
'music-library',
7072
'photos',
73+
'reminders',
74+
'speech-recognition',
7175
'screen',
72-
'speech-recognition'
7376
]
7477

7578
for (const type of types) {

binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"-framework CoreGraphics",
3131
"-framework Contacts",
3232
"-framework EventKit",
33+
"-framework IOKit",
3334
"-framework Photos",
3435
"-framework Speech",
3536
"-framework Storekit"

index.d.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@ export function askForAccessibilityAccess(): undefined
1515
export function getAuthStatus(authType: AuthType): PermissionType | 'not determined'
1616

1717
export type AuthType =
18+
| 'accessibility'
1819
| 'bluetooth'
19-
| 'contacts'
2020
| 'calendar'
21-
| 'reminders'
22-
| 'full-disk-access'
2321
| 'camera'
24-
| 'photos'
25-
| 'speech-recognition'
22+
| 'contacts'
23+
| 'full-disk-access'
24+
| 'input-monitoring'
25+
| 'location'
2626
| 'microphone'
2727
| 'music-library'
28-
| 'accessibility'
29-
| 'location'
28+
| 'photos'
29+
| 'reminders'
30+
| 'speech-recognition'
3031
| 'screen'
3132

3233
export type PermissionType = 'authorized' | 'denied' | 'restricted'

index.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@ const permissions = require('bindings')('permissions.node')
22

33
function getAuthStatus(type) {
44
const validTypes = [
5-
'contacts',
5+
'accessibility',
6+
'bluetooth',
67
'calendar',
7-
'reminders',
8-
'full-disk-access',
98
'camera',
10-
'photos',
11-
'speech-recognition',
9+
'contacts',
10+
'full-disk-access',
11+
'input-monitoring',
12+
'location',
1213
'microphone',
1314
'music-library',
14-
'accessibility',
15-
'location',
15+
'photos',
16+
'reminders',
17+
'speech-recognition',
1618
'screen',
17-
'bluetooth',
1819
]
1920

2021
if (!validTypes.includes(type)) {
@@ -35,17 +36,17 @@ function askForFoldersAccess(folder) {
3536
}
3637

3738
module.exports = {
39+
askForAccessibilityAccess: permissions.askForAccessibilityAccess,
3840
askForCalendarAccess: permissions.askForCalendarAccess,
41+
askForCameraAccess: permissions.askForCameraAccess,
3942
askForContactsAccess: permissions.askForContactsAccess,
4043
askForFoldersAccess,
4144
askForFullDiskAccess: permissions.askForFullDiskAccess,
4245
askForRemindersAccess: permissions.askForRemindersAccess,
43-
askForCameraAccess: permissions.askForCameraAccess,
4446
askForMicrophoneAccess: permissions.askForMicrophoneAccess,
4547
askForMusicLibraryAccess: permissions.askForMusicLibraryAccess,
4648
askForPhotosAccess: permissions.askForPhotosAccess,
4749
askForSpeechRecognitionAccess: permissions.askForSpeechRecognitionAccess,
4850
askForScreenCaptureAccess: permissions.askForScreenCaptureAccess,
49-
askForAccessibilityAccess: permissions.askForAccessibilityAccess,
5051
getAuthStatus,
5152
}

permissions.mm

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#import <CoreLocation/CoreLocation.h>
1010
#import <EventKit/EventKit.h>
1111
#import <Foundation/Foundation.h>
12+
#import <IOKit/hidsystem/IOHIDLib.h>
1213
#import <Photos/Photos.h>
1314
#import <Speech/Speech.h>
1415
#import <Storekit/Storekit.h>
@@ -136,6 +137,23 @@ bool HasOpenSystemPreferencesDialog() {
136137
return kAuthorized;
137138
}
138139

140+
// Returns a status indicating whether the user has authorized
141+
// input monitoring access.
142+
std::string InputMonitoringAuthStatus() {
143+
if (@available(macOS 10.15, *)) {
144+
switch (IOHIDCheckAccess(kIOHIDRequestTypeListenEvent)) {
145+
case kIOHIDAccessTypeGranted:
146+
return kAuthorized;
147+
case kIOHIDAccessTypeDenied:
148+
return kDenied;
149+
default:
150+
return kNotDetermined;
151+
}
152+
}
153+
154+
return kAuthorized;
155+
}
156+
139157
// Returns a status indicating whether the user has authorized Apple Music
140158
// Library access.
141159
std::string MusicLibraryAuthStatus() {
@@ -361,6 +379,8 @@ bool HasOpenSystemPreferencesDialog() {
361379
auth_status = BluetoothAuthStatus();
362380
} else if (type == "music-library") {
363381
auth_status = MusicLibraryAuthStatus();
382+
} else if (type == "input-monitoring") {
383+
auth_status = InputMonitoringAuthStatus();
364384
}
365385

366386
return Napi::Value::From(env, auth_status);

test/module.spec.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ describe('node-mac-permissions', () => {
1111

1212
it('should return a string', () => {
1313
const types = [
14-
'contacts',
14+
'accessibility',
15+
'bluetooth',
1516
'calendar',
16-
'reminders',
17-
'full-disk-access',
1817
'camera',
19-
'photos',
20-
'speech-recognition',
18+
'contacts',
19+
'full-disk-access',
20+
'input-monitoring',
21+
'location',
2122
'microphone',
2223
'music-library',
23-
'accessibility',
24-
'location',
24+
'photos',
25+
'reminders',
26+
'speech-recognition',
2527
'screen',
2628
]
2729

0 commit comments

Comments
 (0)