Commit 257e732a authored by Jose Blaya's avatar Jose Blaya
Browse files

Persist the public username in the Keychain instead the PlainStore

parent 00ea4a0d
......@@ -11,9 +11,7 @@ import Foundation
protocol PlainStore: class {
// MARK: Account
var publicUsername: String? { get set }
var accountInfo: AccountInfo? { get set }
var lastSignupEmail: String? { get set }
......
......@@ -17,6 +17,10 @@ protocol SecureStore: class {
func setUsername(_ username: String?)
func publicUsername() -> String?
func setPublicUsername(_ username: String?)
func password(for username: String) -> String?
func setPassword(_ password: String?, for username: String)
......
......@@ -48,7 +48,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
}
var publicUsername: String? {
guard let username = accessedDatabase.plain.publicUsername else {
guard let username = accessedDatabase.secure.publicUsername() else {
return nil
}
return username
......@@ -69,7 +69,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
}
set {
if let user = newValue {
accessedDatabase.plain.publicUsername = user.credentials.username
accessedDatabase.secure.setPublicUsername(user.credentials.username)
accessedDatabase.secure.setPassword(user.credentials.password, for: user.credentials.username)
accessedDatabase.plain.accountInfo = user.info
} else {
......@@ -77,7 +77,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
accessedDatabase.secure.setPassword(nil, for: username)
accessedDatabase.secure.setUsername(nil)
}
accessedDatabase.plain.publicUsername = nil
accessedDatabase.secure.setPublicUsername(nil)
accessedDatabase.plain.accountInfo = nil
}
}
......@@ -111,7 +111,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
let tokenComponents = token.split(by: token.count/2)
if let first = tokenComponents.first,
let last = tokenComponents.last {
self.accessedDatabase.plain.publicUsername = username
self.accessedDatabase.secure.setPublicUsername(username)
self.accessedDatabase.secure.setUsername(first)
self.accessedDatabase.secure.setToken(token,
for: self.accessedDatabase.secure.tokenKey(for: first))
......@@ -300,7 +300,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
self.accessedStore.finishTransaction(transaction, success: true)
}
self.accessedDatabase.plain.lastSignupEmail = nil
self.accessedDatabase.plain.publicUsername = credentials.username
self.accessedDatabase.secure.setPublicUsername(credentials.username)
self.accessedDatabase.secure.setPassword(credentials.password, for: credentials.username)
let user = UserAccount(credentials: credentials, info: nil)
......@@ -337,7 +337,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
let tokenComponents = token.split(by: token.count/2)
if let first = tokenComponents.first,
let last = tokenComponents.last {
self.accessedDatabase.plain.publicUsername = credentials.username
self.accessedDatabase.secure.setPublicUsername(credentials.username)
self.accessedDatabase.secure.setUsername(first)
self.accessedDatabase.secure.setToken(token,
for: self.accessedDatabase.secure.tokenKey(for: first))
......@@ -446,7 +446,7 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
accessedDatabase.secure.setUsername(nil)
accessedDatabase.secure.setToken(nil, for: accessedDatabase.secure.tokenKey(for: username))
}
accessedDatabase.plain.publicUsername = nil
accessedDatabase.secure.setPublicUsername(nil)
accessedDatabase.plain.accountInfo = nil
}
#endif
......
......@@ -57,9 +57,6 @@ extension Client {
- Returns: `self`
*/
@discardableResult public func truncate() -> Self {
if let username = plain.publicUsername {
secure.clear(for: username)
}
plain.clear()
transient = MemoryStore()
return self
......
......@@ -78,6 +78,21 @@ extension KeychainStore {
}
}
extension KeychainStore {
func publicUsername() -> String? {
return try? backend.publicUsername()
}
func setPublicUsername(_ username: String?) {
if let username = username {
try? backend.set(publicUsername: username)
} else {
backend.removePublicUsername()
}
}
}
extension KeychainStore {
func token(for username: String) -> String? {
......
......@@ -28,6 +28,7 @@ public class Keychain {
private let accessGroup: String?
private let usernameKey = "USERNAME_KEY"
private let publicUsernameKey = "PUBLIC_USERNAME_KEY"
/**
Default initializer. Uses the default keychain associated with the main bundle identifier.
......@@ -287,6 +288,64 @@ extension Keychain {
}
extension Keychain {
// MARK: Public Username
/// :nodoc:
public func set(publicUsername: String) throws {
removePublicUsername()
var query = [String: Any]()
setScope(query: &query)
query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrAccount as String] = publicUsernameKey
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
query[kSecValueData as String] = publicUsername.data(using: .utf8)
let status = SecItemAdd(query as CFDictionary, nil)
guard (status == errSecSuccess) else {
throw KeychainError.add
}
}
/// :nodoc:
@discardableResult public func removePublicUsername() -> Bool {
var query = [String: Any]()
setScope(query: &query)
query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrAccount as String] = publicUsernameKey
let status = SecItemDelete(query as CFDictionary)
return (status == errSecSuccess)
}
/// :nodoc:
public func publicUsername() throws -> String {
var query = [String: Any]()
setScope(query: &query)
query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrAccount as String] = publicUsernameKey
//query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
query[kSecMatchLimit as String] = kSecMatchLimitOne
query[kSecReturnData as String] = true
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard (status == errSecSuccess) else {
throw KeychainError.notFound
}
guard let data = result as? Data else {
throw KeychainError.notFound
}
guard let token = String(data: data, encoding: .utf8) else {
throw KeychainError.notFound
}
return token
}
}
extension Keychain {
// MARK: Token
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment