Skip to content

Commit

Permalink
feat(storage): add createSignedURLs method (#273)
Browse files Browse the repository at this point in the history
* feat: add createSignedURLs method

* Add storage example and storage test
  • Loading branch information
grdsdev authored Mar 21, 2024
1 parent fca6721 commit 77e5c3d
Show file tree
Hide file tree
Showing 23 changed files with 543 additions and 102 deletions.
24 changes: 24 additions & 0 deletions Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
7962989D2AEBC6F9000AA957 /* SVGView in Frameworks */ = {isa = PBXBuildFile; productRef = 7962989C2AEBC6F9000AA957 /* SVGView */; };
79719ECE2ADF26C400737804 /* Supabase in Frameworks */ = {isa = PBXBuildFile; productRef = 79719ECD2ADF26C400737804 /* Supabase */; };
797D664A2B46A1D8007592ED /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797D66492B46A1D8007592ED /* Dependencies.swift */; };
797EFB662BABD82A00098D6B /* BucketList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797EFB652BABD82A00098D6B /* BucketList.swift */; };
797EFB682BABD90500098D6B /* Stringfy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797EFB672BABD90500098D6B /* Stringfy.swift */; };
797EFB6A2BABDF3800098D6B /* BucketDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797EFB692BABDF3800098D6B /* BucketDetailView.swift */; };
797EFB6C2BABE1B800098D6B /* FileObjectDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797EFB6B2BABE1B800098D6B /* FileObjectDetailView.swift */; };
7993B8A92B3C673A009B610B /* AuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7993B8A82B3C673A009B610B /* AuthView.swift */; };
7993B8AB2B3C67E0009B610B /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7993B8AA2B3C67E0009B610B /* Toast.swift */; };
79AF047F2B2CE207008761AD /* AuthWithEmailAndPassword.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79AF047E2B2CE207008761AD /* AuthWithEmailAndPassword.swift */; };
Expand Down Expand Up @@ -87,6 +91,10 @@
796298982AEBBA77000AA957 /* MFAFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFAFlow.swift; sourceTree = "<group>"; };
7962989A2AEBBD9F000AA957 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
797D66492B46A1D8007592ED /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = "<group>"; };
797EFB652BABD82A00098D6B /* BucketList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BucketList.swift; sourceTree = "<group>"; };
797EFB672BABD90500098D6B /* Stringfy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stringfy.swift; sourceTree = "<group>"; };
797EFB692BABDF3800098D6B /* BucketDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BucketDetailView.swift; sourceTree = "<group>"; };
797EFB6B2BABE1B800098D6B /* FileObjectDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileObjectDetailView.swift; sourceTree = "<group>"; };
7993B8A82B3C673A009B610B /* AuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthView.swift; sourceTree = "<group>"; };
7993B8AA2B3C67E0009B610B /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = "<group>"; };
7993B8AC2B3C97B6009B610B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -182,6 +190,7 @@
793895C82954ABFF0044F2B8 /* Examples */ = {
isa = PBXGroup;
children = (
797EFB642BABD7FF00098D6B /* Storage */,
79AF04822B2CE3BD008761AD /* Auth */,
7962989A2AEBBD9F000AA957 /* Info.plist */,
793895CD2954AC000044F2B8 /* Assets.xcassets */,
Expand All @@ -201,6 +210,7 @@
793E03082B2CED5D00AC7DED /* Contants.swift */,
793E030A2B2CEDDA00AC7DED /* ActionState.swift */,
79E2B55B2B97A2310042CD21 /* UIApplicationExtensions.swift */,
797EFB672BABD90500098D6B /* Stringfy.swift */,
);
path = Examples;
sourceTree = "<group>";
Expand All @@ -220,6 +230,16 @@
name = Frameworks;
sourceTree = "<group>";
};
797EFB642BABD7FF00098D6B /* Storage */ = {
isa = PBXGroup;
children = (
797EFB652BABD82A00098D6B /* BucketList.swift */,
797EFB692BABDF3800098D6B /* BucketDetailView.swift */,
797EFB6B2BABE1B800098D6B /* FileObjectDetailView.swift */,
);
path = Storage;
sourceTree = "<group>";
};
79AF04822B2CE3BD008761AD /* Auth */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -452,6 +472,7 @@
7956406A2955AFBD0088A06F /* ErrorText.swift in Sources */,
79AF04812B2CE261008761AD /* AuthView.swift in Sources */,
794EF1242955F3DE008C9526 /* TodoListRow.swift in Sources */,
797EFB662BABD82A00098D6B /* BucketList.swift in Sources */,
79E2B55C2B97A2310042CD21 /* UIApplicationExtensions.swift in Sources */,
794EF1222955F26A008C9526 /* AddTodoListView.swift in Sources */,
7956405E2954ADE00088A06F /* Secrets.swift in Sources */,
Expand All @@ -462,6 +483,9 @@
795640622955AD2B0088A06F /* HomeView.swift in Sources */,
7940E3152B36187A0089BEE1 /* GoogleSignInWithWebFlow.swift in Sources */,
793895CA2954ABFF0044F2B8 /* ExamplesApp.swift in Sources */,
797EFB682BABD90500098D6B /* Stringfy.swift in Sources */,
797EFB6C2BABE1B800098D6B /* FileObjectDetailView.swift in Sources */,
797EFB6A2BABDF3800098D6B /* BucketDetailView.swift in Sources */,
793E030D2B2DAB5700AC7DED /* SignInWithApple.swift in Sources */,
793E030B2B2CEDDA00AC7DED /* ActionState.swift in Sources */,
);
Expand Down
18 changes: 10 additions & 8 deletions Examples/Examples/Auth/AuthView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@ struct AuthView: View {
}

