Skip to content

Commit

Permalink
finished extension implmentation
Browse files Browse the repository at this point in the history
  • Loading branch information
leogdion committed Mar 27, 2024
1 parent c48e26f commit 50c29bb
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 230 deletions.
138 changes: 16 additions & 122 deletions Samples/Demo/App/Keychain/CompositeCredentials.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,128 +2,17 @@ import StealthyStash

@StealthyModel
struct CompositeCredentials {
//typealias QueryBuilder = CompositeCredentialsQueryBuilder

// struct QueryBuilder: ModelQueryBuilder {
// static func updates(
// from previousItem: CompositeCredentials,
// to newItem: CompositeCredentials
// ) -> [StealthyPropertyUpdate] {
// let newPasswordData = newItem.password.flatMap {
// $0.data(using: .utf8)
// }.map {
// InternetPasswordItem(account: newItem.userName, data: $0)
// }
//
// let oldPasswordData = previousItem.password.flatMap {
// $0.data(using: .utf8)
// }.map {
// InternetPasswordItem(account: previousItem.userName, data: $0)
// }
//
// let previousTokenData = previousItem.token.flatMap {
// $0.data(using: .utf8)
// }.map {
// GenericPasswordItem(account: previousItem.userName, data: $0)
// }
//
// let newTokenData = newItem.token.flatMap {
// $0.data(using: .utf8)
// }.map {
// GenericPasswordItem(account: newItem.userName, data: $0)
// }
//
// let passwordUpdate = StealthyPropertyUpdate(
// previousProperty: oldPasswordData,
// newProperty: newPasswordData
// )
// let tokenUpdate = StealthyPropertyUpdate(
// previousProperty: previousTokenData,
// newProperty: newTokenData
// )
// return [passwordUpdate, tokenUpdate]
// }
//
// static func properties(
// from model: CompositeCredentials,
// for _: ModelOperation
// ) -> [AnyStealthyProperty] {
// let passwordData = model.password.flatMap {
// $0.data(using: .utf8)
// }
//
// let passwordProperty: AnyStealthyProperty = .init(
// property: InternetPasswordItem(
// account: model.userName,
// data: passwordData ?? .init()
// )
// )
//
// let tokenData = model.token.flatMap {
// $0.data(using: .utf8)
// }
//
// let tokenProperty: AnyStealthyProperty = .init(
// property: GenericPasswordItem(
// account: model.userName,
// data: tokenData ?? .init()
// )
// )
//
// return [passwordProperty, tokenProperty]
// }
//
// static func queries(from _: Void) -> [String: Query] {
// [
// "password": TypeQuery(type: .internet),
// "token": TypeQuery(type: .generic)
// ]
// }
//
// static func model(
// from properties: [String: [AnyStealthyProperty]]
// ) throws -> CompositeCredentials? {
// for internet in properties["password"] ?? [] {
// for generic in properties["token"] ?? [] {
// if internet.account == generic.account {
// return .init(
// userName: internet.account,
// password: internet.dataString,
// token: generic.dataString
// )
// }
// }
// }
// let properties = properties.values.flatMap { $0 }.enumerated().sorted { lhs, rhs in
// if lhs.element.propertyType == rhs.element.propertyType {
// return lhs.offset < rhs.offset
// } else {
// return lhs.element.propertyType == .internet
// }
// }.map(\.element)
//
// guard let username = properties.map(\.account).first else {
// return nil
// }
// let password = properties
// .first { $0.propertyType == .internet }?
// .data
// let token = properties.first {
// $0.propertyType == .generic && $0.account == username
// }?.data
//
// return CompositeCredentials(
// userName: username,
// password: password?.string(),
// token: token?.string()
// )
// }
//
// typealias QueryType = Void
//
// typealias StealthyModelType = CompositeCredentials
// }

#warning("deal with queries")
#warning("add init(properties:)")
init?(properties: [String: AnyStealthyProperty]) {
guard let account = properties["password"]?.account else {
return nil
}
self.account = account
self.password = properties["password"]?.dataString
self.token = properties["token"]?.dataString
}

internal init(account: String, password: String?, token: String?) {
self.account = account
self.password = password
Expand All @@ -132,6 +21,11 @@ struct CompositeCredentials {

let account: String

// @Key
#warning("Add @Key")
// @InternetPassword
#warning("Add @Internet")
#warning("Add @Generic")
let password: String?

let token: String?
Expand Down
4 changes: 2 additions & 2 deletions Samples/Demo/App/Views/CompositeStealthyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct CompositeStealthyView: View {
if object.isLoaded {
Form {
Section("User Name") {
TextField("User name", text: self.$object.secret.userName)
TextField("User name", text: self.$object.secret.account)
}

Section("Password") {
Expand Down Expand Up @@ -71,7 +71,7 @@ struct CompositeStealthyView_Previews: PreviewProvider {
CompositeStealthyView(
repository: PreviewRepository(items: []),
triggerSet: .init(),
secret: .init(userName: "username", password: "password", token: "token")
secret: .init(account: "username", password: "password", token: "token")
)
}
}
56 changes: 56 additions & 0 deletions Sources/StealthyStash/StealthyModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,59 @@ public protocol StealthyModel {
associatedtype QueryBuilder: ModelQueryBuilder
where QueryBuilder.StealthyModelType == Self
}


public extension StealthyModel {

static func dictionary(
for keys: [String],
from dictionary: [String: [AnyStealthyProperty]]
) -> [String: AnyStealthyProperty]? {
let catalog = catalogAccounts(keys: .init(keys), dictionary: dictionary)
return findAccountWithMostMatches(accountCatalog: catalog, dictionary: dictionary)
}

private static func catalogAccounts(keys: Set<String>, dictionary: [String: [AnyStealthyProperty]]) -> [String: [(String, Int)]] {
var accountCatalog = [String: [(String, Int)]]()

for key in keys {
guard let properties = dictionary[key] else { continue }

for (index, property) in properties.enumerated() {
let keyIndexTuple = (key, index)
if var accountIndexArray = accountCatalog[property.account] {
accountIndexArray.append(keyIndexTuple)
accountCatalog[property.account] = accountIndexArray
} else {
accountCatalog[property.account] = [keyIndexTuple]
}
}
}

return accountCatalog
}

private static func findAccountWithMostMatches(accountCatalog: [String: [(String, Int)]], dictionary: [String: [AnyStealthyProperty]]) -> [String: AnyStealthyProperty]? {
var maxAccount: String?
var maxCount = 0

for (account, keyIndexArray) in accountCatalog {
if keyIndexArray.count > maxCount {
maxCount = keyIndexArray.count
maxAccount = account
}
}

guard let account = maxAccount else { return nil }

var resultDictionary = [String: AnyStealthyProperty]()

for (key, index) in accountCatalog[account]! {
if let properties = dictionary[key], properties.indices.contains(index) {
resultDictionary[key] = properties[index]
}
}

return resultDictionary
}
}
Loading

0 comments on commit 50c29bb

Please sign in to comment.