はじめに
個人開発を進める際に、supabaseを用いたバックエンド開発に挑戦しました。
その際、emailとpasswordに加えてユーザーのニックネームも保存をしたかったのですが、公式サイトの実装方法が少し古いものだったり、インターネット検索もうまくヒットしなかったりと、かなり時間を費やしたので、備忘録も兼ねて実装内容をまとめようと思います。
これから実装する方の参考になれば幸いです。
前提
言語はTypeScript、フレームワークはNext.js、コードエディタはVScodeを使用しています。
ORMにはPrismaを使用して、prisma.schemaに記述したテーブル情報をsupabaseのDatabaseに反映させました。
また、この記事はSupabaseのsignIn()メソッドでユーザーの新規登録機能が実装されている前提で記載しています。未実装の方はユーザー登録実装後に参考にしてください。
私が実装したかったこと
個人開発のアプリケーションでは、当初以下のようなテーブル設計を想定していました。
※全てのカラムを書くと長くなるので、必要な箇所だけ抜粋します。
model Owner {
id String @id @default(uuid()) @db.Uuid
nickname String
email String
password String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("owners")
}
ownersテーブルに対して、ユーザー認証に必要なemailとpasswordの情報、さらにニックネームを保存する構成です。
しかし、Supabase Auth機能を使えば、簡単に認証・認可機能を実装できるため、ownersテーブルで全ての情報を管理するのではなく、「emailとpasswordはauth.usersテーブルに、nicknameはownersテーブルに保存する」出来ないかと考えました。
イメージ図
実装した内容
結論、supabaseのtriggerを活用することでユーザーの新規登録がされたら、同時に他のテーブルにもデータ保存ができるようになります。
今回実装する内容は、以下の4つです。
- signUp()メソッドでnicknameの情報を渡す
- auth.usersテーブルとownersテーブルを外部キーで紐づける
- ownersテーブルに書き込みするfunctionを作る
- auth.usersテーブルにレコード追加がされたら、2.のfunctionが実行されるように設定する
1. signUp()メソッドでnicknameの情報を渡す
以下のようにsignUp()でoptionを設定します。こうすることで、ユーザー登録をする際にJSON形式で追加情報を送ることができます。
今回はnicknameカラムを設定しました。
const { data, error } = await supabase.auth.signUp({
email: 'example@email.com',
password: 'example-password',
options: {
data: {
nickname: 'John',
},
},
})
2. auth.usersテーブルとownersテーブルを外部キーで紐づける
まず、ownersテーブルのidカラムとauth.usersテーブルのidカラムを紐付けします。
ownersテーブルのレコードと、auth.usersテーブルのレコードで同一のuuid情報を保持することで、同一ユーザーと識別させることができます。
2-1.Tableを編集する
supabaseのdashboardを開き、サイドバーの「Table Editor」をクリックします。
その後変更したいテーブル名の右横にある「3点リーダー」> 「Edit Table」の順に選択してください。
2-2.idカラムに紐付け設定をする。
「Edit Table」をクリックすると、以下のような画面が表示されます。
真ん中あたりにあるColumnからidカラムを選択し、リンクのアイコンをクリックします。
リンクをクリックすると、紐づけるテーブルとカラムを選択できます。
画像と同じように設定してください。
2-3.オプション設定する
画面下部にある「Action if referenced row removed」で「Cascade」を選択します。
この設定をすることで、auth.usersのレコードが削除された場合は、関連するownersテーブルのデータも一緒に削除することができます。
最後にSaveボタンを押して保存をしてください。
これでownersテーブルのidカラムに、auth.usersテーブルのidカラムを紐付けすることができました。
3. ownersテーブルに書き込みするfunctionを作る
続いて、ownersテーブルにnicknameカラムを書き込みするためのfunction(関数)を作ります。
こちらの動画のように、SQLで作成することもできますが、今回はdashboardから作成します。
3-1. functionを作成する
dashboardのサイドバーにある「Functions」をクリックします。
すると設定画面が表示されるので、schemaで「public」を選択した状態で「Create a new function」をクリックします。
以下の画面でfunctionの作成をしていきます。画像のように設定してください。
-
Name of function
「関数名」を記載する箇所です。任意で名前を付けられます。 -
Return type
関数の戻り値を設定する箇所です。「trigger」を選択します。 -
Defenition
実行する関数を記載する箇所です。以下のように記載してください。
begin
insert into public.テーブル名 (カラム名1, カラム名2) //保存したいテーブル名とカラム名を記載する
values (
new.id,
new.raw_user_meta_data->>'保存したいカラム名',
);
return new;
end;
newとは?
valuesの値にnew.id
やnew.raw_user_meta_data
の記述があります。
このnew
は、新しくデータベースにデータ保存、更新、削除された際の新しいレコードを指します。
つまり、今回はauth.usersのテーブルにデータ保存がされた際に、このfunctionが実行されるためnew.id
でauth.usersテーブルのidカラムのデータを取得できます。
また、new.raw_user_meta_data
は、Supabaseのauth.users テーブルで使用されるフィールドの1つです。
このフィールドには、ユーザーに関連する追加情報を保存するためのJSONオブジェクトが含まれていて、メタデータやカスタムデータが格納されています。
{
"sub": "uuid形式のデータ",
"email": "example@email.com",
"nickname": "John",
"email_verified": false,
"phone_verified": false
}
なお、このraw_user_meta_dataには、signUp()メソッドで定義したoptionsのdata
オブジェクトが含まれます。
const { data, error } = await supabase.auth.signUp({
email: 'example@email.com',
password: 'example-password',
options: {
data: {
nickname: 'John',
},
},
})
option設定はこちらを合わせて参照してみてください。
3-2. Securityの設定をする
画面下部の「Type of Security」で「SECURITY DEFINEDER」を設定します。
この設定をすることで、この関数を作成したユーザーの権限を使って関数実行が可能になります。
4.auth.usersテーブルにレコード追加がされたら、2.のfunctionが実行されるように設定する
最後にTriggerを作成します。
Triggerとは特定のイベントと関数を紐付け、イベントの発生時に関数を発火させます。
今回は「auth.usersにレコードが追加された際に、関数実行する」という設定をしていきます。
4-1. triggerの作成をする
dashboardのサイドバーから「SQL Editor」をクリックします。
エディタが開くので、画像のように記述をします。
create trigger トリガー名 // ①任意のトリガー名
after insert on テーブル名 for each row // ②イベント対象になるテーブル。今回はauth.users
execute function 関数名 // ③2.の工程で作成した関数名を記載する
上記のように記載をしたら、画面の右下の「Run」ボタンをクリックします。
クリックすることで新規トリガーが作成されます。
4-2. トリガーの作成を確認する
dashboardの「Database」から「Trigger」を選択する。
schemaで「auth」をプルダウンから選択すると、先ほど作成したtriggerが確認できます。
挙動を確認する
ここまでの設定ができたら、アプリからユーザー登録をしましょう。
以下のようにownersテーブルにもnicknameカラムが保存されていることが確認できればOKです。
最後に
今回は主にdashboardから作成をしましたが、SQL Editorを使ってfunctionやtriggerを作る方法が公式サイトでは紹介されています。
なお、今回公式サイトの動画ではtriggerをdashboardのGUIから作っていましたが、現在その機能がないようです。(ここですごく手こずりました)
なのでSQLから作成することに慣れておく方がベターかもしれません