1// Copyright 2019-present 650 Industries. All rights reserved. 2 3#import <ExpoModulesCore/EXPermissionsService.h> 4 5#import "EXPermissionsManager.h" 6#import "EXEnvironment.h" 7 8NSString * const EXPermissionsKey = @"ExpoPermissions"; 9 10@interface EXPermissionsManager () 11 12@property (nonatomic, strong) NSMutableDictionary<NSString *, NSDictionary *> *permissionsCache; 13 14@end 15 16@implementation EXPermissionsManager 17 18- (instancetype)init 19{ 20 if (self = [super init]) { 21 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 22 NSDictionary *expoPermissions = [userDefaults dictionaryForKey:EXPermissionsKey]; 23 _permissionsCache = expoPermissions ? [[NSMutableDictionary alloc] initWithDictionary:expoPermissions] : [NSMutableDictionary new]; 24 } 25 return self; 26} 27 28EX_REGISTER_SINGLETON_MODULE(Permissions) 29 30- (EXPermissionStatus)getPermission:(NSString *)permissionType forExperience:(NSString *)scopeKey 31{ 32 permissionType = [EXPermissionsManager mapPermissionType:permissionType]; 33 34 NSString *scopeKeyKey = [EXPermissionsManager escapedResourceName:scopeKey]; 35 NSDictionary *experiencePermissions = _permissionsCache[scopeKeyKey]; 36 if (!experiencePermissions) { 37 return EXPermissionStatusUndetermined; 38 } 39 40 NSDictionary *permissionData = experiencePermissions[permissionType]; 41 if (!permissionData) { 42 return EXPermissionStatusUndetermined; 43 } 44 45 if ([permissionData[@"status"] isEqualToString:[EXPermissionsService permissionStringForStatus:EXPermissionStatusGranted]]) { 46 return EXPermissionStatusGranted; 47 } 48 49 return EXPermissionStatusDenied; 50} 51 52- (BOOL)hasGrantedPermission:(NSString *)permission forExperience:(NSString *)scopeKey 53{ 54 if ([EXEnvironment sharedEnvironment].isDetached) { 55 return YES; 56 } 57 58 return [self getPermission:[EXPermissionsManager mapPermissionType:permission] forExperience:scopeKey] == EXPermissionStatusGranted; 59} 60 61- (BOOL)savePermission:(NSDictionary *)permission ofType:(NSString *)type forExperience:(NSString *)scopeKey 62{ 63 type = [EXPermissionsManager mapPermissionType:type]; 64 65 NSString *scopeKeyKey = [EXPermissionsManager escapedResourceName:scopeKey]; 66 NSMutableDictionary *experiencePermissions; 67 if ([_permissionsCache objectForKey:scopeKeyKey] == nil) { 68 experiencePermissions = [[NSMutableDictionary alloc] init]; 69 } else { 70 experiencePermissions = [[NSMutableDictionary alloc] initWithDictionary:_permissionsCache[scopeKeyKey]]; 71 } 72 73 experiencePermissions[type] = permission; 74 _permissionsCache[scopeKeyKey] = experiencePermissions; 75 [self synchronizeWithPermissions:_permissionsCache]; 76 return YES; 77} 78 79- (void)synchronizeWithPermissions:(NSDictionary *)permissions 80{ 81 [[NSUserDefaults standardUserDefaults] setObject:permissions forKey:EXPermissionsKey]; 82} 83 84+ (NSString *)escapedResourceName:(NSString *)name 85{ 86 NSString *charactersToEscape = @"!*'();:@&=+$,/?%#[]"; 87 NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:charactersToEscape] invertedSet]; 88 return [name stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; 89} 90 91+ (NSString *)mapPermissionType:(NSString *)type 92{ 93 if ([type isEqual:@"locationForeground"]) { 94 return @"location"; 95 } 96 97 return type; 98} 99 100@end 101