Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Patreon linking #1613

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 177 additions & 29 deletions PVLibrary/PVLibrary.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B31ACB33294DBBBC002D7E2F"
BuildableName = "PVPatreonTests.xctest"
BlueprintName = "PVPatreonTests"
ReferencedContainer = "container:PVLibrary.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
91 changes: 91 additions & 0 deletions PVLibrary/PVLibrary/Keychain/Keychain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// Keychain.swift
// AltStore
//
// Created by Riley Testut on 6/4/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//

import Foundation
import KeychainAccess

//import AltSign

@propertyWrapper
public struct KeychainItem<Value>
{
public let key: String

public var wrappedValue: Value? {
get {
switch Value.self
{
case is Data.Type: return try? Keychain.shared.keychain.getData(self.key) as? Value
case is String.Type: return try? Keychain.shared.keychain.getString(self.key) as? Value
default: return nil
}
}
set {
switch Value.self
{
case is Data.Type: Keychain.shared.keychain[data: self.key] = newValue as? Data
case is String.Type: Keychain.shared.keychain[self.key] = newValue as? String
default: break
}
}
}

public init(key: String)
{
self.key = key
}
}

public class Keychain
{
public static let shared = Keychain()

fileprivate let keychain = KeychainAccess.Keychain(service: "org.provenance-emu.provenance").accessibility(.afterFirstUnlock).synchronizable(true)

// @KeychainItem(key: "appleIDEmailAddress")
// public var appleIDEmailAddress: String?
//
// @KeychainItem(key: "appleIDPassword")
// public var appleIDPassword: String?
//
// @KeychainItem(key: "signingCertificatePrivateKey")
// public var signingCertificatePrivateKey: Data?
//
// @KeychainItem(key: "signingCertificateSerialNumber")
// public var signingCertificateSerialNumber: String?
//
// @KeychainItem(key: "signingCertificate")
// public var signingCertificate: Data?
//
// @KeychainItem(key: "signingCertificatePassword")
// public var signingCertificatePassword: String?

@KeychainItem(key: "patreonAccessToken")
public var patreonAccessToken: String?

@KeychainItem(key: "patreonRefreshToken")
public var patreonRefreshToken: String?

@KeychainItem(key: "patreonCreatorAccessToken")
public var patreonCreatorAccessToken: String?

@KeychainItem(key: "patreonAccountID")
public var patreonAccountID: String?

private init()
{
}

public func reset()
{
// self.appleIDEmailAddress = nil
// self.appleIDPassword = nil
// self.signingCertificatePrivateKey = nil
// self.signingCertificateSerialNumber = nil
}
}
38 changes: 38 additions & 0 deletions PVLibrary/PVPatreon/Benefit.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// Benefit.swift
// AltStore
//
// Created by Riley Testut on 8/21/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//

import Foundation

public enum PVPatreonBenefitType: String {
case betaAccess = "7585304"
case credit = "8490206"
}

@available(iOS 12.0, tvOS 12.0, *)
extension PatreonAPI
{
struct BenefitResponse: Decodable
{
var id: String
}
}

@available(iOS 12.0, tvOS 12.0, *)
public struct Benefit: Hashable
{
public var type: PVPatreonBenefitType

init?(response: PatreonAPI.BenefitResponse)
{
guard let type = PVPatreonBenefitType(rawValue: response.id) else {
ELOG("Unknown benefit id \(response.id)")
return nil
}
self.type = type
}
}
29 changes: 29 additions & 0 deletions PVLibrary/PVPatreon/Campaign.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// Campaign.swift
// AltStore
//
// Created by Riley Testut on 8/21/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//

import Foundation

@available(iOS 12.0, tvOS 12.0, *)
extension PatreonAPI
{
struct CampaignResponse: Decodable
{
var id: String
}
}

@available(iOS 12.0, tvOS 12.0, *)
public struct Campaign
{
public var identifier: String

init(response: PatreonAPI.CampaignResponse)
{
self.identifier = response.id
}
}
36 changes: 36 additions & 0 deletions PVLibrary/PVPatreon/Consts.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// Consts.swift
// PVPatreon
//
// Created by Joseph Mattiello on 12/17/22.
// Copyright © 2022 Provenance Emu. All rights reserved.
//

import Foundation

private class PVPatreonHandle: NSObject { }
internal enum Const {
static let bundle: Bundle = Bundle(for: PVPatreonHandle.self)
static let patreon: [String:String] = { bundle.infoDictionary!["PATREON"] as! [String:String] }()
static func string(forKey key: String) -> String {
patreon[key] ?? ""
}
static internal let clientID: String = {
string(forKey:"CLIENT_ID")
}()
static internal let clientSecret: String = {
string(forKey:"CLIENT_SECRET")
}()
static internal let campaignID: String = {
string(forKey:"CAMPAIGN_ID")
}()
static internal let redirectURL: String = {
string(forKey:"REDIRECT_URL")
}()
static internal let callbackURLScheme: String = {
string(forKey:"CALLBACK_URL_SCHEME")
}()
static internal let keychainService: String = {
bundle.infoDictionary!["KEYCHAIN_SERIVCE"] as! String
}()
}
21 changes: 21 additions & 0 deletions PVLibrary/PVPatreon/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KEYCHAIN_SERIVCE</key>
<string>$(KEYCHAIN_SERIVCE)</string>
<key>PATREON</key>
<dict>
<key>CALLBACK_URL_SCHEME</key>
<string>$(CALLBACK_URL_SCHEME)</string>
<key>REDIRECT_URL</key>
<string>$(REDIRECT_URL)</string>
<key>CLIENT_ID</key>
<string>$(CLIENT_ID)</string>
<key>CLIENT_SECRET</key>
<string>$(CLIENT_SECRET)</string>
<key>CAMPAIGN_ID</key>
<string>$(CAMPAIGN_ID)</string>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// PatreonAPI+ASWebAuthenticationPresentationContextProviding.swift
// PVPatreon
//
// Created by Joseph Mattiello on 12/17/22.
// Copyright © 2022 Provenance Emu. All rights reserved.
//

import Foundation
#if canImport(AuthenticationServices)
import AuthenticationServices

@available(tvOS 16.0, *)
extension PatreonAPI: ASWebAuthenticationPresentationContextProviding
{
public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor
{
return UIApplication.shared.keyWindow ?? UIWindow()
}
}
#endif
Loading