Skip to content

Commit e30bfd5

Browse files
Break AuthenticatedRequest into two parts for handling WPCOM token and application password authentication methods.
1 parent a3e21d8 commit e30bfd5

File tree

10 files changed

+250
-194
lines changed

10 files changed

+250
-194
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -506,10 +506,8 @@
506506
B557DA1A20979D66005962F4 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B557DA1920979D66005962F4 /* Settings.swift */; };
507507
B557DA1D20979E7D005962F4 /* Order.swift in Sources */ = {isa = PBXBuildFile; fileRef = B557DA1C20979E7D005962F4 /* Order.swift */; };
508508
B559EBAA20A0B5CD00836CD4 /* orders-load-all.json in Resources */ = {isa = PBXBuildFile; fileRef = B559EBA920A0B5CD00836CD4 /* orders-load-all.json */; };
509-
B567AF2520A0CCA300AB6C62 /* AuthenticatedRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B567AF2420A0CCA300AB6C62 /* AuthenticatedRequest.swift */; };
510509
B567AF2920A0FA1E00AB6C62 /* Mapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B567AF2820A0FA1E00AB6C62 /* Mapper.swift */; };
511510
B567AF2B20A0FA4200AB6C62 /* OrderListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B567AF2A20A0FA4200AB6C62 /* OrderListMapper.swift */; };
512-
B567AF2F20A0FB8F00AB6C62 /* AuthenticatedRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B567AF2C20A0FB8F00AB6C62 /* AuthenticatedRequestTests.swift */; };
513511
B567AF3020A0FB8F00AB6C62 /* DotcomRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B567AF2D20A0FB8F00AB6C62 /* DotcomRequestTests.swift */; };
514512
B567AF3120A0FB8F00AB6C62 /* JetpackRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B567AF2E20A0FB8F00AB6C62 /* JetpackRequestTests.swift */; };
515513
B56C1EB620EA757B00D749F9 /* SiteListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */; };
@@ -758,6 +756,10 @@
758756
EE99814E295AA7430074AE68 /* RequestAuthenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE99814D295AA7430074AE68 /* RequestAuthenticator.swift */; };
759757
EE998150295AACE10074AE68 /* RequestConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE99814F295AACE10074AE68 /* RequestConverter.swift */; };
760758
EECB7EE8286555180028C888 /* media-update-product-id.json in Resources */ = {isa = PBXBuildFile; fileRef = EECB7EE7286555180028C888 /* media-update-product-id.json */; };
759+
EEFAA57B295D7793003583BE /* AuthenticatedDotcomRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFAA57A295D7793003583BE /* AuthenticatedDotcomRequest.swift */; };
760+
EEFAA57D295D77F0003583BE /* AuthenticatedRESTRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFAA57C295D77F0003583BE /* AuthenticatedRESTRequest.swift */; };
761+
EEFAA57F295D78DF003583BE /* AuthenticatedDotcomRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFAA57E295D78DF003583BE /* AuthenticatedDotcomRequestTests.swift */; };
762+
EEFAA581295D78E9003583BE /* AuthenticatedRESTRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFAA580295D78E9003583BE /* AuthenticatedRESTRequestTests.swift */; };
761763
FE28F6E226840DED004465C7 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE28F6E126840DED004465C7 /* User.swift */; };
762764
FE28F6E426842848004465C7 /* UserMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE28F6E326842848004465C7 /* UserMapper.swift */; };
763765
FE28F6E6268429B6004465C7 /* UserRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE28F6E5268429B6004465C7 /* UserRemote.swift */; };
@@ -1292,10 +1294,8 @@
12921294
B557DA1920979D66005962F4 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
12931295
B557DA1C20979E7D005962F4 /* Order.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Order.swift; sourceTree = "<group>"; };
12941296
B559EBA920A0B5CD00836CD4 /* orders-load-all.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "orders-load-all.json"; sourceTree = "<group>"; };
1295-
B567AF2420A0CCA300AB6C62 /* AuthenticatedRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticatedRequest.swift; sourceTree = "<group>"; };
12961297
B567AF2820A0FA1E00AB6C62 /* Mapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mapper.swift; sourceTree = "<group>"; };
12971298
B567AF2A20A0FA4200AB6C62 /* OrderListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderListMapper.swift; sourceTree = "<group>"; };
1298-
B567AF2C20A0FB8F00AB6C62 /* AuthenticatedRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticatedRequestTests.swift; sourceTree = "<group>"; };
12991299
B567AF2D20A0FB8F00AB6C62 /* DotcomRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DotcomRequestTests.swift; sourceTree = "<group>"; };
13001300
B567AF2E20A0FB8F00AB6C62 /* JetpackRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JetpackRequestTests.swift; sourceTree = "<group>"; };
13011301
B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListMapper.swift; sourceTree = "<group>"; };
@@ -1546,6 +1546,10 @@
15461546
EE99814D295AA7430074AE68 /* RequestAuthenticator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestAuthenticator.swift; sourceTree = "<group>"; };
15471547
EE99814F295AACE10074AE68 /* RequestConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestConverter.swift; sourceTree = "<group>"; };
15481548
EECB7EE7286555180028C888 /* media-update-product-id.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-update-product-id.json"; sourceTree = "<group>"; };
1549+
EEFAA57A295D7793003583BE /* AuthenticatedDotcomRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedDotcomRequest.swift; sourceTree = "<group>"; };
1550+
EEFAA57C295D77F0003583BE /* AuthenticatedRESTRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedRESTRequest.swift; sourceTree = "<group>"; };
1551+
EEFAA57E295D78DF003583BE /* AuthenticatedDotcomRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedDotcomRequestTests.swift; sourceTree = "<group>"; };
1552+
EEFAA580295D78E9003583BE /* AuthenticatedRESTRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticatedRESTRequestTests.swift; sourceTree = "<group>"; };
15491553
F3F25DC15EC1D7C631169CB5 /* Pods_Networking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Networking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
15501554
F6CEE1CA2AD376C0C28AE9F6 /* Pods-NetworkingTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkingTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-NetworkingTests/Pods-NetworkingTests.release.xcconfig"; sourceTree = "<group>"; };
15511555
FE28F6E126840DED004465C7 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
@@ -1827,11 +1831,12 @@
18271831
B519A3E82097A91800E2603A /* Requests */ = {
18281832
isa = PBXGroup;
18291833
children = (
1830-
B567AF2C20A0FB8F00AB6C62 /* AuthenticatedRequestTests.swift */,
18311834
DE34052028BDFE3500CF0D97 /* WordPressOrgRequestTests.swift */,
18321835
B567AF2D20A0FB8F00AB6C62 /* DotcomRequestTests.swift */,
18331836
B567AF2E20A0FB8F00AB6C62 /* JetpackRequestTests.swift */,
18341837
020D0C02291504DE00BB3DCE /* UnauthenticatedRequestTests.swift */,
1838+
EEFAA57E295D78DF003583BE /* AuthenticatedDotcomRequestTests.swift */,
1839+
EEFAA580295D78E9003583BE /* AuthenticatedRESTRequestTests.swift */,
18351840
);
18361841
path = Requests;
18371842
sourceTree = "<group>";
@@ -1964,13 +1969,14 @@
19641969
B557DA0620975515005962F4 /* Requests */ = {
19651970
isa = PBXGroup;
19661971
children = (
1967-
B567AF2420A0CCA300AB6C62 /* AuthenticatedRequest.swift */,
19681972
E1BAB2C02913F99500C3982B /* Request.swift */,
19691973
B557DA0E20975E07005962F4 /* DotcomRequest.swift */,
19701974
B557D9FF209754FF005962F4 /* JetpackRequest.swift */,
19711975
DE34051228BDCA5100CF0D97 /* WordPressOrgRequest.swift */,
19721976
029C9E5B291507A40013E5EE /* UnauthenticatedRequest.swift */,
19731977
DEFBA74D29485A7600C35BA9 /* RESTRequest.swift */,
1978+
EEFAA57A295D7793003583BE /* AuthenticatedDotcomRequest.swift */,
1979+
EEFAA57C295D77F0003583BE /* AuthenticatedRESTRequest.swift */,
19741980
);
19751981
path = Requests;
19761982
sourceTree = "<group>";
@@ -3210,7 +3216,6 @@
32103216
451A97E5260B631E0059D135 /* ShippingLabelPredefinedPackage.swift in Sources */,
32113217
BAB373722795A1FB00837B4A /* OrderTaxLine.swift in Sources */,
32123218
EE54C89F2947782E00A9BF61 /* ApplicationPasswordUseCase.swift in Sources */,
3213-
B567AF2520A0CCA300AB6C62 /* AuthenticatedRequest.swift in Sources */,
32143219
453305E92459DF2100264E50 /* PostMapper.swift in Sources */,
32153220
E12552C526385B05001CEE70 /* ShippingLabelAddressValidationSuccess.swift in Sources */,
32163221
456F71D424CB1E2400472EC1 /* ProductTagFromBatchCreation.swift in Sources */,
@@ -3336,6 +3341,7 @@
33363341
CE50345E21B571A7007573C6 /* SitePlanMapper.swift in Sources */,
33373342
DE34051528BDEB1900CF0D97 /* WordPressOrgNetwork.swift in Sources */,
33383343
3192F224260D34C40067FEF9 /* WCPayAccountStatusEnum.swift in Sources */,
3344+
EEFAA57B295D7793003583BE /* AuthenticatedDotcomRequest.swift in Sources */,
33393345
D8FBFF2022D52553006E3336 /* OrderStatsV4Totals.swift in Sources */,
33403346
02C254B925637BA000A04423 /* OrderShippingLabelListMapper.swift in Sources */,
33413347
261CF1B8255AE62D0090D8D3 /* PaymentGatewayRemote.swift in Sources */,
@@ -3354,6 +3360,7 @@
33543360
24F98C522502E79800F49B68 /* FeatureFlagsRemote.swift in Sources */,
33553361
74A1D26D21189DFF00931DFA /* SiteVisitStatsMapper.swift in Sources */,
33563362
45152809257A7C6E0076B03C /* ProductAttributesRemote.swift in Sources */,
3363+
EEFAA57D295D77F0003583BE /* AuthenticatedRESTRequest.swift in Sources */,
33573364
D8FBFF2222D5266E006E3336 /* OrderStatsV4Interval.swift in Sources */,
33583365
4568E2222459ADC60007E478 /* SitePostsRemote.swift in Sources */,
33593366
02C11276274285FF00F4F0B4 /* WooCommerceAvailabilityMapper.swift in Sources */,
@@ -3567,6 +3574,7 @@
35673574
B5C151C0217EE3FB00C7BDC1 /* NoteListMapperTests.swift in Sources */,
35683575
026CF622237D7E61009563D4 /* ProductVariationsRemoteTests.swift in Sources */,
35693576
DEC51A99274DDDC9009F3DF4 /* SitePluginMapperTests.swift in Sources */,
3577+
EEFAA581295D78E9003583BE /* AuthenticatedRESTRequestTests.swift in Sources */,
35703578
CCF48B802628BBC10034EA83 /* ShippingLabelAccountSettingsMapperTests.swift in Sources */,
35713579
FE28F6EC268436C9004465C7 /* UserRemoteTests.swift in Sources */,
35723580
DE74F29E27E0A6800002FE59 /* SiteSettingMapperTests.swift in Sources */,
@@ -3599,14 +3607,14 @@
35993607
74C8F06E20EEC1E800B6EDC9 /* OrderNotesMapperTests.swift in Sources */,
36003608
45ED4F10239E8A54004F1BE3 /* TaxClassListMapperTest.swift in Sources */,
36013609
FE28F6EA26842E49004465C7 /* UserMapperTests.swift in Sources */,
3610+
EEFAA57F295D78DF003583BE /* AuthenticatedDotcomRequestTests.swift in Sources */,
36023611
E137619B2915222100FD098F /* WordPressApiValidatorTests.swift in Sources */,
36033612
020C907F24C7D359001E2BEB /* ProductVariationMapperTests.swift in Sources */,
36043613
74ABA1D5213F26B300FFAD30 /* TopEarnerStatsMapperTests.swift in Sources */,
36053614
74AB5B5121AF426D00859C12 /* SiteAPIRemoteTests.swift in Sources */,
36063615
077F39E626A5D15800ABEADC /* SystemPluginMapperTests.swift in Sources */,
36073616
4599FC6624A633A10056157A /* ProductTagsRemoteTests.swift in Sources */,
36083617
DE97C3922861B8E20042E973 /* CouponEncoderTests.swift in Sources */,
3609-
B567AF2F20A0FB8F00AB6C62 /* AuthenticatedRequestTests.swift in Sources */,
36103618
B5C6FCCD20A34B8300A4F8E4 /* OrderListMapperTests.swift in Sources */,
36113619
B518663520A0A2E800037A38 /* Constants.swift in Sources */,
36123620
D8FBFF1E22D51F39006E3336 /* OrderStatsMapperV4Tests.swift in Sources */,

Networking/Networking/ApplicationPassword/RequestAuthenticator.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private extension RequestAuthenticator {
7575
return UnauthenticatedRequest(request: urlRequest).asURLRequest()
7676
}
7777

78-
return AuthenticatedRequest(authToken: authToken, request: urlRequest).asURLRequest()
78+
return AuthenticatedDotcomRequest(authToken: authToken, request: urlRequest).asURLRequest()
7979
}
8080

8181
/// Attempts creating a request with application password if possible.
@@ -85,6 +85,6 @@ private extension RequestAuthenticator {
8585
throw RequestAuthenticatorError.applicationPasswordNotAvailable
8686
}
8787

88-
return AuthenticatedRequest(applicationPassword: applicationPassword, request: urlRequest).asURLRequest()
88+
return AuthenticatedRESTRequest(applicationPassword: applicationPassword, request: urlRequest).asURLRequest()
8989
}
9090
}

