LoginSignup
1
0

とりあえずHasuraチュートリアルのデータベースはNeonがよい

Last updated at Posted at 2024-06-14

前提

CockroachDBという分散型のPostgreSQLに色気を出したばっかりにHasuraがCockroachDBへ完全対応していないという嵌り方で再度設定からやり直すことになった

ふと、何やら目立つNeonへの誘導バナーが有ることに気づく・・・なぜ最初に気づかなかった、いや、今しがた発生したに違いない。

image.png

Neon

  • ほどほどに良い無料枠が有る
  • Hasuraに薦められた今となってはこれ一択
  • しかも、どちらも同じGoogleアドレスで設定しておけば1クリックするだけで連携まで完結
  • 本日の3時間のエラーとの戦いは全て無に還った
  • 接続つまりConnectionした時点でNeon用のデータベースまで作成されている始末
  • Hasura + Neon だなこりゃ
    image.png

チュートリアルでハマったかもしれない型

image.png

  • なぜにidがTextなんだろうと思うでしょ
  • チュートリアルだとTextだけどタイポだと思ってInteger指定して、Todosテーブルの uiser_idInteger にしたんですよ。
  • そりゃそうでしょ、そうおもうでしょ。
  • そして、 forign key でお互い指定し合って
  • Relation 設定も完了しました
  • ここまで全て success 表示だったんですが気になるのはチュートリアルで Text 指定されていること・・・
  • 実際クエリを投げると、リレーションしているはずなのに呼び出されなかったんです・・・
  • ひょっとしたら私の何らかの間違いかもしれませんが、リレーションするidはHasuraだとText指定にする必要があるかもしれないという勝手な知見でした。
  • 該当チュートリアル: https://hasura.io/learn/ja/graphql/hasura/data-modeling/1-users-table/
  • image.png

大文字・小文字

  • IntegerのidでRelationできなかった理由がわかったかもしれないしわからないかもしれない
  • チュートリアルどおりに、 online_usersのRelationship Name設定している時に、 user 指定のものを User 指定にしたら query エラーになった。
  • このRelationship nameテーブル名かカラム名かと連携しているのか、そもそも小文字である必要があるのか不明だが、 user でないと通らない
  • ただ、 online_users テーブルと users テーブルの id リレーションだから、 Useruser かの連動は無いんじゃなかと
  • そして、 User でqueryエラーになるなら、そもそもRelation設定時に User をエラーにするのでは・・・みたいな勘ぐりがあるものの、そもそもチュートリアル通り小文字にしていない自分が悪い

image.png

RulesとHooksは無くなりActionsの利用に移行

Actionsをどう使えばよいかはわかってないがMarketplaceがあるのは好き

image.png

Actionsを利用する場合の手順

  1. Flowsを選択し、Loginを選択
  2. image.png
  3. Add Action を選択し、Custom tab を選択肢、Create Actionをクリック
  4. image.png
  5. Hasura JWT Claims とコピペして記載し、 Login / Post Login を選択肢、Node.jsの一番数字が大きいバージョンを選択し、Createする
  6. image.png
  7. 次のような画面が表示されるのでimage.png
  8. 次のコードをコピペして、Deploy を押す
Hasura JWT Claims
exports.onExecutePostLogin = async (event, api) => {
  if (event.authorization) {
    // do some custom logic to decide allowed roles
    const roles = ['user']

    api.accessToken.setCustomClaim('https://hasura.io/jwt/claims', {
      'x-hasura-default-role': 'user',
      // do some custom logic to decide allowed roles
      'x-hasura-allowed-roles': roles,
      'x-hasura-user-id': event.user.user_id
    });
  }
}

image.png

