Supabase Storage RLS
Overview
Supabase StorageはPostgresデータベースと統合されています。
つまり、同じ行レベルのセキュリティポリシー
を使用することができます。Supabase Storageはストレージスキーマのobjectsとbucketsテーブルにメタデータを保存します。
ファイルへの読み取りアクセスを許可するには、RLS ポリシーでユーザーにオブジェクトテーブルの SELECT を許可し、新しいオブジェクトをアップロードするには、RLS ポリシーでユーザーにオブジェクトテーブルへの INSERT などのアクセスを許可する必要があります。各種 API 呼び出しと必要なデータベース権限との対応については、リファレンス ドキュメントを参照してください。
パブリックバケットとプライベートバケット#
ストレージバケットはデフォルトではプライベートです。プライベートバケットでは、ダウンロードメソッドでオブジェクトにアクセスできます。これは /object/auth/ API エンドポイントに相当します。
あるいは、/object/signUrl を呼び出す createSignedUrl メソッドを使って、有効期限付きの公開共有可能な URL を作成することもできます。
メソッドを使用して、有効期限付きの公開共有URLを作成することもできます。
公開バケットでは、トークンやAuthorisationヘッダなしで直接アセットにアクセスできます。getPublicUrl
ヘルパーメソッドは、アセットの完全な公開 URL を返します。これは、内部的に /object/public/ API エンドポイントを呼び出します。public Bucket 内のオブジェクトにアクセスする際には認可は不要ですが、public Bucket 内のオブジェクトをアップロードしたり削除したりする際には、適切なアクセス制御が必要になります。また、Public Bucket はパフォーマンスが向上する傾向があります。
summary
今回は、Supabase Storageに画像をアップロードしてみたいと思います。
やってることは単純だけど結構ハマりました😱
ルールの設定をする
作成しているBucketにルールを設定します。赤い丸がついている箇所のボタンを押していけば設定できます。
新しいルールを作成する
2番目の箇所を選択して、ボタンを押す
赤丸で囲んでいる箇所を全てチェックしてボタンを押す
画像をアップロードするソースコード
ログインした後のページで実行してます。
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:supabase_gorouter/extention/push.dart';
import 'package:supabase_gorouter/screen/sign_in_page.dart';
class HomePage extends ConsumerStatefulWidget {
const HomePage({super.key});
static const rootName = '/home_page';
ConsumerState<ConsumerStatefulWidget> createState() => _HomePageState();
}
class _HomePageState extends ConsumerState<HomePage> {
bool isUploading = false;
final supabase = Supabase.instance.client;
Future<void> uploadFile() async {
var pickedFile = await FilePicker.platform
.pickFiles(allowMultiple: false, type: FileType.image);
if (pickedFile != null) {
setState(() {
isUploading = true;
});
try {
File file = File(pickedFile.files.single.path!);
String fileName = pickedFile.files.first.name;
String uploadUrl = await supabase.storage
.from('profiles')
.upload("${supabase.auth.currentUser!.id}/$fileName", file);
setState(() {
isUploading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Uploaded $fileName'),
),
);
} catch (e) {
print(e.toString());
setState(() {
isUploading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Uploaded Error'),
),
);
}
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(actions: [
IconButton(
onPressed: () async {
await supabase.auth.signOut();
if (context.mounted) {
await context.toAndRemoveUntil(const SignInPage());
}
},
icon: const Icon(Icons.logout),
)
], title: const Text('Home Page')),
body: Center(
child: Column(
children: [
IconButton(
onPressed: () async {
await uploadFile();
},
icon: const Icon(Icons.upload))
],
),
),
);
}
}
アップロードに成功すると、画像がBucketに保存されます
thoughts
Firebase Storageは使ったことがあったのですが、Supabase Storageは使ったことがなくて、設定さえできていれば簡単に画像のアップロードができることを学べました。
Baasといえば、Firebaseが人気ですが、Supabaseも最近注目されているので、個人開発で使ってみたいな〜と思いました。
ConsumerStatefulWidgetを使用していますが、StatefulWidgetでもこのコードは使えます。ご興味ある方は、試してみてください。
ログインページはいらないかもしれません。
今回使用したパッケージ
全体のコード
こちらに完成したソースコードのリンクを貼っておきます。
Discussion