Implement keychain groups
This commit is contained in:
parent
0e12f0192a
commit
20fa5d9e48
|
@ -72,6 +72,14 @@ public final class AccountManager: UnreadCountProvider {
|
|||
return CombinedRefreshProgress(downloadProgressArray: downloadProgressArray)
|
||||
}
|
||||
|
||||
public convenience init() {
|
||||
let appGroup = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String
|
||||
let accountsURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup)
|
||||
let accountsFolder = accountsURL!.appendingPathComponent("Accounts").absoluteString
|
||||
let accountsFolderPath = accountsFolder.suffix(from: accountsFolder.index(accountsFolder.startIndex, offsetBy: 7))
|
||||
self.init(accountsFolder: String(accountsFolderPath))
|
||||
}
|
||||
|
||||
public init(accountsFolder: String) {
|
||||
self.accountsFolder = accountsFolder
|
||||
|
||||
|
|
|
@ -10,6 +10,15 @@ import Foundation
|
|||
|
||||
public struct CredentialsManager {
|
||||
|
||||
private static var keychainGroup: String? = {
|
||||
guard let appGroup = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as? String else {
|
||||
return nil
|
||||
}
|
||||
let appIdentifierPrefix = Bundle.main.object(forInfoDictionaryKey: "AppIdentifierPrefix") as! String
|
||||
let appGroupSuffix = appGroup.suffix(appGroup.count - 6)
|
||||
return "\(appIdentifierPrefix)\(appGroupSuffix)"
|
||||
}()
|
||||
|
||||
public static func storeCredentials(_ credentials: Credentials, server: String) throws {
|
||||
|
||||
var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
|
||||
|
@ -20,6 +29,10 @@ public struct CredentialsManager {
|
|||
query[kSecAttrSecurityDomain as String] = credentials.type.rawValue
|
||||
}
|
||||
|
||||
if let securityGroup = keychainGroup {
|
||||
query[kSecAttrAccessGroup as String] = securityGroup
|
||||
}
|
||||
|
||||
let secretData = credentials.secret.data(using: String.Encoding.utf8)!
|
||||
let attributes: [String: Any] = [kSecValueData as String: secretData]
|
||||
let status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary)
|
||||
|
@ -59,6 +72,10 @@ public struct CredentialsManager {
|
|||
query[kSecAttrSecurityDomain as String] = type.rawValue
|
||||
}
|
||||
|
||||
if let securityGroup = keychainGroup {
|
||||
query[kSecAttrAccessGroup as String] = securityGroup
|
||||
}
|
||||
|
||||
var item: CFTypeRef?
|
||||
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
||||
|
||||
|
@ -93,6 +110,10 @@ public struct CredentialsManager {
|
|||
query[kSecAttrSecurityDomain as String] = type.rawValue
|
||||
}
|
||||
|
||||
if let securityGroup = keychainGroup {
|
||||
query[kSecAttrAccessGroup as String] = securityGroup
|
||||
}
|
||||
|
||||
let status = SecItemDelete(query as CFDictionary)
|
||||
guard status == errSecSuccess || status == errSecItemNotFound else {
|
||||
throw CredentialsError.unhandledError(status: status)
|
||||
|
|
|
@ -55,12 +55,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
|
|||
|
||||
// Force lazy initialization of the web view provider so that it can warm up the queue of prepared web views
|
||||
let _ = DetailViewControllerWebViewProvider.shared
|
||||
|
||||
let accountsURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.\(Bundle.main.bundleIdentifier!)")
|
||||
let accountsFolder = accountsURL!.appendingPathComponent("Accounts").absoluteString
|
||||
let accountsFolderPath = accountsFolder.suffix(from: accountsFolder.index(accountsFolder.startIndex, offsetBy: 7))
|
||||
AccountManager.shared = AccountManager(accountsFolder: String(accountsFolderPath))
|
||||
|
||||
AccountManager.shared = AccountManager()
|
||||
AppDefaults.shared = UserDefaults.init(suiteName: "group.\(Bundle.main.bundleIdentifier!)")!
|
||||
|
||||
registerBackgroundTasks()
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroup</key>
|
||||
<string>group.$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
<key>AppIdentifierPrefix</key>
|
||||
<string>$(AppIdentifierPrefix)</string>
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.ranchero.NetNewsWire.FeedRefresh</string>
|
||||
|
|
|
@ -6,5 +6,9 @@
|
|||
<array>
|
||||
<string>group.$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroup</key>
|
||||
<string>group.$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
<key>AppIdentifierPrefix</key>
|
||||
<string>$(AppIdentifierPrefix)</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
|
|
@ -6,5 +6,9 @@
|
|||
<array>
|
||||
<string>group.$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(ORGANIZATION_IDENTIFIER).NetNewsWire.iOS</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -23,11 +23,7 @@ class ShareViewController: SLComposeServiceViewController, ShareFolderPickerCont
|
|||
|
||||
override func viewDidLoad() {
|
||||
|
||||
let rootID = Bundle.main.bundleIdentifier!.replacingOccurrences(of: ".Share-Extension", with: "")
|
||||
let accountsURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.\(rootID)")
|
||||
let accountsFolder = accountsURL!.appendingPathComponent("Accounts").absoluteString
|
||||
let accountsFolderPath = accountsFolder.suffix(from: accountsFolder.index(accountsFolder.startIndex, offsetBy: 7))
|
||||
AccountManager.shared = AccountManager(accountsFolder: String(accountsFolderPath))
|
||||
AccountManager.shared = AccountManager()
|
||||
|
||||
pickerData = FlattenedAccountFolderPickerData()
|
||||
|
||||
|
|
Loading…
Reference in New Issue