diff --git a/Examples/UserManagement/ProfileView.swift b/Examples/UserManagement/ProfileView.swift index aee4e4902..7285239fa 100644 --- a/Examples/UserManagement/ProfileView.swift +++ b/Examples/UserManagement/ProfileView.swift @@ -167,14 +167,15 @@ struct ProfileView: View { private func uploadImage() async throws -> String? { guard let data = avatarImage?.data else { return nil } - let filePath = "\(UUID().uuidString).jpeg" + let userId = try await supabase.auth.session.user.id.uuidString + let filePath = "\(userId)/profile.jpeg" try await supabase.storage .from("avatars") .upload( path: filePath, file: data, - options: FileOptions(contentType: "image/jpeg") + options: FileOptions(contentType: "image/jpeg", upsert: true) ) return filePath diff --git a/Examples/UserManagement/supabase/migrations/20240125111924_init.sql b/Examples/UserManagement/supabase/migrations/20240125111924_init.sql index e71e8697c..4cd25f8f7 100644 --- a/Examples/UserManagement/supabase/migrations/20240125111924_init.sql +++ b/Examples/UserManagement/supabase/migrations/20240125111924_init.sql @@ -49,16 +49,23 @@ insert into storage.buckets(id, name) -- Set up access controls for storage. -- See https://supabase.com/docs/guides/storage/security/access-control#policy-examples for more details. -create policy "Avatar images are publicly accessible." on storage.objects - for select - using (bucket_id = 'avatars'); +create policy "Give users access to own folder 1oj01fe_0" on storage.objects + for select to authenticated + using (bucket_id = 'avatars' + and LOWER(auth.uid()::text) = LOWER((storage.foldername(name))[1])); -create policy "Anyone can upload an avatar." on storage.objects - for insert - with check (bucket_id = 'avatars'); +create policy "Give users access to own folder 1oj01fe_1" on storage.objects + for insert to authenticated + with check (bucket_id = 'avatars' + and LOWER(auth.uid()::text) = LOWER((storage.foldername(name))[1])); -create policy "Anyone can update their own avatar." on storage.objects - for update - using (auth.uid() = owner) - with check (bucket_id = 'avatars'); +create policy "Give users access to own folder 1oj01fe_2" on storage.objects + for update to authenticated + using (bucket_id = 'avatars' + and LOWER(auth.uid()::text) = LOWER((storage.foldername(name))[1])); + +create policy "Give users access to own folder 1oj01fe_3" on storage.objects + for delete to authenticated + using (bucket_id = 'avatars' + and LOWER(auth.uid()::text) = LOWER((storage.foldername(name))[1])); diff --git a/Sources/Storage/StorageFileApi.swift b/Sources/Storage/StorageFileApi.swift index 85dfa9c6b..cbfd01784 100644 --- a/Sources/Storage/StorageFileApi.swift +++ b/Sources/Storage/StorageFileApi.swift @@ -71,9 +71,11 @@ public class StorageFileApi: StorageApi { /// - file: The Data to be stored in the bucket. /// - options: HTTP headers. For example `cacheControl` @discardableResult - public func upload(path: String, file: Data, options: FileOptions = FileOptions()) - async throws -> String - { + public func upload( + path: String, + file: Data, + options: FileOptions = FileOptions() + ) async throws -> String { try await uploadOrUpdate(method: .post, path: path, file: file, options: options) } @@ -84,9 +86,11 @@ public class StorageFileApi: StorageApi { /// - file: The Data to be stored in the bucket. /// - options: HTTP headers. For example `cacheControl` @discardableResult - public func update(path: String, file: Data, options: FileOptions = FileOptions()) - async throws -> String - { + public func update( + path: String, + file: Data, + options: FileOptions = FileOptions() + ) async throws -> String { try await uploadOrUpdate(method: .put, path: path, file: file, options: options) }