なんか追加で設定するHasura Sync Users

  • 英語のページに沿ってHasura Sync Usersも設定が必要
  • 設定は、Hasura JWT Claims同様に進み、Hasura JWT Claimsの部分を、Hasura Sync Usersに変えることと、次のコードを設定画面にコピペする(Hasuraの公式コードとは違う。違う理由はこの↓のコードはHasuraのTodoチュートリアルのDB仕様に基づいたものだから、UserId->idとUserName->nameが違う)
  • image.png
Hasura Sync Users(Auth0)
const fetch = require('node-fetch')

/**
 * Handler that will be called during the execution of a PostLogin flow.
 *
 * @param {Event} event - Details about the user and the context in which they are logging in.
 * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
 */
exports.onExecutePostLogin = async (event, api) => {
  const id = event.user.user_id;
  const name = event.user.name ?? null;


  const admin_secret = "YOUR_HASURA_GRAPHQL_ADMIN_SECRET";
  const url = "https://your-hasura-url.hasura.app/v1/graphql";

  const query = `mutation Auth0SyncUsersAction($id: String!, $name: String) {
    insert_users_one(object: {id: $id, name: $name}, on_conflict: {constraint: users_pkey, update_columns: name}) {
      id
      name
    }
  }
`;

  const variables = { id, name };

  const res = await fetch(url,
    {
      method: 'POST',
      body: JSON.stringify({
        query: query,
        variables: variables
      }),
      headers: {
        'content-type' : 'application/json',
        'x-hasura-admin-secret': admin_secret
      }
    });

  console.log("Response", await res.json())

  return res

};
  • コピペした中の最初の方に有る次の2つのパラメーターは自分のHasuraの設定値に変更する
Hasura Sync Users(Auth0)
const admin_secret = "YOUR_HASURA_GRAPHQL_ADMIN_SECRET";
  const url = "https://your-hasura-url.hasura.app/v1/graphql";
  • 🗃️みたいなとこをクリックしてAdd Dependencyをクリック

  • node-fetchという名前で指定して、バージョンを2にする

  • image.png

  • 終わったらDeployする

  • 再度Actionsページに戻り、flows > login > custom選択するとさっき設定した2個の□があるので左側にこんな感じでドラッグアンドドロップする

  • image.png

接続テスト

  • Hasura Sync Usersに移動
  • 左側▲を押すと、Testが現れるのでしたにスクロールして Run するとテストが通る
    image.png
  • テストに通ったらDB側にもデータが追加されてるimage.png

Auth0 Tokenテスト

  • Extension page で api debugger で検索

  • image.png

  • アプリ認証画面になるので 許可 を選択

  • なお、ここまで全てのサービスで同じGmailアドレスを利用しておくことが寛容

  • 何も考えずに同じGmailでSNS認証を通していたが、ビジネスロジックを考えると同じじゃなかったらなんかエラーでてたかもと思った

  • image.png

  • Applicationという選択肢で使用するアプリを選択

  • 注意点として、 Callback URL は後で利用するのでメモに貼り付けて保存が必要

  • 次に OAuth2 / OIDC タブをクリックして

  • image.png

  • ページ内検索で Audience を探す

  • image.png

  • 自分のHasuraのURLをコピペ

  • image.png

  • 今まで見たこと無いSaveボタンをクリック

  • image.png

  • Application画面に移動して、今回利用するアプリ名を選択肢、メモしていたCallback URLをコピペしてSaveボタンをクリック

  • image.png

  • 別タブで開いていたAuth0 Authentication API Debuggerページに戻る。いわゆるさっきの今まで見たこと無いSaveボタンが有るOAuth2 / OIDCページimage.png

  • ここでよく覚えてないけどAuth0のApplicationタブにあるCallbackURLは次のようにした。LoginURIは未指定でいける。結局このあと行う認証自体はGoogleアカウントと認証するのできっとLoginURIは不要なんじゃなかろうか。

  • image.png

  • 正直どのサービスで許可したのかさえあやふやだったので、サービスを選択する画面が出たらHasuraとかじゃなくて All Service みたいなのを選択したら良い。セキュリティ的には危ういが、初回のチュートリアルとしてはOK.

  • とりあえず、Auth0のExtensionページから移動した先で色々設定して次のような状態になればOK

  • image.png

  • 同様にHasura側でもGoogleドメインで↑許可したやつが反映される

  • image.png

