DenoKVが発表された。以前からDeno自体は気になっていたので、これを機に触ってみることにした。
サンプル: Todoリスト
ベースとなるのはこのTodoリストアプリ。 DenoKVを使って複数のユーザーがTodoを追加・削除しながら、Todoリストを共有できる。 サンプルアプリではあるが良くできている。TwitterでDemoが流れてきていたが、リアルタイム並みに高速でリストが同期されるのには驚いた。
実際にDenoDeployのアカウントを作って試したみた。Github上のリポジトリを指定するだけで、すぐにデプロイが完了する。 上記のサンプルをForkしたものはこちら。
実際に見てみると、Demoほど高速で同期はされないようだ。原因はおそらく、Deno KVのWriteリージョン(データがまず書き込まれるリージョン)が現状Virginia, USAで固定になっているため、地域差があるのだろう。現状東京リージョンでは展開されていないので、そこは今後に期待したい。
DenoとSupabaseでWeb認証を試す
上記のアプリでは、誰でもTodoを編集できる。クローズドで認証したユーザーのみがTodoを表示・編集できるようにしてみたくなったので、試してみた。
Deno初心者かつWeb認証の実装もやったことがなかったので、色々と調べてみたが、分かりやすいYoutube動画があったので、fresh(denoのWebフレームワーク.preactを採用している) + Supabaseで実装してみた。
Supabaseでの認証のポイントとしては、freshのroutes/_middleware.ts
に以下のコードを追加する。この関数は、あらゆるリクエストをインターセプトする形で実行され、ユーザーの認証を確認することができる。
export async function handler(
req: Request,
ctx: MiddleareHandlerContext<State>
) {
const client = createClient(
Deno.env.get("SUPABASE_URL") || "",
Deno.env.get("SUPABASE_KEY") || ""
);
ctx.state.supabaseClient = client;
const supaCreds = getCookies(req.headers)["supaLogin"];
if (!supaCreds) {
return ctx.next();
}
const { error } = await client.auth.getUser(supaCreds);
if (error) {
console.log(error.message);
ctx.state.loggedIn = false;
} else {
ctx.state.loggedIn = true;
}
return await ctx.next();
}
supabase clinet libraryのclient.auth.getUser
を利用することで、ユーザーの認証を確認することができる。
これが正しい使い方かわからなかったのだが、公式ドキュメントにも以下のような記載があった
This method is useful for checking if the user is authorized because it validates the user’s access token JWT on the server. Should be used only when you require the most current user data. For faster results, getSession().session.user is recommended.
一方で検証できていないがgetSession().session.user
を使うこともでき、そちらの方が高速なようだ。
Should be used only when you require the most current user data. For faster results, getSession().session.user is recommended.
認証されている時のみ表示したいページは、routes/auth/
に配置し、routes/auth/_middleware.ts
に以下のようなコードを追加する。
export async function handler(
req: Request,
ctx: MiddleareHandlerContext<State>
) {
if (!ctx.state.loggedIn) {
return new Response(null, {
status: 302,
headers: {
Location: "/",
},
});
}
return await ctx.next();
}
これで、認証されていない場合は、/
にリダイレクトされるようになる。
UIからは、props
を通じて、ctx.stateに設定した値を参照することができる。今回はprops.state.loggedIn
を参照することで、 ログイン状態に応じてUIの表示を切り替えることができる。
Supabaseでユーザーを作成する
通常のWebサービスではWeb上でユーザーを作成することができるものだが、今回はあくまでサンプルかつ知り合いで試しに使うくらいの想定なので、Supabaseの管理画面からユーザーを作成した。
Supabaseのダッシュボードから簡単に作成でき、Invitationをメールで送るか、すぐにユーザーを作成するかを選択できる。
まとめ
DenoKVと合わせて、Supabaseでの認証も試してみた。やはり実際に手を動かすことで、DenoについてもSupabaseについても理解が深まったのでよかった。