Open4
SvelteKitでデモアプリ作るぞ
Zennみたいな記事投稿サイトを作ろう
やりたいこと
- ユーザー・管理者の両方があるwebアプリ
使いたい技術
SvelteKitで入るやつは便利そう
- bun
- パッケージ管理
- SvelteKit
- 大枠として
- lucia-auth
- ログインに使用
- paraglide
- i18n対応
- mode-watcher
- ダークモード対応
- drizzle / pglite
- データベース
- mdsvex
- マークダウンを採用する場合
- storybook
- コンポーネント単位で編集するとなるとあったほうが良いか
- unocss
- スタイリング
使わない
- prettier
- eslintでフォーマットまでやるため
- tailwind
- unoを使うため
要件
- ユーザーをCRUDできる
- ユーザーは自分の投稿をCRUDできる
- 管理者はユーザーとは別画面でいろいろ管理できる
- 管理者は自由にCRUDできる必要はない
- 作成は他の管理者が代わりにできればよいであろう
- そうすると管理者権限の管理者と一般権限の管理者が生まれることになるな…これめんどいやつ
IDは識別子でありソートに使うべきではない!
数値カラムはナシだな
とはいえ時刻でソートすると同時に作成されたレコードの順序が安定しない可能性がある
そうするとIDはUUID v7またはcuid2が適切 どっちが良いかしら
- UUID v7 → uuid型があるのでデータ効率が良い
- cuid2 → uuidよりちょっと短い
と思ったけどIDにタイムスタンプが含まれているって脆弱性になり得ないか?
たとえばユーザーIDからユーザーの登録時刻がわかってしまう
そしてこれ結局created_atでソートしてるのと同じやん
→ じゃあUUID v4でいいや
luciaのサンプルから設定を書き換える必要がある
- userのidをuuidにする
- session.idはencodedTokenという名前にしたい
- session.user_idはuniqueだよな…?→複数デバイスでログインする可能性があるのでユーザーが複数のセッションを持つことはおかしくない
- userにはcreated_at / updated_atを追加する
- sessionには不要でしょう
こんな感じのスキーマになった
import { integer, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
// wrapper function for timestamp with zone
function tsz() {
return timestamp({ withTimezone: true, mode: 'date', precision: 3 }).notNull();
}
const timestamps = {
createdAt: tsz().$default(() => new Date()),
updatedAt: tsz().$onUpdate(() => new Date()),
};
export const user = pgTable('user', {
id: uuid().defaultRandom().primaryKey(),
username: text().notNull().unique(),
passwordHash: text().notNull(),
...timestamps,
});
export const session = pgTable('session', {
encodedToken: text().primaryKey(),
userId: uuid().notNull().references(() => user.id),
expiresAt: tsz(),
});
export type Session = typeof session.$inferSelect;
export type User = typeof user.$inferSelect;
ちなみにcasing
を設定しているのでスネークケース名の再定義は不要
user
- passkeysでログインする
- ユーザーネームを入れるとパスキーの設定を行いそれでログインする
- 別デバイスの場合はパスキーを連携してログインする
- すでにログインしているデバイスがあれば、ログイン画面内でOTPを生成してログインできるようにしてもいい
admin
- メールアドレスとパスワードでログインする
- 登録はすでに登録している管理者がメールを送信し、そのメールのマジックリンクから登録する
- 最初は開発者がコンソールから登録するか初期データを入れる
- permission_levelを持つ smallintでよい
- administrator
- 他のアドミンの追加はこのレベルからしかできないとする
- member
- だいたいの機能の編集が出来る、ただしアドミンは除く
- supporter デフォルト
- クリティカルな操作はできない
-
developer- 最強権限として用意しようかと思ったけど開発者は直接コンソール叩いたりするはずなので不要
- administrator