確認テスト

  • その後の公式ページ(英語)には何か操作があったがその画面がでなかったので確認テストをしたら通ったのでOKということにしたい
  • HasuraのQuery投げれる次のページで
  • image.png
  • 次のようなクエリ投げてデータが返って来たら良いらしいが、どう考えてもHasuraで実行しているのでHasuraのデータをっているようにしか見えないから、Auth0と接続できているかちょっとよくわからん。
  • なお、今回のAuth0の件だけで記事書きながらだけど3時間はかかった。
hasura
{
  users {
    id
  }
}

hasuraスキーマエクスポートhttps://hasura.io/learn/ja/graphql/hasura-advanced/migrations-metadata/3-metadata/

Firebaseなら

  • どこかの記事でFirebaseの方がAuth0より操作が大変って書いてたけど、Hasura公式英語ページ見る限りFirebaseの方が簡単そう
  • 実際のところFirebaseの方が慣れているのと、Firebaseは先月末プレでPostgreSQL使えるようになった( Cloud SQL for PostgreSQL:ただし使ってみたけど未完成っぽい)
  • そういうの含めFirebaseで認証作業をやってみようと思う

Hasura公式Firebase Doc

  • https://hasura.io/learn/graphql/hasura-authentication/integrations/firebase/
  • 割と適当に設定コピペでして、ローカルのindex.htmlをプレビューして適当に登録したら
  • image.png
  • Firebase側にも反映されてた。ここまで10分たらず。(だがしかし、動作できているか怪しい。なぜならHasuraのFirebaseに関する操作説明がAuth0のそれに比べ薄いから。Auth0を使ったほうが無難なのかもしれない。)
  • そんな時に使うパイセンの知見:https://zenn.dev/yubachiri/articles/bb4ac475d7e3560c3913#firebase
  • image.png
  • ただ、Hasura側に戻った時に次のエラーが見えてた
  • 追記:ここは公式英語ページの内容を正規表現で一括変更していた時に半角スペースが混じっていたから目グレップで修正したらSUCCESSになりました
  • image.png
  • ここまでは、htmlプレビューしてFirebaseにユーザ生成するまでなのでよく考えたらHasuraまだ絡んでなかった

HasuraとFirebaseをConnect

firebase-tools-login-init
# 次のコマンドはnode.jsを最新にするものです。エラーが出たら無視してください。
npm install -g node

# sampleフォルダを作ります。別の名前でも良いです。
mkdir sample

# sampleフォルダに移動します。
cd sample

# firebaseを利用するツールをインストールします
npm install -g firebase-tools

# firebaseにログインします。大抵はGmailの認証情報です
firebase login

# firebaseを利用できるようにするため初期化しています
firebase init

windowsのwsl

  • ここにきてwindows側のwslをクリーンに使いたいと思った
  • MacBookのM4ほしい

VSCodeから操作してwsl開く

Hasuraチュートリアル

todo

slack clone

React側

やっとReact側の実装に進む

Hasura公式参照

ReactとNext.jsの違い

Reactで作る場合の管理画面テンプレート

とりあえずwindows+docker+reactではじめる

企業支給PC利用の初学者の方はwindows利用の方も多いのでここ頑張って。

Dockerはずっと使います。

何度もやっていると慣れます。

習うより慣れろ。

ホットリリードできない場合

