sync-docs-and-fixes

This commit is contained in:
SpecialX
2026-03-03 17:32:26 +08:00
parent 538805bad0
commit eb08c0ab68
73 changed files with 2218 additions and 422 deletions

View File

@@ -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
}
}