Refactor how we do Secrets to work with the new Swift Package structure
This commit is contained in:
parent
7bd1ac2d89
commit
b724658528
|
@ -266,7 +266,7 @@ public final class RedditFeedProvider: FeedProvider {
|
|||
extension RedditFeedProvider: OAuth2SwiftProvider {
|
||||
|
||||
public static var oauth2Swift: OAuth2Swift {
|
||||
let oauth2 = OAuth2Swift(consumerKey: Secrets.redditConsumerKey,
|
||||
let oauth2 = OAuth2Swift(consumerKey: SecretsManager.provider.redditConsumerKey,
|
||||
consumerSecret: "",
|
||||
authorizeUrl: "https://www.reddit.com/api/v1/authorize.compact?",
|
||||
accessTokenUrl: "https://www.reddit.com/api/v1/access_token",
|
||||
|
@ -283,7 +283,7 @@ extension RedditFeedProvider: OAuth2SwiftProvider {
|
|||
let state = generateState(withLength: 20)
|
||||
let scope = "identity mysubreddits read"
|
||||
let params = [
|
||||
"client_id" : Secrets.redditConsumerKey,
|
||||
"client_id" : SecretsManager.provider.redditConsumerKey,
|
||||
"response_type" : "code",
|
||||
"state" : state,
|
||||
"redirect_uri" : "netnewswire://success",
|
||||
|
|
|
@ -74,8 +74,8 @@ public final class TwitterFeedProvider: FeedProvider {
|
|||
let tokenSecretCredentials = Credentials(type: .oauthAccessTokenSecret, username: screenName, secret: oauthTokenSecret)
|
||||
try? CredentialsManager.storeCredentials(tokenSecretCredentials, server: Self.server)
|
||||
|
||||
client = OAuthSwiftClient(consumerKey: Secrets.twitterConsumerKey,
|
||||
consumerSecret: Secrets.twitterConsumerSecret,
|
||||
client = OAuthSwiftClient(consumerKey: SecretsManager.provider.twitterConsumerKey,
|
||||
consumerSecret: SecretsManager.provider.twitterConsumerSecret,
|
||||
oauthToken: oauthToken,
|
||||
oauthTokenSecret: oauthTokenSecret,
|
||||
version: .oauth1)
|
||||
|
@ -92,8 +92,8 @@ public final class TwitterFeedProvider: FeedProvider {
|
|||
self.oauthToken = tokenCredentials.secret
|
||||
self.oauthTokenSecret = tokenSecretCredentials.secret
|
||||
|
||||
client = OAuthSwiftClient(consumerKey: Secrets.twitterConsumerKey,
|
||||
consumerSecret: Secrets.twitterConsumerSecret,
|
||||
client = OAuthSwiftClient(consumerKey: SecretsManager.provider.twitterConsumerKey,
|
||||
consumerSecret: SecretsManager.provider.twitterConsumerSecret,
|
||||
oauthToken: oauthToken,
|
||||
oauthTokenSecret: oauthTokenSecret,
|
||||
version: .oauth1)
|
||||
|
@ -286,8 +286,8 @@ extension TwitterFeedProvider: OAuth1SwiftProvider {
|
|||
|
||||
public static var oauth1Swift: OAuth1Swift {
|
||||
return OAuth1Swift(
|
||||
consumerKey: Secrets.twitterConsumerKey,
|
||||
consumerSecret: Secrets.twitterConsumerSecret,
|
||||
consumerKey: SecretsManager.provider.twitterConsumerKey,
|
||||
consumerSecret: SecretsManager.provider.twitterConsumerSecret,
|
||||
requestTokenUrl: "https://api.twitter.com/oauth/request_token",
|
||||
authorizeUrl: "https://api.twitter.com/oauth/authorize",
|
||||
accessTokenUrl: "https://api.twitter.com/oauth/access_token"
|
||||
|
|
|
@ -11,7 +11,6 @@ import Secrets
|
|||
|
||||
enum FeedWranglerConfig {
|
||||
static let pageSize = 100
|
||||
static let clientKey = Secrets.feedWranglerKey // Add FEED_WRANGLER_KEY = XYZ to SharedXcodeSettings/DeveloperSettings.xcconfig
|
||||
static let clientPath = "https://feedwrangler.net/api/v2/"
|
||||
static let clientURL = {
|
||||
URL(string: FeedWranglerConfig.clientPath)!
|
||||
|
|
|
@ -15,10 +15,10 @@ extension OAuthAuthorizationClient {
|
|||
/// Models private NetNewsWire client secrets.
|
||||
/// These placeholders are substitued 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: Secrets.feedlyClientId,
|
||||
return OAuthAuthorizationClient(id: SecretsManager.provider.feedlyClientId,
|
||||
redirectUri: "netnewswire://auth/feedly",
|
||||
state: nil,
|
||||
secret: Secrets.feedlyClientSecret)
|
||||
secret: SecretsManager.provider.feedlyClientSecret)
|
||||
}
|
||||
|
||||
static var feedlySandboxClient: OAuthAuthorizationClient {
|
||||
|
|
|
@ -30,7 +30,7 @@ public extension URLRequest {
|
|||
self.url = url.appendingQueryItems([
|
||||
URLQueryItem(name: "email", value: credentials.username),
|
||||
URLQueryItem(name: "password", value: credentials.secret),
|
||||
URLQueryItem(name: "client_key", value: FeedWranglerConfig.clientKey)
|
||||
URLQueryItem(name: "client_key", value: SecretsManager.provider.feedWranglerKey)
|
||||
])
|
||||
case .feedWranglerToken:
|
||||
self.url = url.appendingQueryItem(URLQueryItem(name: "access_token", value: credentials.secret))
|
||||
|
|
|
@ -14,6 +14,7 @@ import RSWeb
|
|||
import Account
|
||||
import RSCore
|
||||
import RSCoreResources
|
||||
import Secrets
|
||||
|
||||
// If we're not going to import Sparkle, provide dummy protocols to make it easy
|
||||
// for AppDelegate to comply
|
||||
|
@ -104,6 +105,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
|||
NSWindow.allowsAutomaticWindowTabbing = false
|
||||
super.init()
|
||||
|
||||
SecretsManager.provider = Secrets()
|
||||
AccountManager.shared = AccountManager(accountsFolder: Platform.dataSubfolder(forApplication: nil, folderName: "Accounts")!)
|
||||
FeedProviderManager.shared.delegate = ExtensionPointManager.shared
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import RSWeb
|
|||
import Account
|
||||
import BackgroundTasks
|
||||
import os.log
|
||||
import Secrets
|
||||
|
||||
var appDelegate: AppDelegate!
|
||||
|
||||
|
@ -60,6 +61,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|||
super.init()
|
||||
appDelegate = self
|
||||
|
||||
SecretsManager.provider = Secrets()
|
||||
let documentAccountURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let documentAccountsFolder = documentAccountURL.appendingPathComponent("Accounts").absoluteString
|
||||
let documentAccountsFolderPath = String(documentAccountsFolder.suffix(from: documentAccountsFolder.index(documentAccountsFolder.startIndex, offsetBy: 7)))
|
||||
|
|
|
@ -13,6 +13,7 @@ import Articles
|
|||
import RSWeb
|
||||
import Account
|
||||
import RSCore
|
||||
import Secrets
|
||||
|
||||
// If we're not going to import Sparkle, provide dummy protocols to make it easy
|
||||
// for AppDelegate to comply
|
||||
|
@ -70,6 +71,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
|||
override init() {
|
||||
super.init()
|
||||
|
||||
SecretsManager.provider = Secrets()
|
||||
AccountManager.shared = AccountManager(accountsFolder: Platform.dataSubfolder(forApplication: nil, folderName: "Accounts")!)
|
||||
FeedProviderManager.shared.delegate = ExtensionPointManager.shared
|
||||
|
||||
|
|
|
@ -444,6 +444,12 @@
|
|||
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; };
|
||||
51C452B42265141B00C03939 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C452B32265141B00C03939 /* WebKit.framework */; };
|
||||
51C452B82265178500C03939 /* styleSheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 51C452B72265178500C03939 /* styleSheet.css */; };
|
||||
51C4CFF024D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
|
||||
51C4CFF124D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
|
||||
51C4CFF224D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
|
||||
51C4CFF324D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
|
||||
51C4CFF424D37D1F00AF9874 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4CFEF24D37D1F00AF9874 /* Secrets.swift */; };
|
||||
51C4CFF624D37DD500AF9874 /* Secrets in Frameworks */ = {isa = PBXBuildFile; productRef = 51C4CFF524D37DD500AF9874 /* Secrets */; };
|
||||
51C65AFC24CCB2C9008EB3BD /* TimelineItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C65AFB24CCB2C9008EB3BD /* TimelineItems.swift */; };
|
||||
51C65AFD24CCB2C9008EB3BD /* TimelineItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C65AFB24CCB2C9008EB3BD /* TimelineItems.swift */; };
|
||||
51C9DE5823EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C9DE5723EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift */; };
|
||||
|
@ -1661,6 +1667,7 @@
|
|||
51C4528B2265095F00C03939 /* AddFolderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFolderViewController.swift; sourceTree = "<group>"; };
|
||||
51C452B32265141B00C03939 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
51C452B72265178500C03939 /* styleSheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = styleSheet.css; sourceTree = "<group>"; };
|
||||
51C4CFEF24D37D1F00AF9874 /* Secrets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = "<group>"; };
|
||||
51C65AFB24CCB2C9008EB3BD /* TimelineItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItems.swift; sourceTree = "<group>"; };
|
||||
51C9DE5723EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrapperScriptMessageHandler.swift; sourceTree = "<group>"; };
|
||||
51CD32A824D2CB25009ABAEF /* SyncDatabase */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SyncDatabase; sourceTree = "<group>"; };
|
||||
|
@ -2043,6 +2050,7 @@
|
|||
514C16DE24D2EF15009A3AFA /* RSTree in Frameworks */,
|
||||
65ED42DE235E74230081F399 /* Sparkle.framework in Frameworks */,
|
||||
65ED42D9235E740D0081F399 /* Sparkle.framework in Frameworks */,
|
||||
51C4CFF624D37DD500AF9874 /* Secrets in Frameworks */,
|
||||
51E4DAED2425F6940091EB5B /* CloudKit.framework in Frameworks */,
|
||||
514C16E124D2EF38009A3AFA /* RSCoreResources in Frameworks */,
|
||||
514C16CE24D2E63F009A3AFA /* Account in Frameworks */,
|
||||
|
@ -3190,6 +3198,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
842E45CD1ED8C308000A8B52 /* AppNotifications.swift */,
|
||||
51C4CFEF24D37D1F00AF9874 /* Secrets.swift */,
|
||||
511B9805237DCAC90028BCAA /* UserInfoKey.swift */,
|
||||
51C452AD2265102800C03939 /* Timeline */,
|
||||
84702AB31FA27AE8006B8943 /* Commands */,
|
||||
|
@ -3702,6 +3711,7 @@
|
|||
514C16CD24D2E63F009A3AFA /* Account */,
|
||||
514C16DD24D2EF15009A3AFA /* RSTree */,
|
||||
514C16E024D2EF38009A3AFA /* RSCoreResources */,
|
||||
51C4CFF524D37DD500AF9874 /* Secrets */,
|
||||
);
|
||||
productName = NetNewsWire;
|
||||
productReference = 849C64601ED37A5D003D8FC0 /* NetNewsWire.app */;
|
||||
|
@ -4420,6 +4430,7 @@
|
|||
51B80EB824BD1F8B00C6C32D /* ActivityViewController.swift in Sources */,
|
||||
51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */,
|
||||
51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */,
|
||||
51C4CFF324D37D1F00AF9874 /* Secrets.swift in Sources */,
|
||||
51B80EE124BD3E9600C6C32D /* FindInArticleActivity.swift in Sources */,
|
||||
6586A5F724B632F8002BCF4F /* SettingsDetailAccountModel.swift in Sources */,
|
||||
51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */,
|
||||
|
@ -4625,6 +4636,7 @@
|
|||
51B54A4324B5499B0014348B /* WebViewProvider.swift in Sources */,
|
||||
1799E6CE24C320D600511E91 /* InspectorModel.swift in Sources */,
|
||||
514E6C0024AD255D00AC6F6E /* PreviewArticles.swift in Sources */,
|
||||
51C4CFF424D37D1F00AF9874 /* Secrets.swift in Sources */,
|
||||
1729529524AA1CAA00D65E66 /* GeneralPreferencesView.swift in Sources */,
|
||||
1769E32724BC5B6C000E1E8E /* AddAccountModel.swift in Sources */,
|
||||
1729529424AA1CAA00D65E66 /* AdvancedPreferencesView.swift in Sources */,
|
||||
|
@ -4803,6 +4815,7 @@
|
|||
65ED403C235DEF6C0081F399 /* SingleLineTextFieldSizer.swift in Sources */,
|
||||
65ED403D235DEF6C0081F399 /* TimelineTableCellView.swift in Sources */,
|
||||
65ED403E235DEF6C0081F399 /* TimelineCellAppearance.swift in Sources */,
|
||||
51C4CFF124D37D1F00AF9874 /* Secrets.swift in Sources */,
|
||||
510C43F4243C11FE009F70C3 /* ExtensionPointAddTableCellView.swift in Sources */,
|
||||
65ED403F235DEF6C0081F399 /* ArticleRenderer.swift in Sources */,
|
||||
65ED4040235DEF6C0081F399 /* GeneralPrefencesViewController.swift in Sources */,
|
||||
|
@ -4888,6 +4901,7 @@
|
|||
5F323809231DF9F000706F6B /* VibrantTableViewCell.swift in Sources */,
|
||||
51FE10042345529D0056195D /* UserNotificationManager.swift in Sources */,
|
||||
519ED47C24488C6F007F8E94 /* ExtensionInspectorViewController.swift in Sources */,
|
||||
51C4CFF224D37D1F00AF9874 /* Secrets.swift in Sources */,
|
||||
51C452A022650A1900C03939 /* WebFeedIconDownloader.swift in Sources */,
|
||||
51C4529E22650A1900C03939 /* ImageDownloader.swift in Sources */,
|
||||
51A66685238075AE00CB272D /* AddWebFeedDefaultContainer.swift in Sources */,
|
||||
|
@ -5140,6 +5154,7 @@
|
|||
84B99C9D1FAE83C600ECDEDB /* DeleteCommand.swift in Sources */,
|
||||
849A97541ED9EAC0007D329B /* AddWebFeedWindowController.swift in Sources */,
|
||||
5144EA40227A37EC00D19003 /* ImportOPMLWindowController.swift in Sources */,
|
||||
51C4CFF024D37D1F00AF9874 /* Secrets.swift in Sources */,
|
||||
849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */,
|
||||
51333D1624685D2E00EB5C91 /* AddRedditFeedWindowController.swift in Sources */,
|
||||
84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */,
|
||||
|
@ -5782,6 +5797,10 @@
|
|||
package = 510ECA4024D1DCD0001C31A6 /* XCRemoteSwiftPackageReference "RSTree" */;
|
||||
productName = RSTree;
|
||||
};
|
||||
51C4CFF524D37DD500AF9874 /* Secrets */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = Secrets;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 849C64581ED37A5D003D8FC0 /* Project object */;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Script"
|
||||
scriptText = ""${PROJECT_DIR}/buildscripts/updateSecrets.sh" ">
|
||||
scriptText = ""${PROJECT_DIR}/buildscripts/updateSecrets.sh" 2>&1 ">
|
||||
<EnvironmentBuildable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
|
|
|
@ -17,7 +17,6 @@ let package = Package(
|
|||
name: "Secrets",
|
||||
dependencies: [
|
||||
.product(name: "OAuthSwift", package: "OAuthSwift"),
|
||||
],
|
||||
exclude: ["Secrets.swift.gyb"]),
|
||||
]),
|
||||
]
|
||||
)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
//
|
||||
// SecretsManager.swift
|
||||
//
|
||||
//
|
||||
// Created by Maurice Parker on 7/30/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class SecretsManager {
|
||||
public static var provider: SecretsProvider!
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// SecretsProvider.swift
|
||||
//
|
||||
//
|
||||
// Created by Maurice Parker on 7/30/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol SecretsProvider {
|
||||
var feedWranglerKey: String { get }
|
||||
var mercuryClientId: String { get }
|
||||
var mercuryClientSecret: String { get }
|
||||
var feedlyClientId: String { get }
|
||||
var feedlyClientSecret: String { get }
|
||||
var twitterConsumerKey: String { get }
|
||||
var twitterConsumerSecret: String { get }
|
||||
var redditConsumerKey: String { get }
|
||||
}
|
|
@ -38,8 +38,8 @@ class ArticleExtractor {
|
|||
self.articleLink = articleLink
|
||||
|
||||
let clientURL = "https://extract.feedbin.com/parser"
|
||||
let username = Secrets.mercuryClientId
|
||||
let signiture = articleLink.hmacUsingSHA1(key: Secrets.mercuryClientSecret)
|
||||
let username = SecretsManager.provider.mercuryClientId
|
||||
let signiture = articleLink.hmacUsingSHA1(key: SecretsManager.provider.mercuryClientSecret)
|
||||
|
||||
if let base64URL = articleLink.data(using: .utf8)?.base64EncodedString() {
|
||||
let fullURL = "\(clientURL)/\(username)/\(signiture)?base64_url=\(base64URL)"
|
||||
|
|
|
@ -17,10 +17,12 @@ def snake_to_camel(snake_str):
|
|||
|
||||
salt = [ord(byte) for byte in os.urandom(64)]
|
||||
}%
|
||||
public enum Secrets {
|
||||
import Secrets
|
||||
|
||||
public struct Secrets: SecretsProvider {
|
||||
% for secret in secrets:
|
||||
|
||||
public static var ${snake_to_camel(secret)}: String {
|
||||
public var ${snake_to_camel(secret)}: String {
|
||||
let encoded: [UInt8] = [
|
||||
% for chunk in chunks(encode(os.environ.get(secret) or "", salt), 8):
|
||||
${"".join(["0x%02x, " % byte for byte in chunk])}
|
||||
|
@ -34,17 +36,14 @@ public enum Secrets {
|
|||
%{
|
||||
# custom example: static let myVariable = "${os.environ.get('MY_CUSTOM_VARIABLE')}"
|
||||
}%
|
||||
}
|
||||
|
||||
private extension Secrets {
|
||||
|
||||
private static let salt: [UInt8] = [
|
||||
private let salt: [UInt8] = [
|
||||
% for chunk in chunks(salt, 8):
|
||||
${"".join(["0x%02x, " % byte for byte in chunk])}
|
||||
% end
|
||||
]
|
||||
|
||||
private static func decode(_ encoded: [UInt8], salt: [UInt8]) -> String {
|
||||
private func decode(_ encoded: [UInt8], salt: [UInt8]) -> String {
|
||||
String(decoding: encoded.enumerated().map { (offset, element) in
|
||||
element ^ salt[offset % salt.count]
|
||||
}, as: UTF8.self)
|
|
@ -12,6 +12,7 @@ import RSWeb
|
|||
import Account
|
||||
import BackgroundTasks
|
||||
import os.log
|
||||
import Secrets
|
||||
|
||||
var appDelegate: AppDelegate!
|
||||
|
||||
|
@ -60,6 +61,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|||
super.init()
|
||||
appDelegate = self
|
||||
|
||||
SecretsManager.provider = Secrets()
|
||||
let documentAccountURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let documentAccountsFolder = documentAccountURL.appendingPathComponent("Accounts").absoluteString
|
||||
let documentAccountsFolderPath = String(documentAccountsFolder.suffix(from: documentAccountsFolder.index(documentAccountsFolder.startIndex, offsetBy: 7)))
|
||||
|
|
Loading…
Reference in New Issue