capacitor-secure-storage-plugin 0.11.0 → 0.12.0

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.
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
10
10
  s.homepage = package['repository']['url']
11
11
  s.author = package['author']
12
12
  s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
- s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
14
  s.ios.deployment_target = '14.0'
15
15
  s.dependency 'Capacitor'
16
16
  s.dependency 'SwiftKeychainWrapper'
package/Package.swift ADDED
@@ -0,0 +1,30 @@
1
+ // swift-tools-version: 5.9
2
+ import PackageDescription
3
+
4
+ let package = Package(
5
+ name: "CapacitorSecureStoragePlugin",
6
+ platforms: [.iOS(.v14)],
7
+ products: [
8
+ .library(
9
+ name: "CapacitorSecureStoragePlugin",
10
+ targets: ["SecureStoragePlugin"])
11
+ ],
12
+ dependencies: [
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0"),
14
+ .package(url: "https://github.com/jrendel/SwiftKeychainWrapper.git", from: "4.0.0")
15
+ ],
16
+ targets: [
17
+ .target(
18
+ name: "SecureStoragePlugin",
19
+ dependencies: [
20
+ .product(name: "Capacitor", package: "capacitor-swift-pm"),
21
+ .product(name: "Cordova", package: "capacitor-swift-pm"),
22
+ .product(name: "SwiftKeychainWrapper", package: "SwiftKeychainWrapper")
23
+ ],
24
+ path: "ios/Sources/SecureStoragePlugin"),
25
+ .testTarget(
26
+ name: "SecureStoragePluginTests",
27
+ dependencies: ["SecureStoragePlugin"],
28
+ path: "ios/Tests/SecureStoragePluginTests")
29
+ ]
30
+ )
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![npm version](https://badge.fury.io/js/capacitor-secure-storage-plugin.svg)](https://badge.fury.io/js/capacitor-secure-storage-plugin)
2
+
1
3
  # capacitor-secure-storage-plugin
2
4
 
3
5
  Capacitor plugin for storing string values securly on iOS and Android.
@@ -7,7 +7,17 @@ import SwiftKeychainWrapper
7
7
  * here: https://capacitor.ionicframework.com/docs/plugins/ios
8
8
  */
9
9
  @objc(SecureStoragePlugin)
10
- public class SecureStoragePlugin: CAPPlugin {
10
+ public class SecureStoragePlugin: CAPPlugin, CAPBridgedPlugin {
11
+ public let identifier = "SecureStoragePlugin"
12
+ public let jsName = "SecureStoragePlugin"
13
+ public let pluginMethods: [CAPPluginMethod] = [
14
+ CAPPluginMethod(name: "set", returnType: CAPPluginReturnPromise),
15
+ CAPPluginMethod(name: "get", returnType: CAPPluginReturnPromise),
16
+ CAPPluginMethod(name: "keys", returnType: CAPPluginReturnPromise),
17
+ CAPPluginMethod(name: "remove", returnType: CAPPluginReturnPromise),
18
+ CAPPluginMethod(name: "clear", returnType: CAPPluginReturnPromise),
19
+ CAPPluginMethod(name: "getPlatform", returnType: CAPPluginReturnPromise),
20
+ ]
11
21
  var keychainwrapper: KeychainWrapper = KeychainWrapper.init(serviceName: "cap_sec")
12
22
 
13
23
  @objc func set(_ call: CAPPluginCall) {
@@ -0,0 +1,247 @@
1
+ import XCTest
2
+ import Capacitor
3
+ import SwiftKeychainWrapper
4
+
5
+ @testable import Plugin
6
+
7
+ class PluginTests: XCTestCase {
8
+
9
+ func setupDedicatedWrapper() -> KeychainWrapper {
10
+ let wrapper = KeychainWrapper.init(serviceName: "cap_sec")
11
+ wrapper.removeAllKeys()
12
+ return wrapper
13
+ }
14
+
15
+ func testSet() {
16
+ let key = "key"
17
+ let value = "Hello, World!"
18
+ let valueModified = "Modified"
19
+ let keychainwrapper = setupDedicatedWrapper()
20
+ KeychainWrapper.standard.set(value, forKey: key)
21
+
22
+ let plugin = SecureStoragePlugin()
23
+
24
+ let call = CAPPluginCall(callbackId: "test", options: [
25
+ "key": key,
26
+ "value": valueModified
27
+ ], success: { (result, call) in
28
+ let resultValue = result!.data?["value"] as? Bool
29
+ XCTAssertTrue(resultValue ?? false)
30
+ // dedicated keychain wrapper
31
+ let dedicatedValue = keychainwrapper.string(forKey: key)
32
+ XCTAssertEqual(valueModified, dedicatedValue)
33
+ // standard keychain wrapper should not be modified
34
+ let standardValue = KeychainWrapper.standard.string(forKey: key)
35
+ XCTAssertEqual(value, standardValue)
36
+ }, error: { (err) in
37
+ XCTFail("Error shouldn't have been called")
38
+ })
39
+
40
+ plugin.set(call!)
41
+ }
42
+
43
+ func testGet() {
44
+ let key = "key"
45
+ let value = "Hello, World!"
46
+ let keychainwrapper = setupDedicatedWrapper()
47
+ keychainwrapper.set(value, forKey: key)
48
+
49
+ let plugin = SecureStoragePlugin()
50
+
51
+ let call = CAPPluginCall(callbackId: "test", options: [
52
+ "key": key
53
+ ], success: { (result, call) in
54
+ let resultValue = result!.data?["value"] as? String
55
+ XCTAssertEqual(value, resultValue)
56
+ }, error: { (err) in
57
+ XCTFail("Error shouldn't have been called")
58
+ })
59
+
60
+ plugin.get(call!)
61
+ }
62
+
63
+ func testGetCopy() {
64
+ let key = "key"
65
+ let value = "Hello, World!"
66
+ let keychainwrapper = setupDedicatedWrapper()
67
+
68
+ KeychainWrapper.standard.set(value, forKey: key)
69
+
70
+ let plugin = SecureStoragePlugin()
71
+
72
+ let call = CAPPluginCall(callbackId: "test", options: [
73
+ "key": key
74
+ ], success: { (result, call) in
75
+ let resultValue = result!.data?["value"] as? String
76
+ XCTAssertEqual(value, resultValue)
77
+ let dedicatedValue = keychainwrapper.string(forKey: key)
78
+ XCTAssertEqual(value, dedicatedValue)
79
+ let standardValue = KeychainWrapper.standard.string(forKey: key)
80
+ XCTAssertNil(standardValue)
81
+ }, error: { (err) in
82
+ XCTFail("Error shouldn't have been called")
83
+ })
84
+
85
+ plugin.get(call!)
86
+ }
87
+
88
+ func testKeys() {
89
+ let key = "key"
90
+ let key2 = "key2"
91
+ let value = "value"
92
+
93
+ let plugin = SecureStoragePlugin()
94
+
95
+ let keychainwrapper = setupDedicatedWrapper()
96
+ keychainwrapper.set(value, forKey: key)
97
+ keychainwrapper.set(value, forKey: key2)
98
+
99
+
100
+ let callOne = CAPPluginCall(callbackId: "test", options: [:],
101
+ success: { (result, call) in
102
+ let resultValue = result!.data?["value"] as? Array<String>
103
+ XCTAssertEqual(2, resultValue!.count)
104
+ XCTAssertTrue(resultValue!.contains(key))
105
+ XCTAssertTrue(resultValue!.contains(key2))
106
+ }, error: { (err) in
107
+ XCTFail("Error shouldn't have been called")
108
+ })
109
+ plugin.keys(callOne!)
110
+ }
111
+
112
+ func testNonExistingGet() {
113
+ let key = "keyNonExisting"
114
+
115
+ let plugin = SecureStoragePlugin()
116
+
117
+ let call = CAPPluginCall(callbackId: "test", options: [
118
+ "key": key
119
+ ], success: { (result, call) in
120
+ XCTFail("Error shouldn't have been called")
121
+ }, error: { (err) in
122
+ XCTAssertNotNil(err)
123
+ })
124
+
125
+ plugin.get(call!)
126
+ }
127
+
128
+ func testNonExistingRemoveBoth() {
129
+ let key = "keyNonExisting"
130
+
131
+ let plugin = SecureStoragePlugin()
132
+
133
+ let call = CAPPluginCall(callbackId: "test", options: [
134
+ "key": key
135
+ ], success: { (result, call) in
136
+ XCTFail("Error shouldn't have been called")
137
+ }, error: { (err) in
138
+ XCTAssertNotNil(err)
139
+ })
140
+
141
+ plugin.remove(call!)
142
+ }
143
+
144
+ func testRemoveBoth() {
145
+ let key = "key"
146
+ let value = "Hello, World!"
147
+ // prefill dedicated keychain wrapper
148
+ let keychainwrapper = setupDedicatedWrapper()
149
+ keychainwrapper.set(value, forKey: key)
150
+ // prefill standard keychain wrapper
151
+ KeychainWrapper.standard.set(value, forKey: key)
152
+
153
+ let plugin = SecureStoragePlugin()
154
+
155
+ let call = CAPPluginCall(callbackId: "test", options: [
156
+ "key": key
157
+ ], success: { (result, call) in
158
+ let resultValue = result!.data?["value"] as? Bool
159
+ XCTAssertTrue(resultValue ?? false)
160
+ // dedicated keychain wrapper
161
+ let dedicatedValue = keychainwrapper.string(forKey: key)
162
+ XCTAssertNil(dedicatedValue)
163
+ // standard keychain wrapper
164
+ let standardValueRemoved = KeychainWrapper.standard.string(forKey: key)
165
+ XCTAssertNil(standardValueRemoved)
166
+ }, error: { (err) in
167
+ XCTFail("Error shouldn't have been called")
168
+ })
169
+
170
+ plugin.remove(call!)
171
+ }
172
+
173
+ // same as testRemoveBoth, but don't prefill standard wrapper
174
+ func testRemove() {
175
+ let key = "key"
176
+ let value = "Hello, World!"
177
+ // prefill dedicated keychain wrapper
178
+ let keychainwrapper = setupDedicatedWrapper()
179
+ keychainwrapper.set(value, forKey: key)
180
+
181
+ let plugin = SecureStoragePlugin()
182
+
183
+ let call = CAPPluginCall(callbackId: "test", options: [
184
+ "key": key
185
+ ], success: { (result, call) in
186
+ let resultValue = result!.data?["value"] as? Bool
187
+ XCTAssertTrue(resultValue ?? false)
188
+ // dedicated keychain wrapper
189
+ let dedicatedValue = keychainwrapper.string(forKey: key)
190
+ XCTAssertNil(dedicatedValue)
191
+ }, error: { (err) in
192
+ XCTFail("Error shouldn't have been called")
193
+ })
194
+
195
+ plugin.remove(call!)
196
+ }
197
+
198
+ func testClear() {
199
+ let key = "key"
200
+ let value = "Hello, World!"
201
+ let standardOnlyKey = "standard key"
202
+ let standardOnlyValue = "standard value"
203
+ // prefill dedicated keychain wrapper
204
+ let keychainwrapper = setupDedicatedWrapper()
205
+ keychainwrapper.set(value, forKey: key)
206
+ keychainwrapper.set(value + "2", forKey: key + "2")
207
+ // prefill standard keychain wrapper
208
+ KeychainWrapper.standard.set(value, forKey: key)
209
+ KeychainWrapper.standard.set(standardOnlyValue, forKey: standardOnlyKey)
210
+
211
+ let plugin = SecureStoragePlugin()
212
+
213
+ let call = CAPPluginCall(callbackId: "test", options: [
214
+ "key": key
215
+ ], success: { (result, call) in
216
+ let resultValue = result!.data?["value"] as? Bool
217
+ XCTAssertTrue(resultValue ?? false)
218
+ // key present in dedicated and standard wrapper removed
219
+ let dedicatedValue = keychainwrapper.string(forKey: key)
220
+ XCTAssertNil(dedicatedValue)
221
+ let dedicatedValue2 = keychainwrapper.string(forKey: key + "2")
222
+ XCTAssertNil(dedicatedValue2)
223
+ let standardValue = KeychainWrapper.standard.string(forKey: key)
224
+ XCTAssertNil(standardValue)
225
+ // key only defined in standard wrapper still present
226
+ let standardValue2 = KeychainWrapper.standard.string(forKey: standardOnlyKey)
227
+ XCTAssertEqual(standardOnlyValue, standardValue2)
228
+ }, error: { (err) in
229
+ XCTFail("Error shouldn't have been called")
230
+ })
231
+
232
+ plugin.clear(call!)
233
+ }
234
+
235
+ func testGetPlatform() {
236
+ let plugin = SecureStoragePlugin()
237
+ let call = CAPPluginCall(callbackId: "test",
238
+ success: { (result, call) in
239
+ let resultValue = result!.data?["value"] as? String
240
+ XCTAssertEqual("ios", resultValue)
241
+ }, error: { (err) in
242
+ XCTFail("Error shouldn't have been called")
243
+ })
244
+
245
+ plugin.getPlatform(call!)
246
+ }
247
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-secure-storage-plugin",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Securely store secrets such as usernames, passwords, tokens, certificates or other sensitive information (strings) on iOS & Android",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -10,7 +10,9 @@
10
10
  "android/src/main/",
11
11
  "android/build.gradle",
12
12
  "dist/",
13
- "ios/Plugin/",
13
+ "ios/Sources",
14
+ "ios/Tests",
15
+ "Package.swift",
14
16
  "CapacitorSecureStoragePlugin.podspec"
15
17
  ],
16
18
  "author": "martinkasa",
@@ -29,7 +31,7 @@
29
31
  ],
30
32
  "scripts": {
31
33
  "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
32
- "verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin && cd ..",
34
+ "verify:ios" : "xcodebuild -scheme CapacitorSecureStoragePlugin -destination generic/platform=iOS",
33
35
  "verify:android": "cd android && ./gradlew clean build test && cd ..",
34
36
  "verify:web": "npm run build",
35
37
  "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
@@ -1,24 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>CFBundleDevelopmentRegion</key>
6
- <string>$(DEVELOPMENT_LANGUAGE)</string>
7
- <key>CFBundleExecutable</key>
8
- <string>$(EXECUTABLE_NAME)</string>
9
- <key>CFBundleIdentifier</key>
10
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
- <key>CFBundleInfoDictionaryVersion</key>
12
- <string>6.0</string>
13
- <key>CFBundleName</key>
14
- <string>$(PRODUCT_NAME)</string>
15
- <key>CFBundlePackageType</key>
16
- <string>FMWK</string>
17
- <key>CFBundleShortVersionString</key>
18
- <string>1.0</string>
19
- <key>CFBundleVersion</key>
20
- <string>$(CURRENT_PROJECT_VERSION)</string>
21
- <key>NSPrincipalClass</key>
22
- <string></string>
23
- </dict>
24
- </plist>
@@ -1,10 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- //! Project version number for Plugin.
4
- FOUNDATION_EXPORT double PluginVersionNumber;
5
-
6
- //! Project version string for Plugin.
7
- FOUNDATION_EXPORT const unsigned char PluginVersionString[];
8
-
9
- // In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
10
-
@@ -1,13 +0,0 @@
1
- #import <Foundation/Foundation.h>
2
- #import <Capacitor/Capacitor.h>
3
-
4
- // Define the plugin using the CAP_PLUGIN Macro, and
5
- // each method the plugin supports using the CAP_PLUGIN_METHOD macro.
6
- CAP_PLUGIN(SecureStoragePlugin, "SecureStoragePlugin",
7
- CAP_PLUGIN_METHOD(set, CAPPluginReturnPromise);
8
- CAP_PLUGIN_METHOD(get, CAPPluginReturnPromise);
9
- CAP_PLUGIN_METHOD(keys, CAPPluginReturnPromise);
10
- CAP_PLUGIN_METHOD(remove, CAPPluginReturnPromise);
11
- CAP_PLUGIN_METHOD(clear, CAPPluginReturnPromise);
12
- CAP_PLUGIN_METHOD(getPlatform, CAPPluginReturnPromise);
13
- )