Skip to content

Commit b749a3b

Browse files
committed
build out keychain functionality
1 parent 08eb3d6 commit b749a3b

File tree

1 file changed

+15
-118
lines changed

1 file changed

+15
-118
lines changed

swift-sdk/Internal/IterableKeychain.swift

Lines changed: 15 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -59,134 +59,31 @@ class IterableKeychain {
5959
}
6060
}
6161

62-
init(wrapper: KeychainWrapper = KeychainWrapper()) {
63-
self.wrapper = wrapper
64-
}
65-
66-
private let wrapper: KeychainWrapper
67-
}
68-
69-
/// Basic wrapper for keychain
70-
/// This should have no dependency on Iterable classes
71-
class KeychainWrapper {
72-
init(serviceName: String = Const.Keychain.serviceName) {
73-
self.serviceName = serviceName
74-
}
75-
76-
@discardableResult
77-
func set(_ value: Data, forKey key: String) -> Bool {
78-
var keychainQueryDictionary: [String: Any] = setupKeychainQueryDictionary(forKey: key)
79-
80-
keychainQueryDictionary[SecValueData] = value
62+
func getLastPushPayload(currentDate: Date) -> [AnyHashable: Any]? {
63+
// let data = wrapper.data(forKey: Const.Keychain.Key.lastPushPayload)
8164

82-
// Assign default protection - Protect the keychain entry so it's only valid when the device is unlocked
83-
keychainQueryDictionary[SecAttrAccessible] = SecAttrAccessibleWhenUnlocked
8465

85-
let status: OSStatus = SecItemAdd(keychainQueryDictionary as CFDictionary, nil)
8666

87-
if status == errSecSuccess {
88-
return true
89-
} else if status == errSecDuplicateItem {
90-
return update(value, forKey: key)
91-
} else {
92-
return false
93-
}
94-
}
95-
96-
func data(forKey key: String) -> Data? {
97-
var keychainQueryDictionary = setupKeychainQueryDictionary(forKey: key)
98-
99-
// Limit search results to one
100-
keychainQueryDictionary[SecMatchLimit] = SecMatchLimitOne
101-
102-
// Specify we want Data/CFData returned
103-
keychainQueryDictionary[SecReturnData] = CFBooleanTrue
104-
105-
// Search
106-
var result: AnyObject?
107-
let status = SecItemCopyMatching(keychainQueryDictionary as CFDictionary, &result)
108-
109-
return status == noErr ? result as? Data : nil
67+
return nil
11068
}
11169

112-
@discardableResult
113-
func removeValue(forKey key: String) -> Bool {
114-
let keychainQueryDictionary: [String: Any] = setupKeychainQueryDictionary(forKey: key)
115-
116-
// Delete
117-
let status: OSStatus = SecItemDelete(keychainQueryDictionary as CFDictionary)
118-
119-
if status == errSecSuccess {
120-
return true
121-
} else {
122-
return false
70+
func setLastPushPayload(_ payload: [AnyHashable: Any]?, withExpiration expiration: Date?) {
71+
guard let value = payload?.jsonValue, JSONSerialization.isValidJSONObject(value) else {
72+
wrapper.removeValue(forKey: Const.Keychain.Key.lastPushPayload)
73+
return
12374
}
124-
}
125-
126-
@discardableResult
127-
func removeAll() -> Bool {
128-
var keychainQueryDictionary: [String: Any] = [SecClass: SecClassGenericPassword]
129-
130-
keychainQueryDictionary[SecAttrService] = serviceName
131-
132-
let status: OSStatus = SecItemDelete(keychainQueryDictionary as CFDictionary)
13375

134-
if status == errSecSuccess {
135-
return true
136-
} else {
137-
return false
76+
do {
77+
let data = try JSONSerialization.data(withJSONObject: value, options: [])
78+
wrapper.set(data, forKey: Const.Keychain.Key.lastPushPayload)
79+
} catch {
80+
wrapper.removeValue(forKey: Const.Keychain.Key.lastPushPayload)
13881
}
13982
}
14083

141-
142-
private let serviceName: String
143-
144-
private func setupKeychainQueryDictionary(forKey key: String) -> [String: Any] {
145-
// Setup default access as generic password (rather than a certificate, internet password, etc)
146-
var keychainQueryDictionary: [String: Any] = [SecClass: SecClassGenericPassword]
147-
148-
// Uniquely identify this keychain accessor
149-
keychainQueryDictionary[SecAttrService] = serviceName
150-
151-
// Uniquely identify the account who will be accessing the keychain
152-
let encodedIdentifier: Data? = key.data(using: .utf8)
153-
154-
keychainQueryDictionary[SecAttrGeneric] = encodedIdentifier
155-
156-
keychainQueryDictionary[SecAttrAccount] = encodedIdentifier
157-
158-
keychainQueryDictionary[SecAttrSynchronizable] = CFBooleanFalse
159-
160-
return keychainQueryDictionary
161-
}
162-
163-
private func update(_ value: Data, forKey key: String) -> Bool {
164-
let keychainQueryDictionary: [String: Any] = setupKeychainQueryDictionary(forKey: key)
165-
let updateDictionary = [SecValueData: value]
166-
167-
// Update
168-
let status: OSStatus = SecItemUpdate(keychainQueryDictionary as CFDictionary, updateDictionary as CFDictionary)
169-
170-
if status == errSecSuccess {
171-
return true
172-
} else {
173-
return false
174-
}
84+
init(wrapper: KeychainWrapper = KeychainWrapper()) {
85+
self.wrapper = wrapper
17586
}
17687

177-
private let SecValueData = kSecValueData as String
178-
private let SecAttrAccessible: String = kSecAttrAccessible as String
179-
private let SecAttrAccessibleWhenUnlocked = kSecAttrAccessibleWhenUnlocked
180-
private let SecClass: String = kSecClass as String
181-
private let SecClassGenericPassword = kSecClassGenericPassword
182-
private let SecAttrService: String = kSecAttrService as String
183-
private let SecAttrGeneric: String = kSecAttrGeneric as String
184-
private let SecAttrAccount: String = kSecAttrAccount as String
185-
private let SecAttrSynchronizable: String = kSecAttrSynchronizable as String
186-
private let CFBooleanTrue = kCFBooleanTrue
187-
private let CFBooleanFalse = kCFBooleanFalse
188-
private let SecMatchLimit: String = kSecMatchLimit as String
189-
private let SecMatchLimitOne = kSecMatchLimitOne
190-
private let SecReturnData: String = kSecReturnData as String
88+
private let wrapper: KeychainWrapper
19189
}
192-

0 commit comments

Comments
 (0)