Skip to content

Commit b122a2b

Browse files
committed
feat: add access status getter for camera/mic
1 parent 0c5a821 commit b122a2b

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ This native Node.js module allows you to manage an app's access to:
1616

1717
## `permissions.getAuthStatus(type)`
1818

19-
* `type` String - The type of system component to which you are requesting access. Can be one of 'contacts', 'full-disk-access', 'photos', 'reminders', 'camera', 'microphone', 'screen-capture', or 'calendar'.
19+
* `type` String - The type of system component to which you are requesting access. Can be one of 'contacts', 'full-disk-access', 'photos', 'reminders', 'camera', 'microphone', or 'calendar'.
2020

2121
Returns `String` - Can be one of 'not determined', 'denied', 'authorized', or 'restricted'.
2222

index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
const permissions = require('bindings')('permissions.node')
22

33
function getAuthStatus(type) {
4-
const validTypes = ['contacts', 'calendar', 'reminders', 'full-disk-access']
4+
const validTypes = [
5+
'contacts',
6+
'calendar',
7+
'reminders',
8+
'full-disk-access',
9+
'camera',
10+
'microphone'
11+
]
12+
513
if (!validTypes.includes(type)) {
614
throw new TypeError(`${type} is not a valid type`)
715
}

permissions.mm

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
std::string ContactAuthStatus() {
3131
std::string auth_status = "not determined";
3232

33-
CNEntityType entityType = CNEntityTypeContacts;
34-
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:entityType];
33+
CNEntityType entity_type = CNEntityTypeContacts;
34+
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:entity_type];
3535

3636
if (status == CNAuthorizationStatusAuthorized)
3737
auth_status = "authorized";
@@ -44,11 +44,11 @@
4444
}
4545

4646
// Returns a status indicating whether or not the user has authorized Calendar/Reminders access
47-
std::string EventAuthStatus(std::string type) {
47+
std::string EventAuthStatus(const std::string& type) {
4848
std::string auth_status = "not determined";
4949

50-
EKEntityType entityType = (type == "calendar") ? EKEntityTypeEvent : EKEntityTypeReminder;
51-
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:entityType];
50+
EKEntityType entity_type = (type == "calendar") ? EKEntityTypeEvent : EKEntityTypeReminder;
51+
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:entity_type];
5252

5353
if (status == EKAuthorizationStatusAuthorized)
5454
auth_status = "authorized";
@@ -60,6 +60,7 @@
6060
return auth_status;
6161
}
6262

63+
// Returns a status indicating whether or not the user has Full Disk Access
6364
std::string FDAAuthStatus() {
6465
std::string auth_status = "not determined";
6566
NSString *path;
@@ -83,6 +84,27 @@
8384
return auth_status;
8485
}
8586

87+
// Returns a status indicating whether or not the user has authorized Camera/Microphone access
88+
std::string MediaAuthStatus(const std::string& type) {
89+
std::string auth_status = "not determined";
90+
91+
if (@available(macOS 10.14, *)) {
92+
AVMediaType media_type = (type == "microphone") ? AVMediaTypeAudio : AVMediaTypeVideo;
93+
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:media_type];
94+
95+
if (status == AVAuthorizationStatusAuthorized)
96+
auth_status = "authorized";
97+
else if (status == AVAuthorizationStatusDenied)
98+
auth_status = "denied";
99+
else if (status == AVAuthorizationStatusRestricted)
100+
auth_status = "restricted";
101+
} else {
102+
auth_status = "authorized";
103+
}
104+
105+
return auth_status;
106+
}
107+
86108
/***** EXPORTED FUNCTIONS *****/
87109

88110
// Returns the user's access consent status as a string
@@ -99,6 +121,10 @@
99121
auth_status = EventAuthStatus("reminders");
100122
} else if (type == "full-disk-access") {
101123
auth_status = FDAAuthStatus();
124+
} else if (type == "microphone") {
125+
auth_status = MediaAuthStatus("microphone");
126+
} else if (type == "camera") {
127+
auth_status = MediaAuthStatus("camera");
102128
}
103129

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

test/module.spec.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ describe('node-mac-permissions', () => {
1212
})
1313

1414
it('should return a string', () => {
15-
const types = ['contacts', 'calendar', 'reminders', 'full-disk-access']
15+
const types = [
16+
'contacts',
17+
'calendar',
18+
'reminders',
19+
'full-disk-access',
20+
'camera',
21+
'microphone'
22+
]
23+
1624
const statuses = ['not determined', 'denied', 'authorized', 'restricted']
1725
for (const type of types) {
1826
const status = getAuthStatus(type)

0 commit comments

Comments
 (0)