@capgo/capacitor-updater 7.23.13 → 7.24.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.
- package/README.md +115 -92
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +6 -7
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +3 -3
- package/android/src/main/java/ee/forgr/capacitor_updater/DeviceIdHelper.java +221 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +1 -1
- package/dist/docs.json +1 -1
- package/dist/esm/definitions.d.ts +10 -1
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +5 -6
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +3 -3
- package/ios/Sources/CapacitorUpdaterPlugin/DeviceIdHelper.swift +120 -0
- package/package.json +2 -3
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
import Security
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Helper class to manage device ID persistence across app installations.
|
|
12
|
+
* Uses iOS Keychain to persist the device ID.
|
|
13
|
+
*/
|
|
14
|
+
class DeviceIdHelper {
|
|
15
|
+
private static let keychainService = "app.capgo.updater"
|
|
16
|
+
private static let keychainAccount = "deviceId"
|
|
17
|
+
private static let legacyDefaultsKey = "appUUID"
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets or creates a device ID that persists across reinstalls.
|
|
21
|
+
*
|
|
22
|
+
* This method:
|
|
23
|
+
* 1. First checks for an existing ID in Keychain (persists across reinstalls)
|
|
24
|
+
* 2. Falls back to UserDefaults (for migration from older versions)
|
|
25
|
+
* 3. Generates a new UUID if neither exists
|
|
26
|
+
* 4. Stores the ID in Keychain for future use
|
|
27
|
+
*
|
|
28
|
+
* @return Device ID as a lowercase UUID string
|
|
29
|
+
*/
|
|
30
|
+
static func getOrCreateDeviceId() -> String {
|
|
31
|
+
// Try to get device ID from Keychain first
|
|
32
|
+
if let keychainDeviceId = getDeviceIdFromKeychain() {
|
|
33
|
+
return keychainDeviceId.lowercased()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Migration: Check UserDefaults for existing device ID
|
|
37
|
+
var deviceId = UserDefaults.standard.string(forKey: legacyDefaultsKey)
|
|
38
|
+
|
|
39
|
+
if deviceId == nil || deviceId!.isEmpty {
|
|
40
|
+
// Generate new device ID if none exists
|
|
41
|
+
deviceId = UUID().uuidString
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Ensure lowercase for consistency
|
|
45
|
+
deviceId = deviceId!.lowercased()
|
|
46
|
+
|
|
47
|
+
// Save to Keychain for persistence across reinstalls
|
|
48
|
+
saveDeviceIdToKeychain(deviceId: deviceId!)
|
|
49
|
+
|
|
50
|
+
return deviceId!
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves the device ID from iOS Keychain.
|
|
55
|
+
*
|
|
56
|
+
* @return Device ID string or nil if not found
|
|
57
|
+
*/
|
|
58
|
+
private static func getDeviceIdFromKeychain() -> String? {
|
|
59
|
+
let query: [String: Any] = [
|
|
60
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
61
|
+
kSecAttrService as String: keychainService,
|
|
62
|
+
kSecAttrAccount as String: keychainAccount,
|
|
63
|
+
kSecReturnData as String: true,
|
|
64
|
+
kSecMatchLimit as String: kSecMatchLimitOne
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
var result: AnyObject?
|
|
68
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
69
|
+
|
|
70
|
+
guard status == errSecSuccess,
|
|
71
|
+
let data = result as? Data,
|
|
72
|
+
let deviceId = String(data: data, encoding: .utf8) else {
|
|
73
|
+
return nil
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return deviceId
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Saves the device ID to iOS Keychain with appropriate accessibility settings.
|
|
81
|
+
*
|
|
82
|
+
* Uses kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly:
|
|
83
|
+
* - Data persists across reinstalls
|
|
84
|
+
* - Data is NOT synced to iCloud
|
|
85
|
+
* - Data is accessible after first device unlock
|
|
86
|
+
* - Data stays on this device only (privacy-friendly)
|
|
87
|
+
*
|
|
88
|
+
* @param deviceId The device ID to save
|
|
89
|
+
*/
|
|
90
|
+
private static func saveDeviceIdToKeychain(deviceId: String) {
|
|
91
|
+
guard let data = deviceId.data(using: .utf8) else {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Delete any existing entry first
|
|
96
|
+
let deleteQuery: [String: Any] = [
|
|
97
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
98
|
+
kSecAttrService as String: keychainService,
|
|
99
|
+
kSecAttrAccount as String: keychainAccount
|
|
100
|
+
]
|
|
101
|
+
SecItemDelete(deleteQuery as CFDictionary)
|
|
102
|
+
|
|
103
|
+
// Add new entry with appropriate accessibility
|
|
104
|
+
let addQuery: [String: Any] = [
|
|
105
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
106
|
+
kSecAttrService as String: keychainService,
|
|
107
|
+
kSecAttrAccount as String: keychainAccount,
|
|
108
|
+
kSecValueData as String: data,
|
|
109
|
+
// This ensures data persists across reinstalls but stays on device (not synced)
|
|
110
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
let status = SecItemAdd(addQuery as CFDictionary, nil)
|
|
114
|
+
|
|
115
|
+
if status != errSecSuccess {
|
|
116
|
+
// Log error but don't crash - we'll fall back to UserDefaults on next launch
|
|
117
|
+
print("Failed to save device ID to Keychain: \(status)")
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-updater",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.24.0",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "Live update for capacitor apps",
|
|
6
6
|
"main": "dist/plugin.cjs.js",
|
|
@@ -52,8 +52,7 @@
|
|
|
52
52
|
"eslint": "eslint . --ext .ts",
|
|
53
53
|
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
54
54
|
"swiftlint": "node-swiftlint",
|
|
55
|
-
"docgen": "
|
|
56
|
-
"docgen:api": "node scripts/generate-docs.js",
|
|
55
|
+
"docgen": "node scripts/generate-docs.js",
|
|
57
56
|
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
58
57
|
"clean": "rimraf ./dist",
|
|
59
58
|
"watch": "tsc --watch",
|