Supabase(スーパーベース・スパベース)の使い方4回目。
今回はこれまで作成してきたWebアプリに、RLS設定も行っていきます。本人しか編集・削除できなくしていきましょう。

RLSをオンにすると、セキュリティが爆上がりするの♪

爆上がり…。ぜひおさえておきたい設定だわ!
なお前回の記事を見ていない方は、まずはこちらをチェックしておいてくださいね。
RLSとはなにか
まずはRLSが何かについてから。RLSの正式名称はこちら。
Rowは、データベース内の各レコードのこと。つまり、データベース内のレコードひとつずつに対してセキュリティ設定を行えるということになります。

ちなみに、Rowは、Low(低い)にも似ているけど、Low Level Securityだと「低レベルのセキュリティ」になっちゃうから、間違えないでね。

一文字間違えただけで、意味が全く変わるのね。
具体的には、Supabase内でポリシーを設定していくことになります。ポリシーに合ったデータのみ登録・更新・削除・表示ができるという仕組みです。

今回はRLSをオフにしてあるけど、このままだと、誰でもデータにアクセスできちゃうし、変更もできちゃうんだ。

あら、困るわね。見るだけならいいけど、変更はされたくないわ。

だよね。それじゃここから、まずはRLSを有効にして、その後にポリシーを設定して、見れるけど変更はできないようにしていこう。
SupabaseのRLSを有効にする
RLSはデフォルトではオンになっています。ただ今回の連載では、便宜上RLSをオフにして進めていきました。もしオフになっている場合には、オンにしておいてくださいね。
Supabaseにログインして、サイドバーよりTable Editorを選択します。【RLS disabled】をクリックし、【Enable RLS for this table】ボタンをクリックします。

Supabaseのポリシーを設定する方法
次に、Supabaseのポリシーを設定します。Supabaseにログインして、サイドバーよりTable Editorを選択します。【Add RLS Policy】をクリックします。

【Create Policy】ボタンをクリックします。

次の画面となります。ここからポリシーを作っていきます。


ポリシーってなに?

アクセス制限って考えると分かりやすいかも。データにアクセスするためのルールを決めておくの。
今回は次のポリシーを設定します。
| 操作 | 内容 | 誰が実行できる? |
|---|---|---|
| SELECT | 表示 | ログイン済みユーザーのみ |
| INSERT | 新規作成 | ログイン済みユーザーのみ |
| UPDATE | 更新 | 本人のみ(自分が登録したデータ) |
| DELETE | 削除 | 本人のみ(自分が登録したデータ) |
上記に応じて4個のポリシーを作成します。

ポリシーって1個ずつ設定するのね。

ええ。ちょっと面倒だけど、でも操作ごとに細かく権限を設定できるから、セキュリティを高められるの。
SELECT(表示)ポリシー
まず表示用のポリシーを作成します。下記の画面で、Templates/SELECTを選ぶと、テンプレートが適用されます。
テンプレートでは、表示用のポリシーは「全員が見れる」となっています。今回はログインユーザーのみに表示したいので、Target Rolesをauthenticatedにしておきましょう。
作成後に保存します。

INSERT(新規作成)ポリシー
同じようにして、他のポリシーも作成していきます。
次はINSERT(新規作成)ポリシーを作ります。こちらも先ほどと同様の手順です。下記の画面で、Templates/INSERTを選ぶと、テンプレートが適用されます。
テンプレートでは、新規作成用のポリシーは「認証ユーザーのみ」となっています。これはそのままにしておきます。作成後に保存します。

UPDATE(更新)ポリシー
次にUPDATE(更新)ポリシーですが、これは、テーブルに手を加える必要があります。
本人のみ更新できるようには、データを登録する際に、「誰がデータを登録したか」を記録しておく必要があります。
bihinsテーブルに登録者情報を追加
Supabaseにログインし、Table Editor/bihinsテーブルの【Insert】ボタンから、Insert column(列を挿入)を選択します。

右側にカラム(列)設定用の画面が表示されます。Nameは【user_id】としておきます。Typeは【uuid】とし、Default Valueは(auth.uid())とします。
Default Valueは、新しいデータを登録するときに、自動的に入る値のことです。。(auth.uid())と設定すると、ログイン中のユーザーのIDが自動的に入ります。

最後に画面下の【add foreign key】ボタンをクリックします。すると、foreignkey設定画面がでてきます。foreignkeyを設定してきましょう。

foreign keyって?

外部キー。つまり、外部のテーブルと連携させるキーのこと。
今回は、bihinsテーブルのuser_idに、usersテーブルのid情報を紐づけていきます。これによって、だれがbihin(備品)を登録したかを記録できます。
foreign keyは、下記のように設定します。Actionは今回はデフォルトのままにしておきます。

UPDATEポリシーの作成
次にUPDATE(更新)ポリシーを作ります。UPDATE用に今回使えるテンプレートがないため、以下のように手動で設定します。

画面下部のSQLエディタで、以下のようなコードが生成されます:
|
1 2 3 4 5 6 7 8 9 10 |
Use options above to edit alter policy "Enable update for users based on user_id" on "public"."bihins" to authenticated using ( (( SELECT auth.uid() AS uid) = user_id) ) with check ( (( SELECT auth.uid() AS uid) = user_id) ); |
USINGは「どのデータを更新対象にするか」(既存のデータのチェック)、WITH CHECKは「更新後のデータが条件を満たしているか」(新しいデータのチェック)をチェックします。
設定が完了したら、【Save policy】ボタンをクリックして保存します。
DELETE(削除)ポリシー
最後にDELETE(削除)ポリシーを作成します。こちらはテンプレートが利用できます。下記の画面で、Templates/DELETEを選ぶと、テンプレートが適用されます。
これで本人が登録したデータのみ削除できるようになります。こちらもログインユーザーのみに表示したいので、Target Rolesをauthenticatedにしておきましょう。
作成後に保存します。

以上でポリシーの作成完了!

面倒だったけど、何をやっているかはわかってきたわ。

ポリシーはWebアプリによって変える必要があるけど、今回のように本人だけが更新・削除可能は、わりと定番パターンだと思うよ。また使ってみてね。
なおSupabaseの公式マニュアルでも、RLSで使用するポリシーの書き方の説明があります。より詳しく知りたい方は、こちらも参考にしてみてください。
Webアプリでテスト
Supabase側でRLS設定をしたので、ポリシーが有効になるはずです。実際にテストしてみてください。たとえば、花子さんが登録した備品は、太郎さんには編集・削除できないはずです。
【Webアプリ画面例】


あら!ちゃんと機能してる。

すごいでしょ
ただ、実際のWebアプリでは、ポリシーが効いているだけでは不完全です。たとえば、本人以外には、編集は削除ボタンが見れなくするといった変更も入れておくと、使いやすくなるでしょう。
【本人以外にはボタンは非表示にしたときの例】


このあたりはまた、生成AIにコードを書いてもらえるよ。

やっぱりユーザーの使い勝手も大事ね。
さいごに
RLS設定、いかがでしたか?
「誰が・何を・どこまでできるか」を柔軟に設定できる強力な機能です。今回は4つのポリシーを設定しましたが、社内備品管理アプリのセキュリティは大幅に向上しました。

たしかに…誰でもデータを登録したり変えたりできるって、考えたら危険よね。

データベース側で制御できるって、安心でしょ。
また続編記事も書いていきますが、続きにご興味あれば、Xアカウントフォローしてくださいね。