var body: some View {
List {
ForEach(Option.allCases, id: \.self) { option in
NavigationLink(option.title, value: option)
NavigationStack {
List {
ForEach(Option.allCases, id: \.self) { option in
NavigationLink(option.title, value: option)
}
}
.navigationDestination(for: Option.self) { options in
options
.navigationTitle(options.title)
}
.navigationBarTitleDisplayMode(.inline)
}
.navigationDestination(for: Option.self) { options in
options
.navigationTitle(options.title)
}
.navigationBarTitleDisplayMode(.inline)
}
}

Expand Down
7 changes: 3 additions & 4 deletions Examples/Examples/Auth/AuthWithEmailAndPassword.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ struct AuthWithEmailAndPassword: View {
}
}

if case let .result(.failure(error)) = actionState {
ErrorText(error)
}

switch actionState {
case .idle:
EmptyView()
Expand Down Expand Up @@ -86,6 +82,7 @@ struct AuthWithEmailAndPassword: View {
.animation(.default, value: mode)
}

@MainActor
func primaryActionButtonTapped() async {
do {
actionState = .inFlight
Expand All @@ -110,6 +107,7 @@ struct AuthWithEmailAndPassword: View {
}
}

@MainActor
private func onOpenURL(_ url: URL) async {
do {
try await supabase.auth.session(from: url)
Expand All @@ -118,6 +116,7 @@ struct AuthWithEmailAndPassword: View {
}
}

@MainActor
private func resendConfirmationButtonTapped() async {
do {
try await supabase.auth.resend(email: email, type: .signup)
Expand Down
11 changes: 7 additions & 4 deletions Examples/Examples/ExamplesApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ struct ExamplesApp: App {
let supabase = SupabaseClient(
supabaseURL: Secrets.supabaseURL,
supabaseKey: Secrets.supabaseAnonKey,
options: .init(auth: .init(storage: KeychainLocalStorage(
service: "supabase.gotrue.swift",
accessGroup: nil
)))
options: .init(global: .init(logger: ConsoleLogger()))
)

struct ConsoleLogger: SupabaseLogger {
func log(message: SupabaseLogMessage) {
print(message)
}
}
36 changes: 20 additions & 16 deletions Examples/Examples/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Guilherme Souza on 23/12/22.
//

import Supabase
import SwiftUI

struct HomeView: View {
Expand All @@ -13,28 +14,31 @@ struct HomeView: View {
@State private var mfaStatus: MFAStatus?

var body: some View {
TodoListView()
.toolbar {
ToolbarItemGroup(placement: .cancellationAction) {
Button("Sign out") {
Task {
try! await supabase.auth.signOut()
}
NavigationStack {
BucketList()
.navigationDestination(for: Bucket.self, destination: BucketDetailView.init)
}
.toolbar {
ToolbarItemGroup(placement: .cancellationAction) {
Button("Sign out") {
Task {
try! await supabase.auth.signOut()
}
}

Button("Reauthenticate") {
Task {
try! await supabase.auth.reauthenticate()
}
Button("Reauthenticate") {
Task {
try! await supabase.auth.reauthenticate()
}
}
}
.task {
}
.task {
// mfaStatus = await verifyMFAStatus()
}
.sheet(unwrapping: $mfaStatus) { $mfaStatus in
MFAFlow(status: mfaStatus)
}
}
.sheet(unwrapping: $mfaStatus) { $mfaStatus in
MFAFlow(status: mfaStatus)
}
}

private func verifyMFAStatus() async -> MFAStatus? {
Expand Down
10 changes: 4 additions & 6 deletions Examples/Examples/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ struct RootView: View {
@Environment(AuthController.self) var auth

var body: some View {
NavigationStack {
if auth.session == nil {
AuthView()
} else {
HomeView()
}
if auth.session == nil {
AuthView()
} else {
HomeView()
}
}
}
Expand Down
87 changes: 87 additions & 0 deletions Examples/Examples/Storage/BucketDetailView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// BucketDetailView.swift
// Examples
//
// Created by Guilherme Souza on 21/03/24.
//

import Supabase
import SwiftUI

struct BucketDetailView: View {
let bucket: Bucket

@State private var fileObjects = ActionState<[FileObject], Error>.idle
@State private var presentBucketDetails = false

var body: some View {
Group {
switch fileObjects {
case .idle:
Color.clear
case .inFlight:
ProgressView()
case let .result(.success(files)):
List {
ForEach(files) { file in
NavigationLink(file.name, value: file)
}
}
case let .result(.failure(error)):
VStack {
ErrorText(error)
Button("Retry") {
Task { await load() }
}
}
}
}
.task { await load() }
.navigationTitle("Objects")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
presentBucketDetails = true
} label: {
Label("Detail", systemImage: "info.circle")
}
}
}
.popover(isPresented: $presentBucketDetails) {
ScrollView {
Text(stringfy(bucket))
.monospaced()
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
}
.navigationDestination(for: FileObject.self) {
FileObjectDetailView(api: supabase.storage.from(bucket.id), fileObject: $0)
}
}

@MainActor
private func load() async {
fileObjects = .inFlight
fileObjects = await .result(
Result {
try await supabase.storage.from(bucket.id).list()
}
)
}
}

#Preview {
BucketDetailView(
bucket: Bucket(
id: UUID().uuidString,
name: "name",
owner: "owner",
isPublic: false,
createdAt: Date(),
updatedAt: Date(),
allowedMimeTypes: nil,
fileSizeLimit: nil
)
)
}
75 changes: 75 additions & 0 deletions Examples/Examples/Storage/BucketList.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// BucketList.swift
// Examples
//
// Created by Guilherme Souza on 21/03/24.
//

import Supabase
import SwiftUI

struct BucketList: View {
@State var buckets = ActionState<[Bucket], Error>.idle

var body: some View {
Group {
switch buckets {
case .idle:
Color.clear
case .inFlight:
ProgressView()
case let .result(.success(buckets)):
List {
ForEach(buckets, id: \.self) { bucket in
NavigationLink(bucket.name, value: bucket)
}
}
.overlay {
if buckets.isEmpty {
Text("No buckets found.")
}
}
case let .result(.failure(error)):
VStack {
ErrorText(error)
Button("Retry") {
Task {
await load()
}
}
}
}
}
.task {
await load()
}
.navigationTitle("Bucket list")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button("Add") {
Task {
do {
try await supabase.storage.createBucket("bucket-\(UUID().uuidString)")
await load()
} catch {}
}
}
}
}
}

@MainActor
private func load() async {
do {
self.buckets = .inFlight
let buckets = try await supabase.storage.listBuckets()
self.buckets = .result(.success(buckets))
} catch {
buckets = .result(.failure(error))
}
}
}

#Preview {
BucketList()
}
Loading

0 comments on commit 77e5c3d

Please sign in to comment.