Open4
Supabase で auth.user を削除する
サーバー側で deleteUser を実行する
const { error } = await supabase.auth.api.deleteUser(
user.id,
'YOUR_SERVICE_ROLE_KEY'
)
Storage に画像をアップロードしている場合、auth.user を削除しようとすると失敗する。
例えば、avatars という名前の bucket に画像をアップロードしている場合は、以下のような select のクエリを発行すると、storage の情報が返ってくる。
select * from storage.objects;
id | bucket_id | name | owner | created_at | updated_at | last_accessed_at | metadata | path_tokens |
---|---|---|---|---|---|---|---|---|
obj-id | avatars | img.png | uid | 2021-11-16T14:21:05.826Z | 2021-11-16T14:21:05.826Z | 2021-11-16T14:21:05.826Z | {"size":24292,"mimetype":"image/png","cacheControl":"max-age=31536000"} | ["img.png"] |
この画像を削除するためには、以下のような DELETE のコマンドを発行する。
DELETE FROM storage.objects WHERE owner = 'uid';
これでテーブルからデータが消えるし、storage からもユーザーが投稿した画像が消える。
しかし、ユーザーの退会ごとに上記のような SQL を発行することはできない。
そこで、以下のような function (ストアドファンクション)を用意する。
create or replace function public.handle_delete_user_created_objects()
returns boolean as $$
begin
delete from storage.objects where owner = auth.uid();
return true;
end;
$$ language plpgsql security definer;
すると、Database > functions に先ほど作成した関数が表示される。
この関数の API Doc を閲覧すると、以下のような JS のコードから関数を呼び出し可能だとわかる。
let { data, error } = await supabase
.rpc('handle_delete_user_created_objects')
if (error) console.error(error)
else console.log(data)
そこで、サーバー側で auth.userユーザーの削除処理をする前に、クライアント側からこの関数を実行すれば、全ての画像を削除することができる。
クライアント側で画像を削除した段階で、storage.objects の auth.user に対する依存関係がなくなるからだ。
// client
const { data, error } = await supabase.rpc('handle_delete_user_created_objects')
// server
const { error } = await supabase.auth.api.deleteUser(id, serviceRoleKey)
これでユーザーを削除することができた。
なお、上記でユーザーに紐づく public なテーブルの行は、users テーブルからのリレーションの条件 on delete cascade で全て自動的に削除されるものとする。
on delete cascade を設定していない場合、public なテーブルから user に関連する行を削除しなければならない