Skip to content

Commit

Permalink
feat: add askForInputMonitoringAccess()
Browse files Browse the repository at this point in the history
  • Loading branch information
codebytere committed Apr 25, 2022
1 parent 188b6f2 commit 1d49735
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,28 @@ askForCameraAccess().then(status => {
})
```

## `permissions.askForInputMonitoringAccess()`

Returns `Promise<String>` - Current permission status; can be `authorized` or `denied`.

Checks the authorization status for input monitoring access. If the status check returns:

* `not determined` - A dialog will be displayed directing the user to the `Security & Privacy` System Preferences window , where the user can approve your app to monitor keyboard events in the background. The Promise is resolved as `denied`.
* `denied` - The `Security & Privacy` System Preferences window is opened with the Input Monitoring privacy key highlighted. On open of the `Security & Privacy` window, the Promise is resolved as `denied`.

**Note:**

- `status` will be resolved back as `authorized` prior to macOS 10.15, as the underlying API was not introduced until that version.

Example:
```js
const { askForInputMonitoringAccess } = require('node-mac-permissions')

askForInputMonitoringAccess().then(status => {
console.log(`Access to Input Monitoring is ${status}`)
})
```

## `permissions.askForMicrophoneAccess()`

Returns `Promise<String>` - Current permission status; can be `authorized`, `denied`, or `restricted`.
Expand Down
7 changes: 4 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// Type definitions for node-mac-permissions
// Project: node-mac-permissions

export function askForAccessibilityAccess(): undefined
export function askForCalendarAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForCameraAccess(): Promise<PermissionType>
export function askForContactsAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForFoldersAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForFullDiskAccess(): undefined
export function askForRemindersAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForCameraAccess(): Promise<PermissionType>
export function askForInputMonitoringAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForMicrophoneAccess(): Promise<PermissionType>
export function askForPhotosAccess(): Promise<PermissionType>
export function askForRemindersAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForSpeechRecognitionAccess(): Promise<Omit<PermissionType, 'restricted'>>
export function askForScreenCaptureAccess(): undefined
export function askForAccessibilityAccess(): undefined
export function getAuthStatus(authType: AuthType): PermissionType | 'not determined'

export type AuthType =
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module.exports = {
askForContactsAccess: permissions.askForContactsAccess,
askForFoldersAccess,
askForFullDiskAccess: permissions.askForFullDiskAccess,
askForInputMonitoringAccess: permissions.askForInputMonitoringAccess,
askForRemindersAccess: permissions.askForRemindersAccess,
askForMicrophoneAccess: permissions.askForMicrophoneAccess,
askForMusicLibraryAccess: permissions.askForMusicLibraryAccess,
Expand Down
31 changes: 31 additions & 0 deletions permissions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,35 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
return deferred.Promise();
}

// Request Input Monitoring access.
Napi::Promise AskForInputMonitoringAccess(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);

if (@available(macOS 10.16, *)) {
std::string auth_status = InputMonitoringAuthStatus();

if (auth_status == kNotDetermined) {
IOHIDRequestAccess(kIOHIDRequestTypeListenEvent);
deferred.Resolve(Napi::String::New(env, kDenied));
} else if (auth_status == kDenied) {
NSWorkspace *workspace = [[NSWorkspace alloc] init];
NSString *pref_string = @"x-apple.systempreferences:com.apple.preference."
@"security?Privacy_ListenEvent";

[workspace openURL:[NSURL URLWithString:pref_string]];

deferred.Resolve(Napi::String::New(env, kDenied));
} else {
deferred.Resolve(Napi::String::New(env, auth_status));
}
} else {
deferred.Resolve(Napi::String::New(env, kAuthorized));
}

return deferred.Promise();
}

// Request Apple Music Library access.
Napi::Promise AskForMusicLibraryAccess(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Expand Down Expand Up @@ -790,6 +819,8 @@ void AskForAccessibilityAccess(const Napi::CallbackInfo &info) {
Napi::Function::New(env, AskForScreenCaptureAccess));
exports.Set(Napi::String::New(env, "askForAccessibilityAccess"),
Napi::Function::New(env, AskForAccessibilityAccess));
exports.Set(Napi::String::New(env, "askForInputMonitoringAccess"),
Napi::Function::New(env, AskForInputMonitoringAccess));

return exports;
}
Expand Down

0 comments on commit 1d49735

Please sign in to comment.