generated from StanfordBDHG/SwiftPackageTemplate
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Firebase Storage Configuration Component (#17)
<!-- This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) SPDX-License-Identifier: MIT --> # *Firebase Storage Configuration Component* ## ♻️ Current situation & Problem At the moment, `SpeziFirebase` offers no Configuration component for configuring the Firebase Storage functionality. This results in the need for users to configure the Firebase Storage themselves, independent of the Spezi ecosystem (which can potentially be dangerous!). ## ⚙️ Release Notes - `SpeziFirebase` now offers the `FirebaseStorageConfiguration` component to configure the Firebase Storage. ## 📚 Documentation Included ## ✅ Testing -- ## 📝 Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [X] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
- Loading branch information
1 parent
7e31453
commit 56dd7fb
Showing
13 changed files
with
276 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
Sources/SpeziFirebaseStorage/FirebaseStorageConfiguration.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import FirebaseStorage | ||
import Spezi | ||
import SpeziFirebaseConfiguration | ||
|
||
|
||
/// Configures the Firebase Storage that can then be used within any application via `Storage.storage()`. | ||
/// | ||
/// The ``FirebaseStorageConfiguration`` can be used to connect to the Firebase Storage emulator: | ||
/// ``` | ||
/// class ExampleAppDelegate: SpeziAppDelegate { | ||
/// override var configuration: Configuration { | ||
/// Configuration(standard: /* ... */) { | ||
/// FirebaseStorageConfiguration(emulatorSettings: (host: "localhost", port: 9199)) | ||
/// // ... | ||
/// } | ||
/// } | ||
/// } | ||
/// ``` | ||
public final class FirebaseStorageConfiguration: Component, DefaultInitializable { | ||
@Dependency private var configureFirebaseApp: ConfigureFirebaseApp | ||
|
||
private let emulatorSettings: (host: String, port: Int)? | ||
|
||
|
||
public required convenience init() { | ||
self.init(emulatorSettings: nil) | ||
} | ||
|
||
/// - Parameters: | ||
/// - emulatorSettings: The emulator settings. The default value is `nil`, connecting the FirebaseStorage module to the FirebaseStorage cloud instance. | ||
public init( | ||
emulatorSettings: (host: String, port: Int)? = nil | ||
) { | ||
self.emulatorSettings = emulatorSettings | ||
} | ||
|
||
|
||
public func configure() { | ||
if let emulatorSettings { | ||
Storage.storage().useEmulator(withHost: emulatorSettings.host, port: emulatorSettings.port) | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
Tests/UITests/TestApp/FirebaseStorageTests/FirebaseStorageTestsView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import FirebaseStorage | ||
import PDFKit | ||
import SpeziViews | ||
import SwiftUI | ||
|
||
|
||
struct FirebaseStorageTestsView: View { | ||
@State private var viewState: ViewState = .idle | ||
|
||
|
||
var body: some View { | ||
Button("Upload") { | ||
uploadFile() | ||
} | ||
.buttonStyle(.borderedProminent) | ||
.disabled(viewState == .processing) | ||
.viewStateAlert(state: $viewState) | ||
.navigationTitle("FirestoreDataStorage") | ||
} | ||
|
||
|
||
@MainActor | ||
private func uploadFile() { | ||
viewState = .processing | ||
Task { | ||
do { | ||
let ref = Storage.storage().reference().child("test.txt") | ||
let metadata = StorageMetadata() | ||
metadata.contentType = "text/plain" | ||
_ = try await ref.putDataAsync("Hello World!".data(using: .utf8) ?? .init(), metadata: metadata) | ||
viewState = .idle | ||
} catch { | ||
viewState = .error(AnyLocalizedError(error: error)) | ||
} | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Tests/UITests/TestApp/FirebaseStorageTests/StorageMetadata+Sendable.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import FirebaseStorage | ||
|
||
|
||
extension StorageMetadata: @unchecked Sendable {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
Tests/UITests/TestAppUITests/FirebaseStorageTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import XCTest | ||
import XCTestExtensions | ||
|
||
|
||
/// The `FirebaseStorageTests` require the Firebase Storage Emulator to run at port 9199. | ||
/// | ||
/// Refer to https://firebase.google.com/docs/emulator-suite#storage about more information about the | ||
/// Firebase Local Emulator Suite. | ||
final class FirebaseStorageTests: XCTestCase { | ||
struct FirebaseStorageItem: Decodable { | ||
let name: String | ||
let bucket: String | ||
} | ||
|
||
|
||
@MainActor | ||
override func setUp() async throws { | ||
try await super.setUp() | ||
|
||
try await deleteAllFiles() | ||
try await Task.sleep(for: .seconds(0.5)) | ||
} | ||
|
||
@MainActor | ||
func testFirebaseStorageFileUpload() async throws { | ||
let app = XCUIApplication() | ||
app.launch() | ||
XCTAssert(app.buttons["FirebaseStorage"].waitForExistence(timeout: 2.0)) | ||
app.buttons["FirebaseStorage"].tap() | ||
|
||
var documents = try await getAllFiles() | ||
XCTAssert(documents.isEmpty) | ||
|
||
XCTAssert(app.buttons["Upload"].waitForExistence(timeout: 2.0)) | ||
app.buttons["Upload"].tap() | ||
|
||
try await Task.sleep(for: .seconds(2.0)) | ||
documents = try await getAllFiles() | ||
XCTAssertEqual(documents.count, 1) | ||
} | ||
|
||
private func getAllFiles() async throws -> [FirebaseStorageItem] { | ||
let documentsURL = try XCTUnwrap( | ||
URL(string: "http://localhost:9199/v0/b/STORAGE_BUCKET/o") | ||
) | ||
let (data, response) = try await URLSession.shared.data(from: documentsURL) | ||
|
||
guard let urlResponse = response as? HTTPURLResponse, | ||
200...299 ~= urlResponse.statusCode else { | ||
print( | ||
""" | ||
The `FirebaseStorageTests` require the Firebase Storage Emulator to run at port 9199. | ||
Refer to https://firebase.google.com/docs/emulator-suite#storage about more information about the | ||
Firebase Local Emulator Suite. | ||
""" | ||
) | ||
throw URLError(.fileDoesNotExist) | ||
} | ||
|
||
struct ResponseWrapper: Decodable { | ||
let items: [FirebaseStorageItem] | ||
} | ||
|
||
do { | ||
return try JSONDecoder().decode(ResponseWrapper.self, from: data).items | ||
} catch { | ||
return [] | ||
} | ||
} | ||
|
||
private func deleteAllFiles() async throws { | ||
for storageItem in try await getAllFiles() { | ||
let url = try XCTUnwrap( | ||
URL(string: "http://localhost:9199/v0/b/STORAGE_BUCKET/o/\(storageItem.name)") | ||
) | ||
var request = URLRequest(url: url) | ||
request.httpMethod = "DELETE" | ||
|
||
let (_, response) = try await URLSession.shared.data(for: request) | ||
|
||
guard let urlResponse = response as? HTTPURLResponse, | ||
200...299 ~= urlResponse.statusCode else { | ||
print( | ||
""" | ||
The `FirebaseStorageTests` require the Firebase Storage Emulator to run at port 9199. | ||
Refer to https://firebase.google.com/docs/emulator-suite#storage about more information about the | ||
Firebase Local Emulator Suite. | ||
""" | ||
) | ||
throw URLError(.fileDoesNotExist) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.