gbmake-payload/src/collections/Users.ts

112 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { CollectionConfig } from 'payload'
export const Users: CollectionConfig = {
slug: 'users',
admin: {
useAsTitle: 'email',
},
auth: true,
fields: [
// Email added by default
{
name: 'roles',
type: 'select',
hasMany: true,
options: ['admin', 'editor', 'user'],
defaultValue: ['user'],
required: true,
saveToJWT: true, // Include in JWT for fast access checks
access: {
update: ({ req: { user } }) => {
// Only admins can update roles
if (!user) return false
return user.roles?.includes('admin') || false
},
},
},
],
hooks: {
beforeChange: [
async ({ data, req, operation }) => {
// 如果是创建操作,检查是否为第一个用户
if (operation === 'create') {
const { totalDocs } = await req.payload.count({
collection: 'users',
})
// 如果这是第一个用户,自动设置为 admin
if (totalDocs === 0) {
data.roles = ['admin']
console.log('🎉 第一个用户注册,自动设置为管理员')
}
}
// 如果是更新操作,检查是否为唯一用户且 roles 为空
if (operation === 'update') {
const { totalDocs } = await req.payload.count({
collection: 'users',
})
// 如果只有一个用户且 roles 为空或只有 user自动升级为 admin
if (
totalDocs === 1 &&
(!data.roles ||
data.roles.length === 0 ||
(data.roles.length === 1 && data.roles[0] === 'user'))
) {
data.roles = ['admin']
console.log('🔧 当前是唯一用户,自动升级为管理员')
}
}
return data
},
],
afterRead: [
async ({ doc, req, context }) => {
// 跳过已标记为处理过的请求
if (context?.skipAutoAdmin) return doc
// 检查是否为唯一用户且 roles 为空或不正确
if (
!doc.roles ||
doc.roles.length === 0 ||
(doc.roles.length === 1 && doc.roles[0] === 'user')
) {
const { totalDocs } = await req.payload.count({
collection: 'users',
})
// 如果只有一个用户,自动更新为 admin
if (totalDocs === 1) {
console.log('🔄 检测到唯一用户权限异常,正在修复...')
try {
// 使用 overrideAccess 绕过权限检查,标记 context 避免循环
await req.payload.update({
collection: 'users',
id: doc.id,
data: {
roles: ['admin'],
},
context: {
skipAutoAdmin: true,
},
overrideAccess: true,
})
// 更新当前文档的 roles
doc.roles = ['admin']
console.log('✅ 唯一用户权限已修复为管理员')
} catch (error) {
console.error('❌ 更新用户权限失败:', error)
}
}
}
return doc
},
],
},
}