package.json
"scripts": {
  "start": "WATCHPACK_POLLING=true react-scripts start",

とりあえずHasuraからデータ取得する

  • 厳密に言うと今やっている流れだと取得できない。
  • ただし一旦この部分を飛ばした先に記載した内容に沿うとできる
  • 理由としてAuth0認証をしているので、Auth0認証が通らないと取得できないから。
  • Auth0認証するページを実装する必要があるが、Hasura内に見当たらない
  • とりあえず認証を解除する方法を探るのも一つの手だが、↓の先生のページで何が取得できるかは、ディベロッパーツール上で確認できるとのこと。
  • この処理の先生記事:https://zenn.dev/yubachiri/articles/bb4ac475d7e3560c3913#firebase

HasuraからエンドポイントURLをコピペ

赤く塗りつぶしている行のURLをコピーしておく。

とりあえず後で使うのでどこかメモ帳にはるか、↓画面を開きっぱなしにしておけば良い。

このURLを エンドポイントURL と名付ける

image.png

App.tsxに次のコードをコピペする

  1. App.tsxに次のコードをコピペする
  2. そのうえで、 HasuraからコピペしたエンドポイントURLを貼る の部分に エンドポイントURL をコピペして保存
App.tsx
import React from './App';

function App() {
  const queryStr = "query MyQuery { users { id email } }"
  const query = { query: queryStr }

  const fetchUsers = () => {
    fetch('HasuraからコピペしたエンドポイントURLを貼る', {
      method: 'POST',
      body: JSON.stringify(query)
    }).then(response => {
      response.json().then(result => {
        console.log(result.data)
      })
    })
  }

  return (
    <div>
      <button onClick={fetchUsers}>
        クリックするとデータ取得
      </button>
    </div>
  );
}

export default App;

日本語で説明

  • 何故ここに来て日本語で説明するかというと初学者用
  • Hasura側の設定を説明しなかったのは今は理解しなくて良いから
  • 日本語化教材告知
    https://www.techpit.jp/courses/257
App.tsx
1. `import React from './App';`  
   `./App`から`React`をインポートします
2. `function App() {`  
   `App`という名前の関数を定義しますこの関数はReactのコンポーネントとして機能します
3. `const queryStr = "query MyQuery { users { id email } }"`  
   `queryStr`という定数を定義しGraphQLのクエリ文字列を代入しますこのクエリはユーザーの`id``email`を取得します
4. `const query = { query: queryStr }`  
   `query`という定数を定義し`queryStr`をプロパティとして持つオブジェクトを代入します
5. `const fetchUsers = () => {`  
   `fetchUsers`という名前の関数を定義しますこの関数はユーザー情報を取得するための非同期操作を行います
6. `fetch('HasuraからコピペしたエンドポイントURLを貼る', {`  
   `fetch`関数を使用して指定したエンドポイントURLからデータを取得します
7. `method: 'POST',`  
   HTTPメソッドとして`POST`を指定します
8. `body: JSON.stringify(query)`  
   リクエストボディとして`query`オブジェクトをJSON形式の文字列に変換したものを指定します
9. `}).then(response => {`  
   `fetch`関数が返すPromiseが解決したときつまりデータの取得が完了したときに実行する処理を定義します
10. `response.json().then(result => {`  
    レスポンスボディをJSON形式のデータに変換しその結果を処理します
11. `console.log(result.data)`  
    取得したデータをコンソールに出力します
12. `return (`  
    `App`関数コンポーネントがレンダリングする要素を返します
13. `<div>`  
    `div`要素を開始します
14. `<button onClick={fetchUsers}>`  
    `fetchUsers`関数をクリックイベントハンドラとして持つ`button`要素を作成します
15. `クリックするとデータ取得`  
    ボタンのラベルとして表示されるテキストです
16. `export default App;`  
    `App`関数コンポーネントをデフォルトエクスポートしますこれにより他のファイルからこのコンポーネントをインポートできます

改とりあえずデータを取得する

image.png

アプリの作成(React予定)

  • データの取得まで何日かかんねん・・・これはHasuraとその周辺技術のバージョンの違いで情報が錯綜していることが問題

ご相談はこちら

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0