sync-docs-and-fixes
This commit is contained in:
41
src/auth.ts
41
src/auth.ts
@@ -1,13 +1,23 @@
|
||||
import { compare, hash } from "bcryptjs"
|
||||
import { compare } from "bcryptjs"
|
||||
import NextAuth from "next-auth"
|
||||
import Credentials from "next-auth/providers/credentials"
|
||||
|
||||
const normalizeRole = (value: unknown) => {
|
||||
const role = String(value ?? "").trim().toLowerCase()
|
||||
if (role === "grade_head" || role === "teaching_head") return "teacher"
|
||||
if (role === "admin" || role === "student" || role === "teacher" || role === "parent") return role
|
||||
return "student"
|
||||
}
|
||||
|
||||
const resolvePrimaryRole = (roleNames: string[]) => {
|
||||
const mapped = roleNames.map((name) => normalizeRole(name)).filter(Boolean)
|
||||
if (mapped.includes("admin")) return "admin"
|
||||
if (mapped.includes("teacher")) return "teacher"
|
||||
if (mapped.includes("parent")) return "parent"
|
||||
if (mapped.includes("student")) return "student"
|
||||
return "student"
|
||||
}
|
||||
|
||||
const normalizeBcryptHash = (value: string) => {
|
||||
if (value.startsWith("$2")) return value
|
||||
if (value.startsWith("$")) return `$2b${value}`
|
||||
@@ -30,7 +40,7 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
const password = String(credentials?.password ?? "")
|
||||
if (!email || !password) return null
|
||||
|
||||
const [{ eq }, { db }, { users }] = await Promise.all([
|
||||
const [{ eq }, { db }, { roles, users, usersToRoles }] = await Promise.all([
|
||||
import("drizzle-orm"),
|
||||
import("@/shared/db"),
|
||||
import("@/shared/db/schema"),
|
||||
@@ -48,11 +58,19 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
const ok = await compare(password, normalizedPassword)
|
||||
if (!ok) return null
|
||||
|
||||
const roleRows = await db
|
||||
.select({ name: roles.name })
|
||||
.from(usersToRoles)
|
||||
.innerJoin(roles, eq(usersToRoles.roleId, roles.id))
|
||||
.where(eq(usersToRoles.userId, user.id))
|
||||
|
||||
const resolvedRole = resolvePrimaryRole(roleRows.map((r) => r.name))
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
name: user.name ?? undefined,
|
||||
email: user.email,
|
||||
role: normalizeRole(user.role),
|
||||
role: resolvedRole,
|
||||
}
|
||||
},
|
||||
}),
|
||||
@@ -67,19 +85,26 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
|
||||
const userId = String(token.id ?? "").trim()
|
||||
if (userId) {
|
||||
const [{ eq }, { db }, { users }] = await Promise.all([
|
||||
const [{ eq }, { db }, { roles, users, usersToRoles }] = await Promise.all([
|
||||
import("drizzle-orm"),
|
||||
import("@/shared/db"),
|
||||
import("@/shared/db/schema"),
|
||||
])
|
||||
|
||||
const fresh = await db.query.users.findFirst({
|
||||
const [fresh, roleRows] = await Promise.all([
|
||||
db.query.users.findFirst({
|
||||
where: eq(users.id, userId),
|
||||
columns: { role: true, name: true },
|
||||
})
|
||||
columns: { name: true },
|
||||
}),
|
||||
db
|
||||
.select({ name: roles.name })
|
||||
.from(usersToRoles)
|
||||
.innerJoin(roles, eq(usersToRoles.roleId, roles.id))
|
||||
.where(eq(usersToRoles.userId, userId)),
|
||||
])
|
||||
|
||||
if (fresh) {
|
||||
token.role = normalizeRole(fresh.role ?? token.role)
|
||||
token.role = resolvePrimaryRole(roleRows.map((r) => r.name))
|
||||
token.name = fresh.name ?? token.name
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user