Get rid of SecretsProvider protocol. Stop passing secretsProvider around — just use SecretKey.whatever static properties.

This commit is contained in:
Brent Simmons 2024-07-07 15:38:45 -07:00
parent 7d40924509
commit 445306ef2a
25 changed files with 61 additions and 81 deletions

View File

@ -102,14 +102,13 @@ import Sparkle
#endif
private var themeImportPath: String?
private let secretsProvider = Secrets()
private let accountManager: AccountManager
override init() {
NSWindow.allowsAutomaticWindowTabbing = false
self.accountManager = AccountManager(accountsFolder: Platform.dataSubfolder(forApplication: nil, folderName: "Accounts")!, secretsProvider: secretsProvider)
self.accountManager = AccountManager(accountsFolder: Platform.dataSubfolder(forApplication: nil, folderName: "Accounts")!)
AccountManager.shared = self.accountManager
super.init()

View File

@ -13,6 +13,7 @@ import Account
import Core
import AppKitExtras
import ArticleExtractor
import Secrets
enum TimelineSourceMode {
case regular, search
@ -1277,8 +1278,7 @@ private extension MainWindowController {
}
func startArticleExtractorForCurrentLink() {
let secrets = Secrets()
if let link = currentLink, let extractor = ArticleExtractor(link, clientID: secrets.mercuryClientID, clientSecret: secrets.mercuryClientSecret) {
if let link = currentLink, let extractor = ArticleExtractor(link, clientID: SecretKey.mercuryClientID, clientSecret: SecretKey.mercuryClientSecret) {
extractor.delegate = self
extractor.process()
articleExtractor = extractor

View File

@ -88,7 +88,7 @@ final class AccountsFeedbinWindowController: NSWindowController {
var validatedCredentials: Credentials?
do {
validatedCredentials = try await Account.validateCredentials(type: .feedbin, credentials: credentials, secretsProvider: Secrets())
validatedCredentials = try await Account.validateCredentials(type: .feedbin, credentials: credentials)
} catch {
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
validationDidThrow = true

View File

@ -85,7 +85,7 @@ class AccountsNewsBlurWindowController: NSWindowController {
var validatedCredentials: Credentials?
do {
validatedCredentials = try await Account.validateCredentials(type: .newsBlur, credentials: credentials, secretsProvider: Secrets())
validatedCredentials = try await Account.validateCredentials(type: .newsBlur, credentials: credentials)
} catch {
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
validationDidThrow = true

View File

@ -185,7 +185,7 @@ extension AccountsPreferencesViewController: AccountsPreferencesAddAccountDelega
addAccountWindowController = accountsReaderAPIWindowController
case .feedly:
let addAccount = FeedlyOAuthAccountAuthorizationOperation(secretsProvider: Secrets())
let addAccount = FeedlyOAuthAccountAuthorizationOperation()
addAccount.delegate = self
addAccount.presentationAnchor = self.view.window!
runAwaitingFeedlyLoginAlertModal(forLifetimeOf: addAccount)

View File

@ -141,7 +141,7 @@ class AccountsReaderAPIWindowController: NSWindowController {
var validatedCredentials: Credentials?
do {
validatedCredentials = try await Account.validateCredentials(type: accountType, credentials: credentials, endpoint: apiURL, secretsProvider: Secrets())
validatedCredentials = try await Account.validateCredentials(type: accountType, credentials: credentials, endpoint: apiURL)
} catch {
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
validationDidThrow = true

View File

@ -270,7 +270,7 @@ public enum FetchType {
return delegate.refreshProgress
}
init(dataFolder: String, type: AccountType, accountID: String, secretsProvider: SecretsProvider, transport: Transport? = nil) {
init(dataFolder: String, type: AccountType, accountID: String, transport: Transport? = nil) {
switch type {
case .onMyMac:
self.delegate = LocalAccountDelegate()
@ -279,17 +279,17 @@ public enum FetchType {
case .feedbin:
self.delegate = FeedbinAccountDelegate(dataFolder: dataFolder, transport: transport)
case .feedly:
self.delegate = FeedlyAccountDelegate(dataFolder: dataFolder, transport: transport, api: FeedlyAccountDelegate.environment, secretsProvider: secretsProvider)
self.delegate = FeedlyAccountDelegate(dataFolder: dataFolder, transport: transport, api: FeedlyAccountDelegate.environment)
case .newsBlur:
self.delegate = NewsBlurAccountDelegate(dataFolder: dataFolder, transport: transport)
case .freshRSS:
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .freshRSS, secretsProvider: secretsProvider)
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .freshRSS)
case .inoreader:
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .inoreader, secretsProvider: secretsProvider)
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .inoreader)
case .bazQux:
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .bazQux, secretsProvider: secretsProvider)
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .bazQux)
case .theOldReader:
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .theOldReader, secretsProvider: secretsProvider)
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport, variant: .theOldReader)
}
self.delegate.accountMetadata = metadata
@ -371,18 +371,18 @@ public enum FetchType {
try CredentialsManager.removeCredentials(type: type, server: server, username: username)
}
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, secretsProvider: SecretsProvider) async throws -> Credentials? {
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil) async throws -> Credentials? {
switch type {
case .feedbin:
return try await FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, secretsProvider: secretsProvider)
return try await FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint)
case .newsBlur:
return try await NewsBlurAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, secretsProvider: secretsProvider)
return try await NewsBlurAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint)
case .freshRSS, .inoreader, .bazQux, .theOldReader:
return try await ReaderAPIAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, secretsProvider: secretsProvider)
return try await ReaderAPIAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint)
default:
return nil

View File

@ -51,7 +51,7 @@ import Secrets
func accountWillBeDeleted(_ account: Account)
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials?
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials?
/// Suspend all network activity
func suspendNetwork()

View File

@ -484,7 +484,7 @@ enum CloudKitAccountDelegateError: LocalizedError {
articlesZone.resetChangeToken()
}
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials? {
return nil
}

View File

@ -395,7 +395,7 @@ public enum FeedbinAccountDelegateError: String, Error {
func accountWillBeDeleted(_ account: Account) {
}
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials? {
let caller = FeedbinAPICaller(transport: transport)
caller.credentials = credentials

View File

@ -73,14 +73,14 @@ final class FeedlyAccountDelegate: AccountDelegate {
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Feedly")
private let syncDatabase: SyncDatabase
init(dataFolder: String, transport: Transport?, api: FeedlyAPICaller.API, secretsProvider: SecretsProvider) {
init(dataFolder: String, transport: Transport?, api: FeedlyAPICaller.API) {
// Many operations have their own operation queues, such as the sync all operation.
// Making this a serial queue at this higher level of abstraction means we can ensure,
// for example, a `FeedlyRefreshAccessTokenOperation` occurs before a `FeedlySyncAllOperation`,
// improving our ability to debug, reason about and predict the behaviour of the code.
if let transport = transport {
self.caller = FeedlyAPICaller(transport: transport, api: api, secretsProvider: secretsProvider)
self.caller = FeedlyAPICaller(transport: transport, api: api)
} else {
@ -95,12 +95,12 @@ final class FeedlyAccountDelegate: AccountDelegate {
sessionConfiguration.httpAdditionalHeaders = UserAgent.headers
let session = URLSession(configuration: sessionConfiguration)
self.caller = FeedlyAPICaller(transport: session, api: api, secretsProvider: secretsProvider)
self.caller = FeedlyAPICaller(transport: session, api: api)
}
let databasePath = (dataFolder as NSString).appendingPathComponent("Sync.sqlite3")
self.syncDatabase = SyncDatabase(databasePath: databasePath)
self.oauthAuthorizationClient = api.oauthAuthorizationClient(secretsProvider: secretsProvider)
self.oauthAuthorizationClient = api.oauthAuthorizationClient()
self.caller.delegate = self
}
@ -374,7 +374,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
}
}
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials? {
assertionFailure("An `account` instance should refresh the access token first instead.")
return credentials
@ -999,17 +999,15 @@ public enum FeedlyOAuthAccountAuthorizationOperationError: LocalizedError {
private let oauthClient: OAuthAuthorizationClient
private var session: ASWebAuthenticationSession?
private let secretsProvider: SecretsProvider
public init(secretsProvider: SecretsProvider) {
self.secretsProvider = secretsProvider
self.oauthClient = FeedlyAPICaller.API.cloud.oauthAuthorizationClient(secretsProvider: secretsProvider)
override public init() {
self.oauthClient = FeedlyAPICaller.API.cloud.oauthAuthorizationClient()
}
public func run() {
assert(presentationAnchor != nil, "\(self) outlived presentation anchor.")
let request = FeedlyAPICaller.oauthAuthorizationCodeGrantRequest(secretsProvider: secretsProvider)
let request = FeedlyAPICaller.oauthAuthorizationCodeGrantRequest()
guard let url = request.url else {
return DispatchQueue.main.async {
@ -1073,7 +1071,7 @@ public enum FeedlyOAuthAccountAuthorizationOperationError: LocalizedError {
let response = try OAuthAuthorizationResponse(url: url, client: self.oauthClient)
let tokenResponse = try await FeedlyAPICaller.requestOAuthAccessToken(with: response, transport: URLSession.webserviceTransport(), secretsProvider: secretsProvider)
let tokenResponse = try await FeedlyAPICaller.requestOAuthAccessToken(with: response, transport: URLSession.webserviceTransport())
saveAccount(for: tokenResponse)
} catch is ASWebAuthenticationSessionError {

View File

@ -158,7 +158,7 @@ final class LocalAccountDelegate: AccountDelegate {
func accountWillBeDeleted(_ account: Account) {
}
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials? {
return nil
}

View File

@ -430,7 +430,7 @@ final class NewsBlurAccountDelegate: AccountDelegate {
}
}
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials? {
let caller = NewsBlurAPICaller(transport: transport)
caller.credentials = credentials

View File

@ -54,7 +54,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
var refreshProgress = DownloadProgress(numberOfTasks: 0)
init(dataFolder: String, transport: Transport?, variant: ReaderAPIVariant, secretsProvider: SecretsProvider) {
init(dataFolder: String, transport: Transport?, variant: ReaderAPIVariant) {
let databasePath = (dataFolder as NSString).appendingPathComponent("Sync.sqlite3")
self.database = SyncDatabase(databasePath: databasePath)
@ -62,7 +62,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
self.variant = variant
if transport != nil {
self.caller = ReaderAPICaller(transport: transport!, secretsProvider: secretsProvider)
self.caller = ReaderAPICaller(transport: transport!)
} else {
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.requestCachePolicy = .reloadIgnoringLocalCacheData
@ -74,7 +74,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
sessionConfiguration.urlCache = nil
sessionConfiguration.httpAdditionalHeaders = UserAgent.headers
self.caller = ReaderAPICaller(transport: URLSession(configuration: sessionConfiguration), secretsProvider: secretsProvider)
self.caller = ReaderAPICaller(transport: URLSession(configuration: sessionConfiguration))
}
caller.delegate = self
@ -458,13 +458,13 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
func accountWillBeDeleted(_ account: Account) {
}
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?) async throws -> Credentials? {
guard let endpoint else {
throw TransportError.noURL
}
let caller = ReaderAPICaller(transport: transport, secretsProvider: secretsProvider)
let caller = ReaderAPICaller(transport: transport)
caller.credentials = credentials
return try await caller.validateCredentials(endpoint: endpoint)

View File

@ -27,8 +27,6 @@ import Secrets
private let defaultAccountFolderName = "OnMyMac"
private let defaultAccountIdentifier = "OnMyMac"
private let secretsProvider: SecretsProvider
public var isSuspended = false
public var isUnreadCountsInitialized: Bool {
for account in activeAccounts {
@ -94,10 +92,9 @@ import Secrets
return CombinedRefreshProgress(downloadProgressArray: downloadProgressArray)
}
public init(accountsFolder: String, secretsProvider: SecretsProvider) {
public init(accountsFolder: String) {
self.accountsFolder = accountsFolder
self.secretsProvider = secretsProvider
// The local "On My Mac" account must always exist, even if it's empty.
let localAccountFolder = (accountsFolder as NSString).appendingPathComponent("OnMyMac")
@ -109,7 +106,7 @@ import Secrets
abort()
}
defaultAccount = Account(dataFolder: localAccountFolder, type: .onMyMac, accountID: defaultAccountIdentifier, secretsProvider: secretsProvider)
defaultAccount = Account(dataFolder: localAccountFolder, type: .onMyMac, accountID: defaultAccountIdentifier)
accountsDictionary[defaultAccount.accountID] = defaultAccount
readAccountsFromDisk()
@ -136,7 +133,7 @@ import Secrets
abort()
}
let account = Account(dataFolder: accountFolder, type: type, accountID: accountID, secretsProvider: secretsProvider)
let account = Account(dataFolder: accountFolder, type: type, accountID: accountID)
accountsDictionary[accountID] = account
var userInfo = [String: Any]()
@ -375,7 +372,7 @@ private extension AccountManager {
}
func loadAccount(_ accountSpecifier: AccountSpecifier) -> Account? {
return Account(dataFolder: accountSpecifier.folderPath, type: accountSpecifier.type, accountID: accountSpecifier.identifier, secretsProvider: secretsProvider)
return Account(dataFolder: accountSpecifier.folderPath, type: accountSpecifier.type, accountID: accountSpecifier.identifier)
}
func loadAccount(_ filename: String) -> Account? {

View File

@ -37,12 +37,12 @@ public protocol FeedlyAPICallerDelegate: AnyObject {
return components
}
public func oauthAuthorizationClient(secretsProvider: SecretsProvider) -> OAuthAuthorizationClient {
public func oauthAuthorizationClient() -> OAuthAuthorizationClient {
switch self {
case .sandbox:
return .feedlySandboxClient
case .cloud:
return OAuthAuthorizationClient.feedlyCloudClient(secretsProvider: secretsProvider)
return OAuthAuthorizationClient.feedlyCloudClient()
}
}
}
@ -50,13 +50,11 @@ public protocol FeedlyAPICallerDelegate: AnyObject {
private let transport: Transport
private let baseURLComponents: URLComponents
private let uriComponentAllowed: CharacterSet
private let secretsProvider: SecretsProvider
private let api: FeedlyAPICaller.API
public init(transport: Transport, api: API, secretsProvider: SecretsProvider) {
public init(transport: Transport, api: API) {
self.transport = transport
self.baseURLComponents = api.baseUrlComponents
self.secretsProvider = secretsProvider
self.api = api
var urlHostAllowed = CharacterSet.urlHostAllowed
@ -556,8 +554,8 @@ extension FeedlyAPICaller {
private static let oauthAuthorizationGrantScope = "https://cloud.feedly.com/subscriptions"
public static func oauthAuthorizationCodeGrantRequest(secretsProvider: SecretsProvider) -> URLRequest {
let client = API.cloud.oauthAuthorizationClient(secretsProvider: secretsProvider)
public static func oauthAuthorizationCodeGrantRequest() -> URLRequest {
let client = API.cloud.oauthAuthorizationClient()
let authorizationRequest = OAuthAuthorizationRequest(clientID: client.id,
redirectURI: client.redirectURI,
scope: oauthAuthorizationGrantScope,
@ -566,13 +564,13 @@ extension FeedlyAPICaller {
return FeedlyAPICaller.authorizationCodeURLRequest(for: authorizationRequest, baseUrlComponents: baseURLComponents)
}
public static func requestOAuthAccessToken(with response: OAuthAuthorizationResponse, transport: any Web.Transport, secretsProvider: any Secrets.SecretsProvider) async throws -> OAuthAuthorizationGrant {
public static func requestOAuthAccessToken(with response: OAuthAuthorizationResponse, transport: any Web.Transport) async throws -> OAuthAuthorizationGrant {
let client = API.cloud.oauthAuthorizationClient(secretsProvider: secretsProvider)
let client = API.cloud.oauthAuthorizationClient()
let request = OAuthAccessTokenRequest(authorizationResponse: response,
scope: oauthAuthorizationGrantScope,
client: client)
let caller = FeedlyAPICaller(transport: transport, api: .cloud, secretsProvider: secretsProvider)
let caller = FeedlyAPICaller(transport: transport, api: .cloud)
let response = try await caller.requestAccessToken(request)
let accessToken = Credentials(type: .oauthAccessToken, username: response.id, secret: response.accessToken)

View File

@ -11,14 +11,14 @@ import Secrets
public extension OAuthAuthorizationClient {
static func feedlyCloudClient(secretsProvider: SecretsProvider) -> OAuthAuthorizationClient {
static func feedlyCloudClient() -> OAuthAuthorizationClient {
/// Models private NetNewsWire client secrets.
/// These placeholders are substituted at build time using a Run Script phase with build settings.
/// https://developer.feedly.com/v3/auth/#authenticating-a-user-and-obtaining-an-auth-code
return OAuthAuthorizationClient(id: secretsProvider.feedlyClientID,
return OAuthAuthorizationClient(id: SecretKey.feedlyClientID,
redirectURI: "netnewswire://auth/feedly",
state: nil,
secret: secretsProvider.feedlyClientSecret)
secret: SecretKey.feedlyClientSecret)
}
static var feedlySandboxClient: OAuthAuthorizationClient {

View File

@ -69,7 +69,6 @@ public enum CreateReaderAPISubscriptionResult: Sendable {
}
private var transport: Transport!
private let secretsProvider: SecretsProvider
private let uriComponentAllowed: CharacterSet
private var accessToken: String?
@ -86,10 +85,9 @@ public enum CreateReaderAPISubscriptionResult: Sendable {
}
/// The delegate should be set in a subsequent call.
public init(transport: Transport, secretsProvider: SecretsProvider) {
public init(transport: Transport) {
self.transport = transport
self.secretsProvider = secretsProvider
var urlHostAllowed = CharacterSet.urlHostAllowed
urlHostAllowed.remove("+")
@ -543,8 +541,8 @@ private extension ReaderAPICaller {
func addVariantHeaders(_ request: inout URLRequest) {
if variant == .inoreader {
request.addValue(secretsProvider.inoreaderAppID, forHTTPHeaderField: "AppId")
request.addValue(secretsProvider.inoreaderAppKey, forHTTPHeaderField: "AppKey")
request.addValue(SecretKey.inoreaderAppID, forHTTPHeaderField: "AppId")
request.addValue(SecretKey.inoreaderAppKey, forHTTPHeaderField: "AppKey")
}
}

View File

@ -263,8 +263,6 @@
51C452AC22650FD200C03939 /* AppNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842E45CD1ED8C308000A8B52 /* AppNotifications.swift */; };
51C452AE2265104D00C03939 /* ArticleStringFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97731ED9EC04007D329B /* ArticleStringFormatter.swift */; };
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; };
51C4CFF024D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
51C4CFF224D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
51C4CFF624D37DD500AF9874 /* Secrets in Frameworks */ = {isa = PBXBuildFile; productRef = 51C4CFF524D37DD500AF9874 /* Secrets */; };
51C9DE5823EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C9DE5723EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift */; };
51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51CE1C0823621EDA005548FC /* RefreshProgressView.xib */; };
@ -938,7 +936,6 @@
51C452822265093600C03939 /* Add.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Add.storyboard; sourceTree = "<group>"; };
51C452842265093600C03939 /* AddFeedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFeedViewController.swift; sourceTree = "<group>"; };
51C4528B2265095F00C03939 /* AddFolderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFolderViewController.swift; sourceTree = "<group>"; };
51C4CFEF24D37D1F00AF9874 /* Secrets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = "<group>"; };
51C9DE5723EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrapperScriptMessageHandler.swift; sourceTree = "<group>"; };
51CE1C0823621EDA005548FC /* RefreshProgressView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RefreshProgressView.xib; sourceTree = "<group>"; };
51CE1C0A23622006005548FC /* RefreshProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshProgressView.swift; sourceTree = "<group>"; };
@ -2115,7 +2112,6 @@
children = (
84DC5FFD2BCE37A300F04682 /* AppDelegate+Shared.swift */,
842E45CD1ED8C308000A8B52 /* AppNotifications.swift */,
51C4CFEF24D37D1F00AF9874 /* Secrets.swift */,
511B9805237DCAC90028BCAA /* UserInfoKey.swift */,
844933D12BA953590068AC51 /* ArticlePathInfo.swift */,
8454C3F2263F2D8700E3F9C7 /* IconImageCache.swift */,
@ -3327,7 +3323,6 @@
51C45294226509C800C03939 /* SearchFeedDelegate.swift in Sources */,
5F323809231DF9F000706F6B /* VibrantTableViewCell.swift in Sources */,
51FE10042345529D0056195D /* UserNotificationManager.swift in Sources */,
51C4CFF224D37D1F00AF9874 /* Secrets.swift in Sources */,
845122712B8CEA9100480DB0 /* SidebarItemIdentifier.swift in Sources */,
51A66685238075AE00CB272D /* AddFeedDefaultContainer.swift in Sources */,
176813E92564BAE200D98635 /* WidgetDeepLinks.swift in Sources */,
@ -3555,7 +3550,6 @@
849A97541ED9EAC0007D329B /* AddFeedWindowController.swift in Sources */,
5144EA40227A37EC00D19003 /* ImportOPMLWindowController.swift in Sources */,
178A9F9D2549449F00AB7E9D /* AddAccountsView.swift in Sources */,
51C4CFF024D37D1F00AF9874 /* Secrets.swift in Sources */,
849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */,
84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */,
D5E4CC64202C1AC1009B4FFC /* ScriptingMainWindowController.swift in Sources */,

View File

@ -30,8 +30,6 @@ class FeedbinAccountViewController: UITableViewController {
weak var account: Account?
weak var delegate: AddAccountDismissDelegate?
var secretsProvider: SecretsProvider!
override func viewDidLoad() {
super.viewDidLoad()
setupFooter()
@ -129,7 +127,7 @@ class FeedbinAccountViewController: UITableViewController {
var validatedCredentials: Credentials?
do {
validatedCredentials = try await Account.validateCredentials(type: .feedbin, credentials: credentials, secretsProvider: Secrets())
validatedCredentials = try await Account.validateCredentials(type: .feedbin, credentials: credentials)
} catch {
self.showError(error.localizedDescription)
validationDidThrow = true

View File

@ -112,7 +112,7 @@ class NewsBlurAccountViewController: UITableViewController {
var validatedCredentials: Credentials?
do {
validatedCredentials = try await Account.validateCredentials(type: .newsBlur, credentials: credentials, secretsProvider: Secrets())
validatedCredentials = try await Account.validateCredentials(type: .newsBlur, credentials: credentials)
} catch {
self.showError(error.localizedDescription)
validationDidThrow = true

View File

@ -165,7 +165,7 @@ class ReaderAPIAccountViewController: UITableViewController {
var validatedCredentials: Credentials?
do {
validatedCredentials = try await Account.validateCredentials(type: type, credentials: credentials, endpoint: url, secretsProvider: Secrets())
validatedCredentials = try await Account.validateCredentials(type: type, credentials: credentials, endpoint: url)
} catch {
self.showError(error.localizedDescription)
validationDidThrow = true

View File

@ -56,14 +56,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
let accountManager: AccountManager
private var secretsProvider = Secrets()
override init() {
let documentFolder = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let documentAccountsFolder = documentFolder.appendingPathComponent("Accounts").absoluteString
let documentAccountsFolderPath = String(documentAccountsFolder.suffix(from: documentAccountsFolder.index(documentAccountsFolder.startIndex, offsetBy: 7)))
self.accountManager = AccountManager(accountsFolder: documentAccountsFolderPath, secretsProvider: secretsProvider)
self.accountManager = AccountManager(accountsFolder: documentAccountsFolderPath)
AccountManager.shared = accountManager
super.init()

View File

@ -16,6 +16,7 @@ import Core
import ArticleExtractor
import Images
import Web
import Secrets
protocol WebViewControllerDelegate: AnyObject {
@ -696,8 +697,7 @@ private extension WebViewController {
func startArticleExtractor() {
guard articleExtractor == nil else { return }
let secrets = Secrets()
if let link = article?.preferredLink, let extractor = ArticleExtractor(link, clientID: secrets.mercuryClientID, clientSecret: secrets.mercuryClientSecret) {
if let link = article?.preferredLink, let extractor = ArticleExtractor(link, clientID: SecretKey.mercuryClientID, clientSecret: SecretKey.mercuryClientSecret) {
extractor.delegate = self
extractor.process()
articleExtractor = extractor

View File

@ -200,7 +200,7 @@ final class AddAccountViewController: UITableViewController, AddAccountDismissDe
addViewController.delegate = self
present(navController, animated: true)
case .feedly:
let addAccount = FeedlyOAuthAccountAuthorizationOperation(secretsProvider: Secrets())
let addAccount = FeedlyOAuthAccountAuthorizationOperation()
addAccount.delegate = self
addAccount.presentationAnchor = self.view.window!
feedlyAddAccountOperation = addAccount