diff --git a/CHANGELOG.md b/CHANGELOG.md index cfaae45..c3884f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ +# 2.8.1 + +- Feature: sitekey ("apiKey") syntax validation + # 2.8.0 -- Feature: passive site key ([#152](https://github.com/hCaptcha/HCaptcha-ios-sdk/issues/152)) +- Feature: passive sitekey ([#152](https://github.com/hCaptcha/HCaptcha-ios-sdk/issues/152)) - Feature: upgrade Xcode to 15. NOTE: this also increases the minimum supported iOS version to 12. ([#134](https://github.com/hCaptcha/HCaptcha-ios-sdk/issues/134)) diff --git a/Example/HCaptcha_Tests/Core/HCaptchaWebViewManager__Tests.swift b/Example/HCaptcha_Tests/Core/HCaptchaWebViewManager__Tests.swift index 7be6707..a1689e8 100644 --- a/Example/HCaptcha_Tests/Core/HCaptchaWebViewManager__Tests.swift +++ b/Example/HCaptcha_Tests/Core/HCaptchaWebViewManager__Tests.swift @@ -21,7 +21,7 @@ class HCaptchaWebViewManager__Tests: XCTestCase { super.setUp() presenterView = UIApplication.shared.keyWindow?.rootViewController?.view - apiKey = String(arc4random()) + apiKey = UUID().uuidString } override func tearDown() { diff --git a/Example/HCaptcha_Tests/Core/HCaptcha__Config__Tests.swift b/Example/HCaptcha_Tests/Core/HCaptcha__Config__Tests.swift index 7e3ed0b..44993ec 100644 --- a/Example/HCaptcha_Tests/Core/HCaptcha__Config__Tests.swift +++ b/Example/HCaptcha_Tests/Core/HCaptcha__Config__Tests.swift @@ -10,15 +10,17 @@ import XCTest class HCaptcha__Config__Tests: XCTestCase { + private static let sApiKey = UUID().uuidString private let expected = "https://hcaptcha.com/1/api.js?onload=onloadCallback&render=explicit&recaptchacompat=off" - + "&host=some-api-key.ios-sdk.hcaptcha.com&sentry=false&endpoint=https%3A%2F%2Fapi.hcaptcha.com" + + "&host=\(sApiKey).ios-sdk.hcaptcha.com&sentry=false&endpoint=https%3A%2F%2Fapi.hcaptcha.com" + "&assethost=https%3A%2F%2Fnewassets.hcaptcha.com&imghost=https%3A%2F%2Fimgs.hcaptcha.com" + "&reportapi=https%3A%2F%2Faccounts.hcaptcha.com" + private let apiKey = sApiKey func test__Base_URL() { // Ensures baseURL failure when nil do { - _ = try HCaptchaConfig(apiKey: "", infoPlistKey: nil, baseURL: nil, infoPlistURL: nil) + _ = try HCaptchaConfig(apiKey: apiKey, infoPlistKey: nil, baseURL: nil, infoPlistURL: nil) XCTFail("Should have failed") } catch let e as HCaptchaError { print(e) @@ -29,24 +31,24 @@ class HCaptcha__Config__Tests: XCTestCase { // Ensures plist url if nil key let plistURL = URL(string: "https://bar")! - let config1 = try? HCaptchaConfig(apiKey: "", infoPlistKey: nil, baseURL: nil, infoPlistURL: plistURL) + let config1 = try? HCaptchaConfig(apiKey: apiKey, infoPlistKey: nil, baseURL: nil, infoPlistURL: plistURL) XCTAssertEqual(config1?.baseURL, plistURL) // Ensures preference of given url over plist entry let url = URL(string: "ftp://foo")! - let config2 = try? HCaptchaConfig(apiKey: "", infoPlistKey: nil, baseURL: url, infoPlistURL: plistURL) + let config2 = try? HCaptchaConfig(apiKey: apiKey, infoPlistKey: nil, baseURL: url, infoPlistURL: plistURL) XCTAssertEqual(config2?.baseURL, url) } func test__Base_URL_Without_Scheme() { // Ignores URL with scheme let goodURL = URL(string: "https://foo.bar")! - let config0 = try? HCaptchaConfig(apiKey: "", infoPlistKey: nil, baseURL: goodURL, infoPlistURL: nil) + let config0 = try? HCaptchaConfig(apiKey: apiKey, infoPlistKey: nil, baseURL: goodURL, infoPlistURL: nil) XCTAssertEqual(config0?.baseURL, goodURL) // Fixes URL without scheme let badURL = URL(string: "foo")! - let config = try? HCaptchaConfig(apiKey: "", infoPlistKey: nil, baseURL: badURL, infoPlistURL: nil) + let config = try? HCaptchaConfig(apiKey: apiKey, infoPlistKey: nil, baseURL: badURL, infoPlistURL: nil) XCTAssertEqual(config?.baseURL.absoluteString, "http://" + badURL.absoluteString) } @@ -63,7 +65,7 @@ class HCaptcha__Config__Tests: XCTestCase { } // Ensures plist key if nil key - let plistKey = "bar" + let plistKey = UUID().uuidString let config1 = try? HCaptchaConfig( apiKey: nil, infoPlistKey: plistKey, @@ -73,35 +75,34 @@ class HCaptcha__Config__Tests: XCTestCase { XCTAssertEqual(config1?.apiKey, plistKey) // Ensures preference of given key over plist entry - let key = "foo" let config2 = try? HCaptchaConfig( - apiKey: key, + apiKey: apiKey, infoPlistKey: plistKey, baseURL: URL(string: "foo"), infoPlistURL: nil ) - XCTAssertEqual(config2?.apiKey, key) + XCTAssertEqual(config2?.apiKey, apiKey) } func test__Locale__Nil() { - let config = try? HCaptchaConfig() + let config = try? HCaptchaConfig(apiKey: apiKey) let actual = config?.actualEndpoint.absoluteString XCTAssertEqual(actual, expected) } func test__Locale__Valid() { let locale = Locale(identifier: "pt-BR") - let config = try? HCaptchaConfig(locale: locale) + let config = try? HCaptchaConfig(apiKey: apiKey, locale: locale) let actual = config?.actualEndpoint.absoluteString XCTAssertEqual(actual, "\(expected)&hl=\(locale.identifier)") } func test__Custom__Host() { let host = "custom-host" - let config = try? HCaptchaConfig(host: host) + let config = try? HCaptchaConfig(apiKey: apiKey, host: host) let actual = config?.actualEndpoint.absoluteString XCTAssertEqual(actual, expected.replacingOccurrences( - of: "some-api-key.ios-sdk.hcaptcha.com", + of: "\(apiKey).ios-sdk.hcaptcha.com", with: host)) } @@ -117,7 +118,7 @@ class HCaptcha__Config__Tests: XCTestCase { } } """ - let config = try? HCaptchaConfig(customTheme: customTheme) + let config = try? HCaptchaConfig(apiKey: apiKey, customTheme: customTheme) let actual = config?.actualEndpoint.absoluteString XCTAssertEqual(actual, expected + "&custom=true") } diff --git a/Example/HCaptcha_Tests/Helpers/HCaptchaConfig+Helpers.swift b/Example/HCaptcha_Tests/Helpers/HCaptchaConfig+Helpers.swift index f0a43f9..074e646 100644 --- a/Example/HCaptcha_Tests/Helpers/HCaptchaConfig+Helpers.swift +++ b/Example/HCaptcha_Tests/Helpers/HCaptchaConfig+Helpers.swift @@ -11,7 +11,7 @@ import Foundation extension HCaptchaConfig { init(html: String = HCaptchaHtml.template, - apiKey: String? = String(arc4random()), + apiKey: String? = UUID().uuidString, passiveApiKey: Bool = false, infoPlistKey: String? = "api-key", baseURL: URL? = URL(string: "http://localhost")!, @@ -46,7 +46,7 @@ extension HCaptchaConfig { locale: locale) } - init(apiKey: String = "some-api-key", + init(apiKey: String = UUID().uuidString, host: String? = nil, customTheme: String? = nil, locale: Locale? = nil) throws { diff --git a/Example/HCaptcha_Tests/Helpers/HCaptchaWebViewManager+Helpers.swift b/Example/HCaptcha_Tests/Helpers/HCaptchaWebViewManager+Helpers.swift index 1990cf4..2c7d730 100644 --- a/Example/HCaptcha_Tests/Helpers/HCaptchaWebViewManager+Helpers.swift +++ b/Example/HCaptcha_Tests/Helpers/HCaptchaWebViewManager+Helpers.swift @@ -37,7 +37,7 @@ extension HCaptchaWebViewManager { self.init( html: html, - apiKey: apiKey ?? "api-key", + apiKey: apiKey ?? UUID().uuidString, passiveApiKey: passiveApiKey, endpoint: endpoint ?? URL(string: "https://api.hcaptcha.com")!, size: size, diff --git a/Example/HCaptcha_Tests/RxSwift/HCaptcha+Rx__Tests.swift b/Example/HCaptcha_Tests/RxSwift/HCaptcha+Rx__Tests.swift index 48bd237..e6c8bce 100644 --- a/Example/HCaptcha_Tests/RxSwift/HCaptcha+Rx__Tests.swift +++ b/Example/HCaptcha_Tests/RxSwift/HCaptcha+Rx__Tests.swift @@ -23,7 +23,7 @@ class HCaptcha_Rx__Tests: XCTestCase { super.setUp() presenterView = UIApplication.shared.keyWindow! - apiKey = String(arc4random()) + apiKey = UUID().uuidString } override func tearDown() { diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 8c7bbf7..d34ae1e 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,7 +1,7 @@ PODS: - AppSwizzle (1.3.1) - - HCaptcha/Core (2.8.0) - - HCaptcha/RxSwift (2.8.0): + - HCaptcha/Core (2.8.1) + - HCaptcha/RxSwift (2.8.1): - HCaptcha/Core - RxSwift (~> 6.2.0) - RxBlocking (6.2.0): @@ -37,7 +37,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: AppSwizzle: db36e436f56110d93e5ae0147683435df593cabc - HCaptcha: 062308169f5cbd964f2ae25954fb773d19e469ed + HCaptcha: 210d88f8b553a0b33e71f0d3cc2fb2a52b520575 RxBlocking: 0b29f7d2079109a8de49c411381bed7c33ef1eeb RxCocoa: 4baf94bb35f2c0ab31bc0cb9f1900155f646ba42 RxRelay: e72dbfd157807478401ef1982e1c61c945c94b2f diff --git a/HCaptcha.podspec b/HCaptcha.podspec index cc32c3c..e62158e 100644 --- a/HCaptcha.podspec +++ b/HCaptcha.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'HCaptcha' - s.version = '2.8.0' + s.version = '2.8.1' s.summary = 'HCaptcha for iOS' s.swift_version = '5.0' diff --git a/HCaptcha/Classes/HCaptchaConfig.swift b/HCaptcha/Classes/HCaptchaConfig.swift index f7f945e..3302abb 100644 --- a/HCaptcha/Classes/HCaptchaConfig.swift +++ b/HCaptcha/Classes/HCaptchaConfig.swift @@ -214,6 +214,10 @@ struct HCaptchaConfig: CustomDebugStringConvertible { throw HCaptchaError.baseURLNotFound } + guard UUID(uuidString: apiKey) != nil else { + throw HCaptchaError.apiKeyInvalid + } + if let customTheme = customTheme { let validationJS: String = "(function() { return \(customTheme) })()" let context = JSContext()! diff --git a/HCaptcha/Classes/HCaptchaError.swift b/HCaptcha/Classes/HCaptchaError.swift index 3bcb6e6..d8ad2a9 100644 --- a/HCaptcha/Classes/HCaptchaError.swift +++ b/HCaptcha/Classes/HCaptchaError.swift @@ -44,6 +44,9 @@ public enum HCaptchaError: Error, CustomStringConvertible { /// Invalid custom theme passed case invalidCustomTheme + /// HCaptchaKey is invalid + case apiKeyInvalid + public static func == (lhs: HCaptchaError, rhs: HCaptchaError) -> Bool { return lhs.description == rhs.description } @@ -63,6 +66,9 @@ public enum HCaptchaError: Error, CustomStringConvertible { case .apiKeyNotFound: return "HCaptchaKey not provided" + case .apiKeyInvalid: + return "HCaptchaKey invalid" + case .baseURLNotFound: return "HCaptchaDomain not provided"