@umutcansu/react-native-pinvault 0.0.0-stage → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE +21 -0
  3. package/README.md +386 -2
  4. package/RNPinVault.podspec +43 -0
  5. package/android/build.gradle +68 -0
  6. package/android/consumer-rules.pro +25 -0
  7. package/android/src/main/AndroidManifest.xml +16 -0
  8. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/ConfigParser.kt +300 -0
  9. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/JsEnvironmentGuard.kt +53 -0
  10. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/NativeSecurity.kt +239 -0
  11. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/PinVaultModule.kt +410 -0
  12. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/PinVaultNetworking.kt +296 -0
  13. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/PinVaultPackage.kt +25 -0
  14. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/PinnedFetch.kt +131 -0
  15. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/ResultMapper.kt +188 -0
  16. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/StrictJson.kt +225 -0
  17. package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/VaultTokenStore.kt +63 -0
  18. package/ios/Core/ConfigParser.swift +276 -0
  19. package/ios/Core/JSEnvironmentGuard.swift +129 -0
  20. package/ios/Core/NativeSecurity.swift +197 -0
  21. package/ios/Core/PinnedFetch.swift +119 -0
  22. package/ios/Core/ReactNetworking.swift +172 -0
  23. package/ios/Core/ResultMapper.swift +163 -0
  24. package/ios/Core/StrictJSON.swift +214 -0
  25. package/ios/Core/VaultTokenStore.swift +66 -0
  26. package/ios/PinVaultBridge.swift +412 -0
  27. package/ios/PinVaultReactNetworking.swift +47 -0
  28. package/ios/RNPinVault.h +7 -0
  29. package/ios/RNPinVault.mm +293 -0
  30. package/ios/RNPinVaultURLRequestHandler.mm +92 -0
  31. package/lib/module/NativePinVault.js +13 -0
  32. package/lib/module/NativePinVault.js.map +1 -0
  33. package/lib/module/index.js +312 -0
  34. package/lib/module/index.js.map +1 -0
  35. package/lib/module/package.json +1 -0
  36. package/lib/module/types.js +2 -0
  37. package/lib/module/types.js.map +1 -0
  38. package/lib/typescript/package.json +1 -0
  39. package/lib/typescript/src/NativePinVault.d.ts +50 -0
  40. package/lib/typescript/src/NativePinVault.d.ts.map +1 -0
  41. package/lib/typescript/src/index.d.ts +150 -0
  42. package/lib/typescript/src/index.d.ts.map +1 -0
  43. package/lib/typescript/src/types.d.ts +346 -0
  44. package/lib/typescript/src/types.d.ts.map +1 -0
  45. package/package.json +128 -4
  46. package/src/NativePinVault.ts +72 -0
  47. package/src/index.ts +385 -0
  48. package/src/types.ts +351 -0
