Skip to content

Commit c203f0f

Browse files
authored
Merge pull request #8029 from woocommerce/td/7891-unautenticated_requests
Account creation: add `UnauthenticatedRequest` instead of passing empty credentials to `AuthenticatedRequest`
2 parents 6067ae1 + b1761b5 commit c203f0f

File tree

8 files changed

+77
-12
lines changed

8 files changed

+77
-12
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
020D07BE23D8570800FD9580 /* MediaListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020D07BD23D8570800FD9580 /* MediaListMapper.swift */; };
1818
020D07C023D8587700FD9580 /* MediaRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020D07BF23D8587700FD9580 /* MediaRemoteTests.swift */; };
1919
020D07C223D858BB00FD9580 /* media-upload.json in Resources */ = {isa = PBXBuildFile; fileRef = 020D07C123D858BB00FD9580 /* media-upload.json */; };
20+
020D0C03291504DE00BB3DCE /* UnauthenticatedRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020D0C02291504DE00BB3DCE /* UnauthenticatedRequestTests.swift */; };
2021
0212683524C046CB00F8A892 /* MockNetwork+Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0212683424C046CB00F8A892 /* MockNetwork+Path.swift */; };
2122
0219B03923964BB3007DCD5E /* ProductShippingClassMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0219B03823964BB3007DCD5E /* ProductShippingClassMapper.swift */; };
2223
021A84DA257DF92800BC71D1 /* ShippingLabelRefundMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021A84D9257DF92800BC71D1 /* ShippingLabelRefundMapper.swift */; };
@@ -55,6 +56,7 @@
5556
029BA4F0255D7282006171FD /* ShippingLabelRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029BA4EF255D7282006171FD /* ShippingLabelRemote.swift */; };
5657
029BA4F4255D72EC006171FD /* ShippingLabelPrintData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029BA4F3255D72EC006171FD /* ShippingLabelPrintData.swift */; };
5758
029BA53B255DFABD006171FD /* ShippingLabelPrintDataMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029BA53A255DFABD006171FD /* ShippingLabelPrintDataMapper.swift */; };
59+
029C9E5C291507A40013E5EE /* UnauthenticatedRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029C9E5B291507A40013E5EE /* UnauthenticatedRequest.swift */; };
5860
02A26F1B2744F5FC008E4EDB /* wc-site-settings-partial.json in Resources */ = {isa = PBXBuildFile; fileRef = 02A26F192744F5FC008E4EDB /* wc-site-settings-partial.json */; };
5961
02A26F1C2744F5FC008E4EDB /* wp-site-settings.json in Resources */ = {isa = PBXBuildFile; fileRef = 02A26F1A2744F5FC008E4EDB /* wp-site-settings.json */; };
6062
02AAD53F250092A400BA1E26 /* product-add-or-delete.json in Resources */ = {isa = PBXBuildFile; fileRef = 02AAD53E250092A300BA1E26 /* product-add-or-delete.json */; };
@@ -756,6 +758,7 @@
756758
020D07BD23D8570800FD9580 /* MediaListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaListMapper.swift; sourceTree = "<group>"; };
757759
020D07BF23D8587700FD9580 /* MediaRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaRemoteTests.swift; sourceTree = "<group>"; };
758760
020D07C123D858BB00FD9580 /* media-upload.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-upload.json"; sourceTree = "<group>"; };
761+
020D0C02291504DE00BB3DCE /* UnauthenticatedRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnauthenticatedRequestTests.swift; sourceTree = "<group>"; };
759762
0212683424C046CB00F8A892 /* MockNetwork+Path.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MockNetwork+Path.swift"; sourceTree = "<group>"; };
760763
0219B03823964BB3007DCD5E /* ProductShippingClassMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductShippingClassMapper.swift; sourceTree = "<group>"; };
761764
021A84D9257DF92800BC71D1 /* ShippingLabelRefundMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelRefundMapper.swift; sourceTree = "<group>"; };
@@ -794,6 +797,7 @@
794797
029BA4EF255D7282006171FD /* ShippingLabelRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelRemote.swift; sourceTree = "<group>"; };
795798
029BA4F3255D72EC006171FD /* ShippingLabelPrintData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPrintData.swift; sourceTree = "<group>"; };
796799
029BA53A255DFABD006171FD /* ShippingLabelPrintDataMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPrintDataMapper.swift; sourceTree = "<group>"; };
800+
029C9E5B291507A40013E5EE /* UnauthenticatedRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnauthenticatedRequest.swift; sourceTree = "<group>"; };
797801
02A26F192744F5FC008E4EDB /* wc-site-settings-partial.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "wc-site-settings-partial.json"; sourceTree = "<group>"; };
798802
02A26F1A2744F5FC008E4EDB /* wp-site-settings.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "wp-site-settings.json"; sourceTree = "<group>"; };
799803
02AAD53E250092A300BA1E26 /* product-add-or-delete.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-add-or-delete.json"; sourceTree = "<group>"; };
@@ -1736,6 +1740,7 @@
17361740
DE34052028BDFE3500CF0D97 /* WordPressOrgRequestTests.swift */,
17371741
B567AF2D20A0FB8F00AB6C62 /* DotcomRequestTests.swift */,
17381742
B567AF2E20A0FB8F00AB6C62 /* JetpackRequestTests.swift */,
1743+
020D0C02291504DE00BB3DCE /* UnauthenticatedRequestTests.swift */,
17391744
);
17401745
path = Requests;
17411746
sourceTree = "<group>";
@@ -1866,6 +1871,7 @@
18661871
B557DA0E20975E07005962F4 /* DotcomRequest.swift */,
18671872
B557D9FF209754FF005962F4 /* JetpackRequest.swift */,
18681873
DE34051228BDCA5100CF0D97 /* WordPressOrgRequest.swift */,
1874+
029C9E5B291507A40013E5EE /* UnauthenticatedRequest.swift */,
18691875
);
18701876
path = Requests;
18711877
sourceTree = "<group>";
@@ -3054,6 +3060,7 @@
30543060
B5A2417D217F9ECC00595DEF /* MetaContainer.swift in Sources */,
30553061
025CA2C4238EBC4300B05C81 /* ProductShippingClassRemote.swift in Sources */,
30563062
D88D5A4B230BCF0A007B6E01 /* ProductReviewListMapper.swift in Sources */,
3063+
029C9E5C291507A40013E5EE /* UnauthenticatedRequest.swift in Sources */,
30573064
93D8BBFB226BBC5100AD2EB3 /* AccountSettings.swift in Sources */,
30583065
B53EF53821813806003E146F /* DotcomError.swift in Sources */,
30593066
CC07865F267799EE00BA9AC1 /* ShippingLabelPurchase.swift in Sources */,
@@ -3306,6 +3313,7 @@
33063313
4513382227A8409000AE5E78 /* InboxNotesRemoteTests.swift in Sources */,
33073314
45E461BE26837DB900011BF2 /* DataRemoteTests.swift in Sources */,
33083315
CEC4BF8F234E382F008D9195 /* RefundMapperTests.swift in Sources */,
3316+
020D0C03291504DE00BB3DCE /* UnauthenticatedRequestTests.swift in Sources */,
33093317
24F98C5E2502EDCF00F49B68 /* BundleWooTests.swift in Sources */,
33103318
036563DF29069C8F00D84BFD /* JustInTimeMessageListMapperTests.swift in Sources */,
33113319
74AB0ACA21948CE4008220CD /* CommentResultMapperTests.swift in Sources */,

