Hasuraを利用して所有しているユーザーテーブルとAuth0のプロファイル情報を結合してみる
Hasuraのリモート結合という機能を使うと、テーブルとリモートデータソース間でデータを結合できます。
リモート結合は、既存のデータソースを変更したり影響を与えたりすることなく、さまざまなデータソースにまたがるデータを1つのデータベースであるかのように扱うことができる という利点があります。
マイクロサービス化や外部APIの使用など、データがいろんなとこに分散され、開発者はアクセスするのに苦労している といった背景がありこの機能ができたようです。
データベースの型とAPIから作成された型の間にリレーションをを作成したら、GraphQLクエリを実行してそれらを結合できます。 APIは、作成するカスタムGraphQLサーバー、サードパーティのSaaS API、またはその他のHasuraインスタンスにすることができます。
他のサービスの請求データとサービス独自のユーザーデータを結合して取得する、外部認証プロバイダーで認証したユーザーのプロファイルとサービス独自のユーザーデータを結合して取得する、別々のデータベース間でデータを結合する などのユースケースが考えられます。
では実際にやってみたいと思います。
今回は 外部認証プロバイダーで認証したユーザーのプロファイルとサービス独自のユーザーデータを結合して取得する というケースでやっていこうと思います。
やってみる
外部認証プロバイダーはAuth0を使用し、データベースはPostgresにします。
※ リモートリレーションシップの設定ができるのは現在Postgresだけかもしれません
※ BigQueryのテーブルではリモートリレーションシップの設定ができなかった
Postgresのテーブルを接続
usersというテーブルを作成し、Hasuraに接続します。
auth0_id
というカラムでAuth0のデータとリレーションを作るために用意しました。
Auth0のユーザープロファイルを取得し、GraphQLクエリで取得できる関数を作成する
Auth0のAPIからユーザー情報を取得し、GraphQLクエリでアクセスできる関数を作ります。
関数を実行する場所はご自身の好きな場所でOKです。
本記事ではGlitchというサービスを使って実行します。
auth0-graphql-server
で検索すると、そのまま使えるプロジェクトがヒットするので、ありがたく使わせてもらいます。
プロジェクトを作ったら、環境変数として以下をセットします。
AUTH0_ADMIN_TOKEN
: Auth0のmanagement APIを使うためのトークンAUTH0_ENDPOINT
: "https://<<テナントのドメイン>>/api/v2/users"
ソースコードはこちら
関数をリモートスキーマとして接続
作った関数をHasuraのリモートスキーマとして登録します
Hasuraのプロジェクト管理画面でRemote Schemas
のページにアクセスし、Add
ボタンを押します。
Remote Schema name
に接続名、GraphQL server URL
には作った関数にhttp経由でアクセスできるURLを入力します。
Postgresのテーブルにリモートリレーションシップを作る
Hasuraに接続したPostgresのテーブル(users)に移動し、Relationships
タブをクリックします。
Add a remote schema relationship
ボタンを押して設定していきましょう。
Name
: リレーションシップの名前を入力Remote Schema
: 追加したリモートスキーマを選択Configuration
: リモートスキーマのフィールドであるauth0_id
をこのテーブル(ここではusersテーブル)のauth0_idカラムに結合する
GraphQLクエリを作成
HasuraでGraphQLクエリを作成して、両方のデータを取得してみます。
query { users { zip birth Auth0Profile { nickname email last_login } } }
上記クエリだと、users
テーブルからzipとbirthを取得、
リモートスキーマのAuth0Profile
からnickname,email,last_login を取得します。
このように同時にデータを取得できました。
まとめ
HasuraのRemote Joinをやってみました。
外部のAPIや別のデータベースでも一つにしてクエリ結果が返ってくるのでとても使い勝手が良いと思います。
関連のあるデータの保存箇所がバラバラの場合、複数のクエリを実行してデータを取得しますが、これなら1回で済むので、このようなケースだと使っていきたいですね。