ユーザー登録の実装 (Svelte & Lucia)
このコードは、SvelteKitのサーバーサイド機能を活用して、ユーザー認証の処理を行うものです。Luciaを使用した認証システムを組み込み、ユーザー登録とリダイレクト処理を実装しています。
+page.server.ts
: ユーザー登録とリダイレクト
load
関数: セッションの検証とリダイレクト
export const load = (async ({ locals }) => {
const session = await locals.auth.validate();
if (!session) return {};
redirect(303, "/");
}) satisfies PageServerLoad;
解説
locals.auth.validate()
を用いて、現在のセッションが有効かどうかを検証します。- セッションがない場合
{}
を返し、ページのロードを許可します。 - セッションが有効なら、
redirect(303, "/")
でトップページにリダイレクトします。 satisfies PageServerLoad;
を使用して型の安全性を確保しています。
actions
オブジェクト: ユーザー登録の処理
export const actions = {
register: async ({ request }) => {
const { username, password, name } = Object.fromEntries(
await request.formData()
) as {
username: string;
password: string;
name: string;
};
try {
const user = await auth.createUser({
key: {
providerId: "username",
providerUserId: username,
password,
},
attributes: {
name,
username,
},
});
console.log("user created", user);
} catch (error) {
console.error(error);
return fail(400, { message: "That username already exists." });
}
redirect(303, "/login");
},
} satisfies Actions;
解説
request.formData()
を使ってフォームデータを取得し、username
,password
,name
を取得します。auth.createUser()
を用いて新しいユーザーを作成します。providerId: "username"
はユーザー名を識別子として使用することを意味します。providerUserId: username
でユーザー名をセット。password
を保存(おそらく内部的にハッシュ化されます)。attributes
にname
とusername
をセット。
- ユーザーの作成に失敗した場合(すでに存在するユーザー名など)、
fail(400, { message: "That username already exists." })
を返してエラーメッセージを表示します。 - 成功した場合、
redirect(303, "/login")
でログインページへリダイレクトします。
+page.svelte
: ページ側の実装
スクリプト部分
<script lang="ts">
import { enhance } from "$app/forms";
import type { ActionData } from "./$types";
export let form: ActionData;
</script>
解説
enhance
を$app/forms
からインポートし、フォーム送信を最適化。form
はサーバーから返されるActionData
型のエラーメッセージを格納。
フォーム部分(HTML)
<form class="bg-white shadow-md rounded-lg max-w-sm mx-auto mt-20 p-6" use:enhance action="?/register" method="post">
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">Name:</label>
<input type="text" id="name" name="name" required />
</div>
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="username">Username:</label>
<input type="text" id="username" name="username" required />
</div>
<div class="mb-6">
<label class="block text-gray-700 text-sm font-bold mb-2" for="password">Password:</label>
<input type="password" id="password" name="password" required />
</div>
<button type="submit" class="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg transition-colors">
REGISTER
</button>
{#if form?.message}
<div class="mt-4 p-3 bg-red-100 text-red-700 rounded-lg">{form.message}</div>
{/if}
<p class="mt-4 text-center text-gray-600">
Already have an account?
<a href="/login" class="text-blue-500 hover:text-blue-700 font-bold">Login here.</a>
</p>
</form>
解説
use:enhance
により、フォーム送信が最適化される。action="?/register"
でactions.register
にフォームを送信。method="post"
によりPOSTリクエストで送信。name
,username
,password
の3つの入力フィールドを持つ。required
属性で入力必須。{#if form?.message}
でエラーメッセージを動的に表示。- 既にアカウントを持っているユーザー向けのログインリンクを設置。
まとめ
load
関数でセッションを確認し、ログイン済みならリダイレクト。actions.register
でユーザー登録を処理し、エラー時には適切なメッセージを返す。- ページ側のフォームでは
use:enhance
を活用し、動的なエラーメッセージを表示。 redirect(303, "/login")
で登録完了後にログインページへ遷移。