Networking/Networking/Network/MockNetwork.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ private extension MockNetwork {
183183
///
184184
private func path(for request: URLRequestConvertible) -> String {
185185
switch request {
186-
case let request as AuthenticatedRequest:
186+
case let request as AuthenticatedDotcomRequest:
187+
return path(for: request.request)
188+
case let request as AuthenticatedRESTRequest:
187189
return path(for: request.request)
188190
case let request as UnauthenticatedRequest:
189191
return path(for: request.request)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Foundation
2+
import Alamofire
3+
4+
/// Wraps up a URLRequestConvertible Instance, and injects
5+
/// the WordPress.com authentication token + `Settings.userAgent`
6+
/// whenever the actual Request is required.
7+
///
8+
struct AuthenticatedDotcomRequest: URLRequestConvertible {
9+
/// Authenticated Request
10+
///
11+
let request: URLRequest
12+
13+
init(authToken: String, request: URLRequest) {
14+
var authenticated = request
15+
16+
authenticated.setValue("Bearer " + authToken, forHTTPHeaderField: "Authorization")
17+
authenticated.setValue("application/json", forHTTPHeaderField: "Accept")
18+
authenticated.setValue(UserAgent.defaultUserAgent, forHTTPHeaderField: "User-Agent")
19+
20+
self.request = authenticated
21+
}
22+
23+
/// Returns the Wrapped Request, but with a WordPress.com Bearer Token set up.
24+
///
25+
func asURLRequest() -> URLRequest {
26+
request
27+
}
28+
}

Networking/Networking/Requests/AuthenticatedRequest.swift renamed to Networking/Networking/Requests/AuthenticatedRESTRequest.swift

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,13 @@
11
import Foundation
22
import Alamofire
33

4-
enum AuthenticatedRequestError: Error {
5-
case invalidCredentials
6-
}
7-
8-
/// Wraps up a URLRequestConvertible Instance, and injects the Credentials + `Settings.userAgent` whenever the actual Request is required.
4+
/// Wraps up a URLRequestConvertible Instance, and injects the application password + `Settings.userAgent` whenever the actual Request is required.
95
///
10-
struct AuthenticatedRequest: URLRequestConvertible {
6+
struct AuthenticatedRESTRequest: URLRequestConvertible {
117
/// Authenticated Request
128
///
139
let request: URLRequest
1410

15-
init(authToken: String, request: URLRequest) {
16-
var authenticated = request
17-
18-
authenticated.setValue("Bearer " + authToken, forHTTPHeaderField: "Authorization")
19-
authenticated.setValue("application/json", forHTTPHeaderField: "Accept")
20-
authenticated.setValue(UserAgent.defaultUserAgent, forHTTPHeaderField: "User-Agent")
21-
22-
self.request = authenticated
23-
}
24-
2511
init(applicationPassword: ApplicationPassword, request: URLRequest) {
2612
var authenticated = request
2713

@@ -42,7 +28,7 @@ struct AuthenticatedRequest: URLRequestConvertible {
4228
self.request = authenticated
4329
}
4430

45-
/// Returns the Wrapped Request, but with a WordPress.com Bearer Token set up.
31+
/// Returns the Wrapped Request, but with the application password injected
4632
///
4733
func asURLRequest() -> URLRequest {
4834
request
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import Foundation
2+
import XCTest
3+
import WordPressShared
4+
@testable import Networking
5+
6+
/// AuthenticatedDotcomRequest Unit Tests
7+
///
8+
final class AuthenticatedDotcomRequestTests: XCTestCase {
9+
10+
/// Sample Unauthenticated Request
11+
///
12+
private var unauthenticatedRequest: URLRequest!
13+
14+
/// Sample Credentials
15+
///
16+
private let credentials = Credentials(username: "username", authToken: "yosemite", siteAddress: "https://wordpress.com")
17+
18+
override func setUp() {
19+
super.setUp()
20+
21+
unauthenticatedRequest = try! URLRequest(url: "www.automattic.com", method: .get)
22+
}
23+
24+
override func tearDown() {
25+
unauthenticatedRequest = nil
26+
27+
super.tearDown()
28+
}
29+
30+
/// Verifies that the Bearer Token is injected, as part of the HTTP Headers.
31+
///
32+
func test_bearer_token_is_injected_as_request_header_when_authenticated_using_WPCOM_token() {
33+
// Given
34+
XCTAssertEqual(unauthenticatedRequest.allHTTPHeaderFields, [:])
35+
36+
guard case let .wpcom(_, authToken, _) = credentials else {
37+
XCTFail("Missing credentials.")
38+
return
39+
}
40+
41+
let authenticated = AuthenticatedDotcomRequest(authToken: authToken, request: unauthenticatedRequest)
42+
43+
// When
44+
let output = authenticated.asURLRequest()
45+
46+
// Then
47+
let generated = output.allHTTPHeaderFields?["Authorization"]
48+
let expected = "Bearer \(authToken)"
49+
XCTAssertEqual(generated, expected)
50+
}
51+
52+
/// Verifies that the User Agent is injected as part of the HTTP Headers.
53+
///
54+
func test_user_agent_is_injected_as_request_header_when_authenticated_using_WPCOM_token() {
55+
// Given
56+
XCTAssertEqual(unauthenticatedRequest.allHTTPHeaderFields, [:])
57+
58+
guard case let .wpcom(_, authToken, _) = credentials else {
59+
XCTFail("Missing credentials.")
60+
return
61+
}
62+
63+
let authenticated = AuthenticatedDotcomRequest(authToken: authToken, request: unauthenticatedRequest)
64+
65+
// When
66+
let output = authenticated.asURLRequest()
67+
68+
// Then
69+
let generated = output.allHTTPHeaderFields?["User-Agent"]
70+
XCTAssertEqual(generated, UserAgent.defaultUserAgent)
71+
}
72+
73+
/// Verifies that the `Accept` header is injected, as part of the HTTP Headers.
74+
///
75+
func test_accept_is_injected_as_request_header_when_authenticated_using_WPCOM_token() {
76+
// Given
77+
XCTAssertEqual(unauthenticatedRequest.allHTTPHeaderFields, [:])
78+
79+
guard case let .wpcom(_, authToken, _) = credentials else {
80+
XCTFail("Missing credentials.")
81+
return
82+
}
83+
84+
let authenticated = AuthenticatedDotcomRequest(authToken: authToken, request: unauthenticatedRequest)
85+
86+
// When
87+
let output = authenticated.asURLRequest()
88+
89+
// Then
90+
let generated = output.allHTTPHeaderFields?["Accept"]
91+
let expected = "application/json"
92+
XCTAssertEqual(generated, expected)
93+
}
94+
}

0 commit comments

Comments
 (0)