Skip to content

Commit d5a9b29

Browse files
[BWA-155] Copy reduced APIService and EnvironmentService into AuthenticatorShared (#1504)
1 parent dc16714 commit d5a9b29

32 files changed

+375
-103
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import BitwardenKit
2+
import Networking
3+
import UIKit
4+
5+
/// A service used by the application to make API requests.
6+
///
7+
class APIService {
8+
// MARK: Properties
9+
10+
/// The API service that is used for general unauthenticated requests.
11+
let apiUnauthenticatedService: HTTPService
12+
13+
// MARK: Private Properties
14+
15+
/// The underlying `HTTPClient` that performs the network request.
16+
private let client: HTTPClient
17+
18+
/// A `RequestHandler` that applies default headers (user agent, client type & name, etc) to requests.
19+
private let defaultHeadersRequestHandler: DefaultHeadersRequestHandler
20+
21+
/// A `ResponseHandler` that validates that HTTP responses contain successful (2XX) HTTP status
22+
/// codes or tries to parse the error otherwise.
23+
private let responseValidationHandler = ResponseValidationHandler()
24+
25+
// MARK: Initialization
26+
27+
/// Initialize an `APIService` used to make API requests.
28+
///
29+
/// - Parameters:
30+
/// - client: The underlying `HTTPClient` that performs the network request. Defaults
31+
/// to `URLSession.shared`.
32+
/// - environmentService: The service used by the application to retrieve the environment settings.
33+
///
34+
init(
35+
client: HTTPClient = URLSession.shared,
36+
environmentService: EnvironmentService
37+
) {
38+
self.client = client
39+
40+
defaultHeadersRequestHandler = DefaultHeadersRequestHandler(
41+
appName: "Bitwarden_Authenticator_Mobile",
42+
appVersion: Bundle.main.appVersion,
43+
buildNumber: Bundle.main.buildNumber,
44+
systemDevice: UIDevice.current
45+
)
46+
47+
apiUnauthenticatedService = HTTPService(
48+
baseURLGetter: { environmentService.apiURL },
49+
client: client,
50+
requestHandlers: [defaultHeadersRequestHandler],
51+
responseHandlers: [responseValidationHandler]
52+
)
53+
}
54+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import BitwardenKit
2+
import TestHelpers
3+
import XCTest
4+
5+
@testable import AuthenticatorShared
6+
@testable import Networking
7+
8+
class APIServiceTests: BitwardenTestCase {
9+
var subject: APIService!
10+
11+
override func setUp() {
12+
super.setUp()
13+
14+
subject = APIService(client: MockHTTPClient())
15+
}
16+
17+
override func tearDown() {
18+
super.tearDown()
19+
20+
subject = nil
21+
}
22+
23+
// MARK: Tests
24+
25+
/// `init(client:)` sets the default base URLs for the HTTP services.
26+
func test_init_defaultURLs() {
27+
let apiUnauthenticatedServiceBaseURL = subject.apiUnauthenticatedService.baseURL
28+
XCTAssertEqual(apiUnauthenticatedServiceBaseURL, URL(string: "https://example.com/api")!)
29+
XCTAssertTrue(
30+
subject.apiUnauthenticatedService.requestHandlers.contains(where: { $0 is DefaultHeadersRequestHandler })
31+
)
32+
XCTAssertNil(subject.apiUnauthenticatedService.tokenProvider)
33+
}
34+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import BitwardenKit
2+
import BitwardenKitMocks
3+
import Networking
4+
5+
@testable import AuthenticatorShared
6+
7+
extension APIService {
8+
convenience init(
9+
client: HTTPClient
10+
) {
11+
self.init(
12+
client: client,
13+
environmentService: MockEnvironmentService()
14+
)
15+
}
16+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// swiftlint:disable:this file_name
2+
3+
import BitwardenKit
4+
import Foundation
5+
6+
// MARK: - DefaultEnvironmentService
7+
8+
/// A default implementation of an `EnvironmentService` which manages the app's environment URLs.
9+
///
10+
class DefaultEnvironmentService: EnvironmentService {
11+
// MARK: Private Properties
12+
13+
/// The app's current environment URLs.
14+
private var environmentURLs: EnvironmentURLs
15+
16+
// MARK: Initialization
17+
18+
/// Initialize a `DefaultEnvironmentService`.
19+
///
20+
init() {
21+
environmentURLs = EnvironmentURLs(environmentURLData: .defaultUS)
22+
}
23+
24+
// MARK: EnvironmentService
25+
26+
func loadURLsForActiveAccount() async {}
27+
28+
func setPreAuthURLs(urls: BitwardenKit.EnvironmentURLData) async {}
29+
}
30+
31+
extension DefaultEnvironmentService {
32+
var apiURL: URL {
33+
environmentURLs.apiURL
34+
}
35+
36+
var baseURL: URL {
37+
environmentURLs.baseURL
38+
}
39+
40+
var changeEmailURL: URL {
41+
environmentURLs.changeEmailURL
42+
}
43+
44+
var eventsURL: URL {
45+
environmentURLs.eventsURL
46+
}
47+
48+
var iconsURL: URL {
49+
environmentURLs.iconsURL
50+
}
51+
52+
var identityURL: URL {
53+
environmentURLs.identityURL
54+
}
55+
56+
var importItemsURL: URL {
57+
environmentURLs.importItemsURL
58+
}
59+
60+
var recoveryCodeURL: URL {
61+
environmentURLs.recoveryCodeURL
62+
}
63+
64+
var region: RegionType {
65+
if environmentURLs.baseURL == EnvironmentURLData.defaultUS.base {
66+
return .unitedStates
67+
} else if environmentURLs.baseURL == EnvironmentURLData.defaultEU.base {
68+
return .europe
69+
} else {
70+
return .selfHosted
71+
}
72+
}
73+
74+
var sendShareURL: URL {
75+
environmentURLs.sendShareURL
76+
}
77+
78+
var settingsURL: URL {
79+
environmentURLs.settingsURL
80+
}
81+
82+
var setUpTwoFactorURL: URL {
83+
environmentURLs.setUpTwoFactorURL
84+
}
85+
86+
var webVaultURL: URL {
87+
environmentURLs.webVaultURL
88+
}
89+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import BitwardenKit
2+
import BitwardenKitMocks
3+
import XCTest
4+
5+
@testable import AuthenticatorShared
6+
7+
class EnvironmentServiceTests: XCTestCase {
8+
// MARK: Properties
9+
10+
var subject: EnvironmentService!
11+
12+
// MARK: Setup & Teardown
13+
14+
override func setUp() {
15+
super.setUp()
16+
17+
subject = DefaultEnvironmentService()
18+
}
19+
20+
override func tearDown() {
21+
super.tearDown()
22+
23+
subject = nil
24+
}
25+
26+
// MARK: Tests
27+
28+
/// The default US URLs are returned.
29+
func test_defaultUrls() {
30+
XCTAssertEqual(subject.apiURL, URL(string: "https://api.bitwarden.com"))
31+
XCTAssertEqual(subject.baseURL, URL(string: "https://vault.bitwarden.com"))
32+
XCTAssertEqual(subject.changeEmailURL, URL(string: "https://vault.bitwarden.com/#/settings/account"))
33+
XCTAssertEqual(subject.eventsURL, URL(string: "https://events.bitwarden.com"))
34+
XCTAssertEqual(subject.iconsURL, URL(string: "https://icons.bitwarden.net"))
35+
XCTAssertEqual(subject.identityURL, URL(string: "https://identity.bitwarden.com"))
36+
XCTAssertEqual(subject.importItemsURL, URL(string: "https://vault.bitwarden.com/#/tools/import"))
37+
XCTAssertEqual(subject.recoveryCodeURL, URL(string: "https://vault.bitwarden.com/#/recover-2fa"))
38+
XCTAssertEqual(subject.region, .unitedStates)
39+
XCTAssertEqual(subject.sendShareURL, URL(string: "https://send.bitwarden.com/#"))
40+
XCTAssertEqual(subject.settingsURL, URL(string: "https://vault.bitwarden.com/#/settings"))
41+
// swiftlint:disable:next line_length
42+
XCTAssertEqual(subject.setUpTwoFactorURL, URL(string: "https://vault.bitwarden.com/#/settings/security/two-factor"))
43+
XCTAssertEqual(subject.webVaultURL, URL(string: "https://vault.bitwarden.com"))
44+
}
45+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Foundation
2+
3+
// MARK: - EnvironmentService
4+
5+
/// A protocol for an `EnvironmentService` which manages the app's environment URLs.
6+
///
7+
public protocol EnvironmentService {
8+
/// The URL for the API.
9+
var apiURL: URL { get }
10+
11+
/// The environment's base URL.
12+
var baseURL: URL { get }
13+
14+
/// The URL for changing email address.
15+
var changeEmailURL: URL { get }
16+
17+
/// The URL for the events API.
18+
var eventsURL: URL { get }
19+
20+
/// The URL for the icons API.
21+
var iconsURL: URL { get }
22+
23+
/// The URL for the identity API.
24+
var identityURL: URL { get }
25+
26+
/// The URL for importing items.
27+
var importItemsURL: URL { get }
28+
29+
/// The URL for the recovery code help page.
30+
var recoveryCodeURL: URL { get }
31+
32+
/// The region of the current environment.
33+
var region: RegionType { get }
34+
35+
/// The URL for sharing a send.
36+
var sendShareURL: URL { get }
37+
38+
/// The URL for vault settings.
39+
var settingsURL: URL { get }
40+
41+
/// The URL for setting up two-factor login.
42+
var setUpTwoFactorURL: URL { get }
43+
44+
/// The URL for the web vault.
45+
var webVaultURL: URL { get }
46+
47+
/// Loads the URLs for the active account into the environment. This can be called on app launch
48+
/// whether there's an active account or not to pre-populate the environment. If there's no
49+
/// active account, the US URLs will be used.
50+
///
51+
func loadURLsForActiveAccount() async
52+
53+
/// Sets the pre-auth URLs for the environment. This should be called if there isn't an an
54+
/// active account on app launch or if the user navigates through the add/create account flow.
55+
///
56+
/// - Parameter urls: The URLs to set and use prior to user authentication.
57+
///
58+
func setPreAuthURLs(urls: EnvironmentURLData) async
59+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Foundation
2+
3+
@testable import BitwardenKit
4+
5+
public class MockEnvironmentService: EnvironmentService {
6+
public var didLoadURLsForActiveAccount = false
7+
public var setActiveAccountEnvironmentURLsData: EnvironmentURLData?
8+
public var setPreAuthEnvironmentURLsData: EnvironmentURLData?
9+
10+
public var apiURL = URL(string: "https://example.com/api")!
11+
public var baseURL = URL(string: "https://example.com")!
12+
public var changeEmailURL = URL(string: "https://example.com/#/settings/account")!
13+
public var eventsURL = URL(string: "https://example.com/events")!
14+
public var iconsURL = URL(string: "https://example.com/icons")!
15+
public var identityURL = URL(string: "https://example.com/identity")!
16+
public var importItemsURL = URL(string: "https://example.com/#/tools/import")!
17+
public var recoveryCodeURL = URL(string: "https://example.com/#/recover-2fa")!
18+
public var region = RegionType.selfHosted
19+
public var sendShareURL = URL(string: "https://example.com/#/send")!
20+
public var settingsURL = URL(string: "https://example.com/#/settings")!
21+
public var setUpTwoFactorURL = URL(string: "https://example.com/#/settings/security/two-factor")!
22+
public var webVaultURL = URL(string: "https://example.com")!
23+
24+
public init() {}
25+
26+
public func loadURLsForActiveAccount() async {
27+
didLoadURLsForActiveAccount = true
28+
}
29+
30+
public func setActiveAccountURLs(urls: EnvironmentURLData) {
31+
setActiveAccountEnvironmentURLsData = urls
32+
}
33+
34+
public func setPreAuthURLs(urls: EnvironmentURLData) async {
35+
setPreAuthEnvironmentURLsData = urls
36+
}
37+
}

BitwardenShared/Core/Auth/Services/API/Organization/OrganizationAPIServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TestHelpers
12
import XCTest
23

34
@testable import BitwardenShared

BitwardenShared/Core/Auth/Services/API/OrganizationUser/OrganizationUserAPIServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TestHelpers
12
import XCTest
23

34
@testable import BitwardenShared

BitwardenShared/Core/Auth/Services/CaptchaService.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import BitwardenKit
12
import Foundation
23

34
// MARK: - CaptchaURLError

BitwardenShared/Core/Auth/Services/CaptchaServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import BitwardenKitMocks
12
import XCTest
23

34
@testable import BitwardenShared

BitwardenShared/Core/Auth/Services/TrustDeviceServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import BitwardenSdk
2+
import TestHelpers
23
import XCTest
34

45
@testable import BitwardenShared

BitwardenShared/Core/Platform/Services/API/APIServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TestHelpers
12
import XCTest
23

34
@testable import BitwardenKit

BitwardenShared/Core/Platform/Services/API/AccountTokenProviderTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Networking
2+
import TestHelpers
23
import XCTest
34

45
@testable import BitwardenShared

BitwardenShared/Core/Platform/Services/API/ConfigAPIServiceTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import BitwardenKit
2+
import BitwardenKitMocks
3+
import TestHelpers
24
import XCTest
35

46
@testable import BitwardenShared

BitwardenShared/Core/Platform/Services/API/EventAPIServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TestHelpers
12
import XCTest
23

34
@testable import BitwardenShared

BitwardenShared/Core/Platform/Services/API/NotificationAPIServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TestHelpers
12
import XCTest
23

34
@testable import BitwardenShared

0 commit comments

Comments
 (0)