react-native-ssl-manager 1.0.1 → 1.0.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 (2) hide show
  1. package/app.plugin.js +293 -0
  2. package/package.json +2 -1
package/app.plugin.js ADDED
@@ -0,0 +1,293 @@
1
+ const {
2
+ withInfoPlist,
3
+ withDangerousMod,
4
+ withXcodeProject,
5
+ withAndroidManifest,
6
+ withMainApplication,
7
+ } = require('@expo/config-plugins');
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ /**
12
+ * Expo Config Plugin for react-native-ssl-manager
13
+ * Automatically configures SSL pinning for Expo projects
14
+ */
15
+ function withSslManager(config, options = {}) {
16
+ const {
17
+ enableAndroid = true,
18
+ enableIOS = true,
19
+ sslConfigPath = 'ssl_config.json',
20
+ } = options;
21
+
22
+ // Add Android configuration
23
+ if (enableAndroid) {
24
+ config = withAndroidSslPinning(config);
25
+ config = withAndroidMainApplication(config);
26
+ config = withAndroidAssets(config, { sslConfigPath });
27
+ }
28
+
29
+ // Add iOS configuration
30
+ if (enableIOS) {
31
+ config = withIOSSslPinning(config);
32
+ config = withIosAssets(config, { sslConfigPath });
33
+ }
34
+
35
+ return config;
36
+ }
37
+
38
+ /**
39
+ * Configure Android SSL pinning
40
+ */
41
+ function withAndroidSslPinning(config) {
42
+ return withAndroidManifest(config, (config) => {
43
+ const manifest = config.modResults;
44
+
45
+ // Add required permissions
46
+ if (!manifest.manifest['uses-permission']) {
47
+ manifest.manifest['uses-permission'] = [];
48
+ }
49
+
50
+ const permissions = Array.isArray(manifest.manifest['uses-permission'])
51
+ ? manifest.manifest['uses-permission']
52
+ : [manifest.manifest['uses-permission']];
53
+
54
+ // Add INTERNET permission if not exists
55
+ if (
56
+ !permissions.find(
57
+ (p) => p.$['android:name'] === 'android.permission.INTERNET'
58
+ )
59
+ ) {
60
+ permissions.push({
61
+ $: {
62
+ 'android:name': 'android.permission.INTERNET',
63
+ },
64
+ });
65
+ }
66
+
67
+ manifest.manifest['uses-permission'] = permissions;
68
+ return config;
69
+ });
70
+ }
71
+
72
+ /**
73
+ * Configure Android MainApplication - No longer needed as autolinking handles package registration
74
+ * Keeping function for backward compatibility but removing auto-registration to avoid duplicates
75
+ */
76
+ function withAndroidMainApplication(config) {
77
+ // No longer auto-register package - let autolinking handle it
78
+ // This prevents duplicate module registration errors
79
+ return config;
80
+ }
81
+
82
+ /**
83
+ * Auto-copy SSL config to Android assets
84
+ */
85
+ function withAndroidAssets(config, options) {
86
+ return withDangerousMod(config, [
87
+ 'android',
88
+ async (config) => {
89
+ const { sslConfigPath = 'ssl_config.json' } = options;
90
+
91
+ try {
92
+ const projectRoot = config.modRequest.projectRoot;
93
+ const sourceConfigPath = path.resolve(projectRoot, sslConfigPath);
94
+
95
+ if (fs.existsSync(sourceConfigPath)) {
96
+ const assetsDir = path.join(
97
+ config.modRequest.platformProjectRoot,
98
+ 'app/src/main/assets'
99
+ );
100
+
101
+ // Create assets directory if it doesn't exist
102
+ if (!fs.existsSync(assetsDir)) {
103
+ fs.mkdirSync(assetsDir, { recursive: true });
104
+ }
105
+
106
+ // Copy SSL config to assets
107
+ const targetPath = path.join(assetsDir, 'ssl_config.json');
108
+ fs.copyFileSync(sourceConfigPath, targetPath);
109
+ } else {
110
+ console.warn(`⚠️ SSL config file not found at: ${sourceConfigPath}`);
111
+ console.warn(
112
+ '💡 Place ssl_config.json in your project root for auto-setup'
113
+ );
114
+ }
115
+ } catch (error) {
116
+ console.warn('⚠️ Failed to auto-copy SSL config to assets:', error);
117
+ }
118
+
119
+ return config;
120
+ },
121
+ ]);
122
+ }
123
+
124
+ /**
125
+ * Configure iOS SSL pinning - No Info.plist modification needed
126
+ * SSL pinning is handled by SharedLogic.swift at runtime
127
+ */
128
+ function withIOSSslPinning(config) {
129
+ // No Info.plist modifications needed
130
+ // SSL pinning is initialized at runtime by SharedLogic.swift
131
+
132
+ return config;
133
+ }
134
+
135
+ /**
136
+ * Auto-copy SSL config to iOS bundle resources and add to Xcode project
137
+ */
138
+ function withIosAssets(config, options) {
139
+ // First copy the file
140
+ config = withDangerousMod(config, [
141
+ 'ios',
142
+ async (config) => {
143
+ const { sslConfigPath = 'ssl_config.json' } = options;
144
+
145
+ try {
146
+ const projectRoot = config.modRequest.projectRoot;
147
+ const sourceConfigPath = path.resolve(projectRoot, sslConfigPath);
148
+
149
+ if (fs.existsSync(sourceConfigPath)) {
150
+ // Create ios directory if it doesn't exist
151
+ const iosDir = path.join(projectRoot, 'ios');
152
+ if (!fs.existsSync(iosDir)) {
153
+ fs.mkdirSync(iosDir, { recursive: true });
154
+ }
155
+
156
+ // Copy ssl_config.json to ios directory
157
+ const targetConfigPath = path.join(iosDir, 'ssl_config.json');
158
+ fs.copyFileSync(sourceConfigPath, targetConfigPath);
159
+
160
+ // Also copy to app bundle directory for Xcode project
161
+ const appBundleDir = path.join(iosDir, config.modRequest.projectName);
162
+ const appBundleConfigPath = path.join(
163
+ appBundleDir,
164
+ 'ssl_config.json'
165
+ );
166
+ if (fs.existsSync(appBundleDir)) {
167
+ fs.copyFileSync(sourceConfigPath, appBundleConfigPath);
168
+ }
169
+ } else {
170
+ console.warn(`⚠️ SSL config file not found at: ${sourceConfigPath}`);
171
+ console.warn(
172
+ '💡 Place ssl_config.json in your project root for auto-setup'
173
+ );
174
+ }
175
+ } catch (error) {
176
+ console.warn('⚠️ Failed to copy SSL config:', error);
177
+ }
178
+
179
+ return config;
180
+ },
181
+ ]);
182
+
183
+ // Add to Xcode project programmatically - run in same withDangerousMod as file copy
184
+ config = withDangerousMod(config, [
185
+ 'ios',
186
+ async (config) => {
187
+ // First ensure file is copied to app bundle directory
188
+ const projectName = config.modRequest.projectName || 'exampleexpo';
189
+ const projectRoot = config.modRequest.projectRoot;
190
+ const sourceConfigPath = path.resolve(projectRoot, 'ssl_config.json');
191
+ const appBundleDir = path.join(
192
+ config.modRequest.platformProjectRoot,
193
+ projectName
194
+ );
195
+ const appBundleConfigPath = path.join(appBundleDir, 'ssl_config.json');
196
+
197
+ // Ensure SSL config is copied to app bundle directory
198
+ if (fs.existsSync(sourceConfigPath) && fs.existsSync(appBundleDir)) {
199
+ fs.copyFileSync(sourceConfigPath, appBundleConfigPath);
200
+ }
201
+
202
+ try {
203
+ const projectPath = path.join(
204
+ config.modRequest.platformProjectRoot,
205
+ `${projectName}.xcodeproj/project.pbxproj`
206
+ );
207
+ const sslConfigPath = appBundleConfigPath;
208
+
209
+ if (!fs.existsSync(projectPath) || !fs.existsSync(sslConfigPath)) {
210
+ console.warn(
211
+ '⚠️ Xcode project or SSL config not found, skipping automatic addition'
212
+ );
213
+ return config;
214
+ }
215
+
216
+ let projectContent = fs.readFileSync(projectPath, 'utf8');
217
+
218
+ // Check if already added
219
+ if (projectContent.includes('ssl_config.json')) {
220
+ return config;
221
+ }
222
+
223
+ // Generate unique IDs for the file
224
+ const fileRefId =
225
+ 'SSL' + Math.random().toString(36).substr(2, 24).toUpperCase();
226
+ const buildFileId =
227
+ 'SSL' + Math.random().toString(36).substr(2, 24).toUpperCase();
228
+
229
+ // Add file reference
230
+ const fileRefEntry = `\t\t${fileRefId} /* ssl_config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ssl_config.json; sourceTree = "<group>"; };`;
231
+ projectContent = projectContent.replace(
232
+ '/* End PBXFileReference section */',
233
+ fileRefEntry + '\n\t\t/* End PBXFileReference section */'
234
+ );
235
+
236
+ // Add build file
237
+ const buildFileEntry = `\t\t${buildFileId} /* ssl_config.json in Resources */ = {isa = PBXBuildFile; fileRef = ${fileRefId} /* ssl_config.json */; };`;
238
+ projectContent = projectContent.replace(
239
+ '/* End PBXBuildFile section */',
240
+ buildFileEntry + '\n\t\t/* End PBXBuildFile section */'
241
+ );
242
+
243
+ // Add to resources build phase
244
+ const resourcesPhaseMatch = projectContent.match(
245
+ /(\w+) \/\* Resources \*\/ = \{[^}]*files = \(([^)]*)\)/
246
+ );
247
+ if (resourcesPhaseMatch) {
248
+ const filesSection = resourcesPhaseMatch[2];
249
+ const newFilesSection =
250
+ filesSection +
251
+ `\t\t\t\t${buildFileId} /* ssl_config.json in Resources */,\n`;
252
+ projectContent = projectContent.replace(
253
+ `files = (${filesSection})`,
254
+ `files = (\n${newFilesSection}\t\t\t)`
255
+ );
256
+ }
257
+
258
+ // Add to main group
259
+ const mainGroupMatch = projectContent.match(
260
+ new RegExp(
261
+ `(\\w+) /\\* ${projectName} \\*/ = \\{[^}]*children = \\(([^)]*)\\)`
262
+ )
263
+ );
264
+ if (mainGroupMatch) {
265
+ const childrenSection = mainGroupMatch[2];
266
+ const newChildrenSection =
267
+ childrenSection + `\t\t\t\t${fileRefId} /* ssl_config.json */,\n`;
268
+ projectContent = projectContent.replace(
269
+ `children = (${childrenSection})`,
270
+ `children = (\n${newChildrenSection}\t\t\t)`
271
+ );
272
+ }
273
+
274
+ // Write back to file
275
+ fs.writeFileSync(projectPath, projectContent);
276
+ } catch (error) {
277
+ console.warn(
278
+ '⚠️ Failed to add SSL config to Xcode project:',
279
+ error.message
280
+ );
281
+ console.warn(
282
+ '💡 File copied to ios/ directory, manual Xcode setup may be needed'
283
+ );
284
+ }
285
+
286
+ return config;
287
+ },
288
+ ]);
289
+
290
+ return config;
291
+ }
292
+
293
+ module.exports = withSslManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ssl-manager",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "React Native SSL Pinning provides seamless SSL certificate pinning integration for enhanced network security in React Native apps. This module enables developers to easily implement and manage certificate pinning, protecting applications against man-in-the-middle (MITM) attacks. With dynamic configuration options and the ability to toggle SSL pinning, it's particularly useful for development and testing scenarios.",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.js",
@@ -29,6 +29,7 @@
29
29
  "android",
30
30
  "ios",
31
31
  "plugin",
32
+ "app.plugin.js",
32
33
  "*.podspec",
33
34
  "react-native-ssl-manager.podspec",
34
35
  "expo-module.config.json",