Skip to content

Commit

Permalink
Merge pull request #1 from ntnhon/main
Browse files Browse the repository at this point in the history
Improved public APIs and added support for nullable
  • Loading branch information
lukacs-m committed Jan 16, 2024
2 parents 4242599 + 73422ca commit 82afa78
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ let retrievedItem: String = try keychain.get(key: "YourKey")
```swift
// Delete a specific item
try keychain.delete("YourKey")
// Or alternatively set a nil value
try keychain.set(nil, for: "YourKey")

// Clear all items of a specific class type
try keychain.clear(ofType: .generic)
Expand Down
8 changes: 4 additions & 4 deletions Sources/SimpleKeychain/Protocols/KeychainServicing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Foundation

public protocol KeychainServicing {
@discardableResult
func get<T: Decodable & Sendable>(key: String, ofType itemClassType: ItemClassType) async throws -> T
func set<T: Encodable & Sendable>(_ item: T,
func get<T: Decodable & Sendable>(key: String, ofType itemClassType: ItemClassType) async throws -> T?
func set<T: Encodable & Sendable>(_ item: T?,
for key: String,
ofType itemClassType: ItemClassType,
with access: KeychainAccessOptions,
Expand All @@ -21,11 +21,11 @@ public protocol KeychainServicing {

extension KeychainServicing {
@discardableResult
func get<T: Decodable & Sendable>(key: String, ofType itemClassType: ItemClassType = .generic) async throws -> T {
func get<T: Decodable & Sendable>(key: String, ofType itemClassType: ItemClassType = .generic) async throws -> T? {
try await get(key: key, ofType: itemClassType)
}

func set<T: Encodable & Sendable>(_ item: T,
func set<T: Encodable & Sendable>(_ item: T?,
for key: String,
ofType itemClassType: ItemClassType = .generic,
with access: KeychainAccessOptions = .default,
Expand Down
27 changes: 21 additions & 6 deletions Sources/SimpleKeychain/SimpleKeychain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public actor SimpleKeychain: KeychainServicing {
}

@discardableResult
public func get<T: Decodable & Sendable>(key: String, ofType itemClassType: ItemClassType = .generic) throws -> T {
public func get<T: Decodable & Sendable>(key: String, ofType itemClassType: ItemClassType = .generic) throws -> T? {
var query = createQuery(for: key, ofType: itemClassType)
query[kSecMatchLimit] = kSecMatchLimitOne
query[kSecReturnAttributes] = kCFBooleanTrue
Expand All @@ -23,7 +23,13 @@ public actor SimpleKeychain: KeychainServicing {
var item: CFTypeRef?
let result = SecItemCopyMatching(query as CFDictionary, &item)
if result != errSecSuccess {
throw result.toSimpleKeychainError
let error = result.toSimpleKeychainError
switch error {
case .itemNotFound:
return nil
default:
throw error
}
}

guard let keychainItem = item as? [CFString: Any],
Expand All @@ -34,11 +40,15 @@ public actor SimpleKeychain: KeychainServicing {
return try JSONDecoder().decode(T.self, from: data)
}

public func set<T: Encodable & Sendable>(_ item: T,
public func set<T: Encodable & Sendable>(_ item: T?,
for key: String,
ofType itemClassType: ItemClassType = .generic,
with access: KeychainAccessOptions = .default,
attributes: [CFString: any Sendable]? = nil) throws {
guard let item else {
try delete(key, ofType: itemClassType)
return
}
let data = try JSONEncoder().encode(item)

do {
Expand All @@ -50,10 +60,15 @@ public actor SimpleKeychain: KeychainServicing {

public func delete(_ key: String, ofType itemClassType: ItemClassType = .generic) throws {
let query = createQuery(for: key, ofType: itemClassType)

let result = SecItemDelete(query as CFDictionary)
if result != errSecSuccess {
throw result.toSimpleKeychainError
let error = result.toSimpleKeychainError
switch error {
case .itemNotFound:
break
default:
throw error
}
}
}

Expand Down Expand Up @@ -110,6 +125,7 @@ private extension SimpleKeychain {
query[kSecClass] = itemClassType.rawValue
query[kSecAttrAccount] = key
query[kSecAttrAccessible] = access.value
query[kSecUseDataProtectionKeychain] = kCFBooleanTrue

if let data {
query[kSecValueData] = data
Expand All @@ -132,4 +148,3 @@ private extension SimpleKeychain {
return query
}
}

0 comments on commit 82afa78

Please sign in to comment.