@@ -0,0 +1,293 @@
1
+ #import "RNPinVault.h"
2
+
3
+ #import <objc/message.h>
4
+ #import <React/RCTBridgeModule.h>
5
+
6
+ #if __has_include(<RNPinVault/RNPinVault-Swift.h>)
7
+ #import <RNPinVault/RNPinVault-Swift.h>
8
+ #else
9
+ #import "RNPinVault-Swift.h"
10
+ #endif
11
+
12
+ @implementation RNPinVault {
13
+ RNPinVaultBridge *_bridge;
14
+ }
15
+
16
+ @synthesize moduleRegistry = _moduleRegistry;
17
+
18
+ + (NSString *)moduleName
19
+ {
20
+ return @"RNPinVault";
21
+ }
22
+
23
+ + (BOOL)requiresMainQueueSetup
24
+ {
25
+ return NO;
26
+ }
27
+
28
+ - (instancetype)init
29
+ {
30
+ if (self = [super init]) {
31
+ _bridge = [RNPinVaultBridge new];
32
+ __weak RNPinVault *weakSelf = self;
33
+ _bridge.emitConnectionEvent = ^(NSDictionary<NSString *, id> *event) {
34
+ [weakSelf emitOnConnectionEvent:event];
35
+ };
36
+ _bridge.emitGuardRequest = ^(NSDictionary<NSString *, id> *request) {
37
+ [weakSelf emitOnGuardRequest:request];
38
+ };
39
+ // Which RCTURLRequestHandler RCTNetworking picks for an https request
40
+ // (its private handlerForRequest:, the method it sends every request through).
41
+ _bridge.reactNetworkingIsPinned = ^NSNumber *_Nullable {
42
+ RNPinVault *strongSelf = weakSelf;
43
+ RCTModuleRegistry *registry = strongSelf ? strongSelf->_moduleRegistry : nil;
44
+ id networking = [registry moduleForName:"Networking"];
45
+ SEL selector = NSSelectorFromString(@"handlerForRequest:");
46
+ Class ours = NSClassFromString(@"RNPinVaultURLRequestHandler");
47
+ if (networking == nil || ours == nil || ![networking respondsToSelector:selector]) {
48
+ return nil;
49
+ }
50
+ NSURLRequest *probe = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://pinvault.invalid/"]];
51
+ id handler = ((id(*)(id, SEL, NSURLRequest *))objc_msgSend)(networking, selector, probe);
52
+ return @([handler isKindOfClass:ours]);
53
+ };
54
+ }
55
+ return self;
56
+ }
57
+
58
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
59
+ (const facebook::react::ObjCTurboModule::InitParams &)params
60
+ {
61
+ return std::make_shared<facebook::react::NativePinVaultSpecJSI>(params);
62
+ }
63
+
64
+ // Swift answers with plain blocks; the JS side reads code, message and userInfo.
65
+ static void (^Resolver(RCTPromiseResolveBlock resolve))(id)
66
+ {
67
+ return ^(id value) { resolve(value); };
68
+ }
69
+
70
+ static void (^Rejecter(RCTPromiseRejectBlock reject))(NSString *, NSString *, NSDictionary<NSString *, id> *)
71
+ {
72
+ return ^(NSString *code, NSString *message, NSDictionary<NSString *, id> *info) {
73
+ NSError *error = info ? [NSError errorWithDomain:@"PinVault" code:0 userInfo:info] : nil;
74
+ reject(code, message, error);
75
+ };
76
+ }
77
+
78
+ #define R Resolver(resolve)
79
+ #define J Rejecter(reject)
80
+
81
+ - (void)start:(NSString *)configJson resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
82
+ {
83
+ [_bridge start:configJson resolve:R reject:J];
84
+ }
85
+
86
+ - (void)updateNow:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
87
+ {
88
+ [_bridge updateNowWithResolve:R reject:J];
89
+ }
90
+
91
+ - (void)currentVersion:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
92
+ {
93
+ [_bridge currentVersionWithResolve:R reject:J];
94
+ }
95
+
96
+ - (void)hostPinVersions:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
97
+ {
98
+ [_bridge hostPinVersionsWithResolve:R reject:J];
99
+ }
100
+
101
+ - (void)pinsForHost:(NSString *)hostname resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
102
+ {
103
+ [_bridge pinsForHost:hostname resolve:R reject:J];
104
+ }
105
+
106
+ - (void)signingStatus:(NSString *)configApiId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
107
+ {
108
+ [_bridge signingStatus:configApiId resolve:R reject:J];
109
+ }
110
+
111
+ - (void)isForceUpdate:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
112
+ {
113
+ [_bridge isForceUpdateWithResolve:R reject:J];
114
+ }
115
+
116
+ - (void)reset:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
117
+ {
118
+ [_bridge resetWithResolve:R reject:J];
119
+ }
120
+
121
+ - (void)schedulePeriodicUpdates:(NSNumber *)intervalHours
122
+ resolve:(RCTPromiseResolveBlock)resolve
123
+ reject:(RCTPromiseRejectBlock)reject
124
+ {
125
+ [_bridge schedulePeriodicUpdates:intervalHours resolve:R reject:J];
126
+ }
127
+
128
+ - (void)cancelPeriodicUpdates:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
129
+ {
130
+ [_bridge cancelPeriodicUpdatesWithResolve:R reject:J];
131
+ }
132
+
133
+ - (void)enableDebugLogging:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
134
+ {
135
+ [_bridge enableDebugLoggingWithResolve:R reject:J];
136
+ }
137
+
138
+ - (void)fetch:(NSString *)requestJson resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
139
+ {
140
+ [_bridge fetch:requestJson resolve:R reject:J];
141
+ }
142
+
143
+ - (void)deviceId:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
144
+ {
145
+ [_bridge deviceIdWithResolve:R reject:J];
146
+ }
147
+
148
+ - (void)enrollForResult:(NSString *)token
149
+ label:(NSString *)label
150
+ resolve:(RCTPromiseResolveBlock)resolve
151
+ reject:(RCTPromiseRejectBlock)reject
152
+ {
153
+ [_bridge enrollForResult:token label:label resolve:R reject:J];
154
+ }
155
+
156
+ - (void)autoEnrollForResult:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
157
+ {
158
+ [_bridge autoEnrollForResultWithResolve:R reject:J];
159
+ }
160
+
161
+ - (void)checkPendingEnrollment:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
162
+ {
163
+ [_bridge checkPendingEnrollmentWithResolve:R reject:J];
164
+ }
165
+
166
+ - (void)isEnrolled:(NSString *)label resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
167
+ {
168
+ [_bridge isEnrolled:label resolve:R reject:J];
169
+ }
170
+
171
+ - (void)isEnrollmentPending:(NSString *)label resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
172
+ {
173
+ [_bridge isEnrollmentPending:label resolve:R reject:J];
174
+ }
175
+
176
+ - (void)enrollmentVerificationCode:(NSString *)label
177
+ resolve:(RCTPromiseResolveBlock)resolve
178
+ reject:(RCTPromiseRejectBlock)reject
179
+ {
180
+ [_bridge enrollmentVerificationCode:label resolve:R reject:J];
181
+ }
182
+
183
+ - (void)enrolledClientCN:(NSString *)label resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
184
+ {
185
+ [_bridge enrolledClientCN:label resolve:R reject:J];
186
+ }
187
+
188
+ - (void)enrolledClientNotAfter:(NSString *)label resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
189
+ {
190
+ [_bridge enrolledClientNotAfter:label resolve:R reject:J];
191
+ }
192
+
193
+ - (void)unenroll:(NSString *)label
194
+ wipeVaultFiles:(BOOL)wipeVaultFiles
195
+ resolve:(RCTPromiseResolveBlock)resolve
196
+ reject:(RCTPromiseRejectBlock)reject
197
+ {
198
+ [_bridge unenroll:label wipeVaultFiles:wipeVaultFiles resolve:R reject:J];
199
+ }
200
+
201
+ - (void)identityKeySecurityLevel:(NSString *)label resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
202
+ {
203
+ [_bridge identityKeySecurityLevel:label resolve:R reject:J];
204
+ }
205
+
206
+ - (void)setVaultToken:(NSString *)key
207
+ token:(NSString *)token
208
+ resolve:(RCTPromiseResolveBlock)resolve
209
+ reject:(RCTPromiseRejectBlock)reject
210
+ {
211
+ [_bridge setVaultToken:key token:token resolve:R reject:J];
212
+ }
213
+
214
+ - (void)clearVaultTokens:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
215
+ {
216
+ [_bridge clearVaultTokensWithResolve:R reject:J];
217
+ }
218
+
219
+ - (void)fetchFile:(NSString *)key
220
+ token:(NSString *)token
221
+ resolve:(RCTPromiseResolveBlock)resolve
222
+ reject:(RCTPromiseRejectBlock)reject
223
+ {
224
+ [_bridge fetchFile:key token:token resolve:R reject:J];
225
+ }
226
+
227
+ - (void)loadFile:(NSString *)key
228
+ encoding:(NSString *)encoding
229
+ resolve:(RCTPromiseResolveBlock)resolve
230
+ reject:(RCTPromiseRejectBlock)reject
231
+ {
232
+ [_bridge loadFile:key encoding:encoding resolve:R reject:J];
233
+ }
234
+
235
+ - (void)fileStatus:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
236
+ {
237
+ [_bridge fileStatus:key resolve:R reject:J];
238
+ }
239
+
240
+ - (void)unlockFile:(NSString *)key
241
+ promptJson:(NSString *)promptJson
242
+ resolve:(RCTPromiseResolveBlock)resolve
243
+ reject:(RCTPromiseRejectBlock)reject
244
+ {
245
+ [_bridge unlockFile:key prompt:promptJson resolve:R reject:J];
246
+ }
247
+
248
+ - (void)isFileLocked:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
249
+ {
250
+ [_bridge isFileLocked:key resolve:R reject:J];
251
+ }
252
+
253
+ - (void)hasFile:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
254
+ {
255
+ [_bridge hasFile:key resolve:R reject:J];
256
+ }
257
+
258
+ - (void)fileVersion:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
259
+ {
260
+ [_bridge fileVersion:key resolve:R reject:J];
261
+ }
262
+
263
+ - (void)clearFile:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
264
+ {
265
+ [_bridge clearFile:key resolve:R reject:J];
266
+ }
267
+
268
+ - (void)syncAllFiles:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
269
+ {
270
+ [_bridge syncAllFilesWithResolve:R reject:J];
271
+ }
272
+
273
+ - (void)attestNow:(NSString *)configApiId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
274
+ {
275
+ [_bridge attestNow:configApiId resolve:R reject:J];
276
+ }
277
+
278
+ - (void)fetchAttestationToken:(NSString *)host resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
279
+ {
280
+ [_bridge fetchAttestationToken:host resolve:R reject:J];
281
+ }
282
+
283
+ - (void)attestationStatus:(NSString *)configApiId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
284
+ {
285
+ [_bridge attestationStatus:configApiId resolve:R reject:J];
286
+ }
287
+
288
+ - (void)answerGuard:(NSString *)requestId allowed:(BOOL)allowed
289
+ {
290
+ [_bridge answerGuard:requestId allowed:allowed];
291
+ }
292
+
293
+ @end
@@ -0,0 +1,92 @@
1
+ // RNPinVaultURLRequestHandler — React Native's https traffic (fetch,
2
+ // XMLHttpRequest, <Image>) through PinVault's pinned session on iOS.
3
+ //
4
+ // RCTNetworking asks every RCTURLRequestHandler whether it can handle a request
5
+ // and picks the one with the highest handlerPriority (RCTNetworking.mm,
6
+ // handlerForRequest:). RCTHTTPRequestHandler has none (0); this one answers
7
+ // YES for https with priority 10, so RN's own handler only sees plain http
8
+ // (which ATS refuses unless the app allows it). In the New Architecture the
9
+ // handler list comes from codegen: package.json → codegenConfig.ios.
10
+ // modulesConformingToProtocol.RCTURLRequestHandler names this module, and
11
+ // RCTAppSetupUtils adds it to RCTNetworking's handlers.
12
+ //
13
+ // The work is Swift (PinVaultReactNetworking.swift → Core/ReactNetworking.swift).
14
+ #import <Foundation/Foundation.h>
15
+ #import <React/RCTBridgeModule.h>
16
+ #import <React/RCTURLRequestDelegate.h>
17
+ #import <React/RCTURLRequestHandler.h>
18
+ #import <ReactCommon/RCTTurboModule.h>
19
+
20
+ #if __has_include(<RNPinVault/RNPinVault-Swift.h>)
21
+ #import <RNPinVault/RNPinVault-Swift.h>
22
+ #else
23
+ #import "RNPinVault-Swift.h"
24
+ #endif
25
+
26
+ @interface RNPinVaultURLRequestHandler : NSObject <RCTURLRequestHandler, RCTTurboModule>
27
+ @end
28
+
29
+ @implementation RNPinVaultURLRequestHandler
30
+
31
+ RCT_EXPORT_MODULE()
32
+
33
+ + (BOOL)requiresMainQueueSetup
34
+ {
35
+ return NO;
36
+ }
37
+
38
+ // Native only: JS never requires this module.
39
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
40
+ (const facebook::react::ObjCTurboModule::InitParams &)params
41
+ {
42
+ return nullptr;
43
+ }
44
+
45
+ - (BOOL)canHandleRequest:(NSURLRequest *)request
46
+ {
47
+ return [RNPinVaultReactNetworking canHandle:request];
48
+ }
49
+
50
+ - (float)handlerPriority
51
+ {
52
+ return 10;
53
+ }
54
+
55
+ - (id)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate
56
+ {
57
+ // RN does not retain the delegate; its RCTNetworkTask keeps itself alive until done.
58
+ __weak id<RCTURLRequestDelegate> weakDelegate = delegate;
59
+ __block __weak RNPinVaultReactNetworkingTask *weakToken = nil;
60
+ RNPinVaultReactNetworkingTask *token = [RNPinVaultReactNetworking prepare:request
61
+ didSendData:^(int64_t bytes) {
62
+ RNPinVaultReactNetworkingTask *t = weakToken;
63
+ if (t) [weakDelegate URLRequest:t didSendDataWithProgress:bytes];
64
+ }
65
+ didReceiveResponse:^(NSURLResponse *response) {
66
+ RNPinVaultReactNetworkingTask *t = weakToken;
67
+ if (t) [weakDelegate URLRequest:t didReceiveResponse:response];
68
+ }
69
+ didReceiveData:^(NSData *data) {
70
+ RNPinVaultReactNetworkingTask *t = weakToken;
71
+ if (t) [weakDelegate URLRequest:t didReceiveData:data];
72
+ }
73
+ didComplete:^(NSError *error) {
74
+ RNPinVaultReactNetworkingTask *t = weakToken;
75
+ if (t) [weakDelegate URLRequest:t didCompleteWithError:error];
76
+ }];
77
+ weakToken = token;
78
+ // The token is returned before any callback can run (RN's rule): resume starts the request.
79
+ dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
80
+ [token resume];
81
+ });
82
+ return token;
83
+ }
84
+
85
+ - (void)cancelRequest:(id)requestToken
86
+ {
87
+ if ([requestToken isKindOfClass:[RNPinVaultReactNetworkingTask class]]) {
88
+ [(RNPinVaultReactNetworkingTask *)requestToken cancel];
89
+ }
90
+ }
91
+
92
+ @end
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ // TurboModule codegen spec (New Architecture only).
4
+ //
5
+ // The native side is a thin bridge over the PinVault libraries
6
+ // (Android: io.github.umutcansu:pinvault, iOS: the PinVault Swift package).
7
+ // Every structured input crosses as a JSON string and is parsed STRICTLY on the
8
+ // native side (unknown keys and wrong types are refused, sizes are bounded);
9
+ // results come back as plain objects that keep the native names. Use the typed
10
+ // wrappers in `index.ts`, not this module directly.
11
+ import { TurboModuleRegistry } from 'react-native';
12
+ export default TurboModuleRegistry.getEnforcing('RNPinVault');
13
+ //# sourceMappingURL=NativePinVault.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativePinVault.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,mBAAmB,QAA6C,cAAc;AA+DvF,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}