Networking/Networking/Network/AlamofireNetwork.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ public class AlamofireNetwork: Network {
1313

1414
/// WordPress.com Credentials.
1515
///
16-
private let credentials: Credentials
16+
private let credentials: Credentials?
1717

1818
public var session: URLSession { SessionManager.default.session }
1919

2020
/// Public Initializer
2121
///
22-
public required init(credentials: Credentials) {
22+
public required init(credentials: Credentials?) {
2323
self.credentials = credentials
2424

2525
// A unique ID is included in the background session identifier so that the session does not get invalidated when the initializer is called multiple
@@ -45,9 +45,9 @@ public class AlamofireNetwork: Network {
4545
/// - Yes. We do the above because the Jetpack Tunnel endpoint doesn't properly relay the correct statusCode.
4646
///
4747
public func responseData(for request: URLRequestConvertible, completion: @escaping (Data?, Error?) -> Void) {
48-
let authenticated = AuthenticatedRequest(credentials: credentials, request: request)
48+
let request = createRequest(wrapping: request)
4949

50-
Alamofire.request(authenticated)
50+
Alamofire.request(request)
5151
.responseData { response in
5252
completion(response.value, response.networkingError)
5353
}
@@ -63,9 +63,9 @@ public class AlamofireNetwork: Network {
6363
/// - completion: Closure to be executed upon completion.
6464
///
6565
public func responseData(for request: URLRequestConvertible, completion: @escaping (Swift.Result<Data, Error>) -> Void) {
66-
let authenticated = AuthenticatedRequest(credentials: credentials, request: request)
66+
let request = createRequest(wrapping: request)
6767

68-
Alamofire.request(authenticated).responseData { response in
68+
Alamofire.request(request).responseData { response in
6969
completion(response.result.toSwiftResult())
7070
}
7171
}
@@ -79,10 +79,10 @@ public class AlamofireNetwork: Network {
7979
/// - Parameter request: Request that should be performed.
8080
/// - Returns: A publisher that emits the result of the given request.
8181
public func responseDataPublisher(for request: URLRequestConvertible) -> AnyPublisher<Swift.Result<Data, Error>, Never> {
82-
let authenticated = AuthenticatedRequest(credentials: credentials, request: request)
82+
let request = createRequest(wrapping: request)
8383

8484
return Future() { promise in
85-
Alamofire.request(authenticated).responseData { response in
85+
Alamofire.request(request).responseData { response in
8686
let result = response.result.toSwiftResult()
8787
promise(Swift.Result.success(result))
8888
}
@@ -92,9 +92,9 @@ public class AlamofireNetwork: Network {
9292
public func uploadMultipartFormData(multipartFormData: @escaping (MultipartFormData) -> Void,
9393
to request: URLRequestConvertible,
9494
completion: @escaping (Data?, Error?) -> Void) {
95-
let authenticated = AuthenticatedRequest(credentials: credentials, request: request)
95+
let request = createRequest(wrapping: request)
9696

97-
backgroundSessionManager.upload(multipartFormData: multipartFormData, with: authenticated) { (encodingResult) in
97+
backgroundSessionManager.upload(multipartFormData: multipartFormData, with: request) { (encodingResult) in
9898
switch encodingResult {
9999
case .success(let upload, _, _):
100100
upload.responseData { response in
@@ -107,6 +107,13 @@ public class AlamofireNetwork: Network {
107107
}
108108
}
109109

110+
private extension AlamofireNetwork {
111+
func createRequest(wrapping request: URLRequestConvertible) -> URLRequestConvertible {
112+
credentials.map { AuthenticatedRequest(credentials: $0, request: request) } ??
113+
UnauthenticatedRequest(request: request)
114+
}
115+
}
116+
110117

111118
// MARK: - Alamofire.DataResponse: Helper Methods
112119
//

Networking/Networking/Network/MockNetwork.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ private extension MockNetwork {
185185
switch request {
186186
case let request as AuthenticatedRequest:
187187
return path(for: request.request)
188+
case let request as UnauthenticatedRequest:
189+
return path(for: request.request)
188190
case let request as JetpackRequest:
189191
return request.path
190192
case let request as DotcomRequest:
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Foundation
2+
import protocol Alamofire.URLRequestConvertible
3+
4+
5+
/// Wraps up a `URLRequestConvertible` instance, and injects the `UserAgent.defaultUserAgent`.
6+
///
7+
struct UnauthenticatedRequest: URLRequestConvertible {
8+
9+
/// Request that does not require WPCOM authentication.
10+
///
11+
let request: URLRequestConvertible
12+
13+
/// Returns the wrapped request, with a custom user-agent header.
14+
///
15+
func asURLRequest() throws -> URLRequest {
16+
var authenticated = try request.asURLRequest()
17+
18+
authenticated.setValue("application/json", forHTTPHeaderField: "Accept")
19+
authenticated.setValue(UserAgent.defaultUserAgent, forHTTPHeaderField: "User-Agent")
20+
21+
return authenticated
22+
}
23+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Foundation
2+
import XCTest
3+
@testable import Networking
4+
5+
/// `UnauthenticatedRequest` Unit Tests
6+
final class UnauthenticatedRequestTests: XCTestCase {
7+
/// Sample Unauthenticated Request
8+
private let unauthenticatedRequest = try! URLRequest(url: "www.automattic.com", method: .get)
9+
10+
/// Verifies that the user-agent is injected as part of the HTTP Headers.
11+
func test_user_agent_is_injected_as_request_header() throws {
12+
// Given
13+
let request = UnauthenticatedRequest(request: unauthenticatedRequest)
14+
15+
// When
16+
let urlRequest = try request.asURLRequest()
17+
18+
// Then
19+
let userAgentHeader = urlRequest.allHTTPHeaderFields?["User-Agent"]
20+
XCTAssertEqual(userAgentHeader, UserAgent.defaultUserAgent)
21+
}
22+
}

WooCommerce/Classes/Yosemite/DeauthenticatedState.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class DeauthenticatedState: StoresManagerState {
1515

1616
init() {
1717
// Used for logged-out state without a WPCOM auth token.
18-
let network = AlamofireNetwork(credentials: .init(authToken: ""))
18+
let network = AlamofireNetwork(credentials: nil)
1919
services = [
2020
JetpackConnectionStore(dispatcher: dispatcher),
2121
AccountCreationStore(dotcomClientID: ApiCredentials.dotcomAppId,

docs/NETWORKING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ At the moment, we provide four implementations of `URLRequestConvertible`:
4545
* [`JetpackRequest`](../Networking/Networking/Requests/JetpackRequest.swift) represents a Jetpack-Tunneled WordPress.com
4646
* [`AuthenticatedRequest`](../Networking/Networking/Requests/AuthenticatedRequest.swift) Wraps up a `URLRequestConvertible` instance, and injects credentials (username and token) when required
4747
* [`WordPressOrgRequest`](../Networking/Networking/Requests/WordPressOrgRequest.swift) model requests to the WordPress.org REST API.
48+
* [`UnauthenticatedRequest`](../Networking/Networking/Requests/UnauthenticatedRequest.swift) Wraps up a `URLRequestConvertible` instance, and injects a custom user-agent header
4849

4950
## [`Mapper`](../Networking/Networking/Mapper/Mapper.swift)
5051
A protocol that abstracts the different parsers.

docs/architecture-overview.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,12 @@ of performing this task for us:
171171

172172
3. **AuthenticatedRequest**
173173

174-
Injects a set of Credentials into anything that conforms to the URLConvertible protocol. Usually wraps up
174+
Injects a set of Credentials and a custom user-agent header into anything that conforms to the URLConvertible protocol. Usually wraps up
175175
a DotcomRequest (OR) JetpackRequest.
176176

177+
4. **UnauthenticatedRequest**
177178

179+
Wraps up a `URLConvertible` with a custom user-agent header. Used when the request does not require WordPress.com authentication.
178180

179181
### Remote Endpoints
180182

0 commit comments

Comments
 (0)