管理者権限を付与する の変更点
更新- 追加された行はこの色です。
- 削除された行はこの色です。
- プログラミング/svelte/管理者権限を付与する へ行く。
- プログラミング/svelte/管理者権限を付与する の差分を削除
[[プログラミング/svelte]] * 権限を管理する [#a538926a] AuthUser と 多対多 関係を持つ Role を導入する。 prisma/schema.prisma model User { ... + roles Role[] } + model Role { + id String @id @default(uuid()) + name String @unique + + users User[] + } マイグレーションする。 LANG: console $ pnpm prisma migrate dev --name "add Role table" Prisma で多対多関係を扱うためのコードは結構煩雑になるようなので、 Role を使うためのユーティリティ関数を db に持たせる。 このやり方が良いのかは疑問が残る?~ → [[やはり後ほど src/lib/server/role.ts に移した>プログラミング/svelte/コード配置の整理]] → [[やはり後ほど src/lib/server/role.ts に移した>プログラミング/svelte/コード配置の整理#u0f474f2]] src/lib/server/db.ts LANG: ts import { PrismaClient } from '@prisma/client'; export class ExtendedPrismaClient extends PrismaClient { constructor() { super() } // userId が undefined なら権限は空とみなされる async getRoles(userId: string | undefined) { if(!userId) { return [] } return (await this.user.findUnique({ where: {id: userId}, select: {roles: true} }))?.roles || [] } async getRolesString(userId: string | undefined) { return (await this.getRoles(userId)).map((role)=> role.name); } async hasRole(userId: string | undefined, role: string) { return (await this.getRolesString(userId)).includes(role); } async addRoles(userId: string, ...roles: string[]) { await this.user.update({ where: { id: userId }, data: { roles: { connectOrCreate: roles.map(role=> ({where: {name: role}, create: {name: role}}) ) }, }, }) } async removeRoles(userId: string, ...roles: string[]) { await this.user.update({ where: { id: userId }, data: { roles: { deleteMany: roles.map(role=>({name: role})) }, }, }) } } export const db = new ExtendedPrismaClient(); Prisma の言語仕様を見ていると TypeScript と VSCode の存在がいかに偉大か実感する。 こんな DSL はエディタ上でエラー検出してくれなきゃ、とてもじゃないけど書けない。 ところで、 LANG: ts roles.map(role=>({name: role})) などという記述に注意が必要。これを LANG: ts roles.map(role=>{name: role}) と書いてしまうと role=>{ の { がブロックの開始として解釈されてしまい、うまく行かない。 (その場合 name: はラベルとして解釈される) JavaScriptのアロー関数でオブジェクトを返す方法~ https://dev.classmethod.jp/articles/arrow-func-return-object/ そこで一見すると無駄に見える括弧で括っている。 サインアップ時、最初のユーザーには admin 権限を持たせることにする。 src/routes/account/(logout)/new/+page.server.ts + import { db } from '$lib/server/db' ... + // 最初のユーザーには admin 権限を持たせる + if(await db.user.count() == 1) { + await db.addRoles(user.userId, 'admin') + } (admin) を含むパスには admin 権限を持っているユーザーしかアクセスできない。 src/hooks.server.ts LANG:ts + if (event.route.id?.match(/\/\(admin\)\//) && !event.locals.session?.user) { + setFlash({ type: 'error', message: '管理者ユーザーのみアクセスできます' }, event); + throw redirect(302, path('/session/new')); + } LANG: console $ git add . && git commit -m "管理者ユーザーの仕組みを導入"
Counter: 350 (from 2010/06/03),
today: 3,
yesterday: 1