使用 Prisma 2 从查询中排除用户的密码



最近我开始做一个新项目来学习一些新技术(Prisma 2、REST-api with Express等(。但是,我遇到了一个问题。

我的应用程序有一个用户身份验证系统,用户模型有一个密码列。因此,当客户端请求用户时,后端会从数据库中选择所有列,包括密码(顺便说一下,这是散列的(。

我试着不在prisma findMany上选择密码列,如下所示:

await prisma.user.findUnique({
where: {
...
},
select: {
password: false
}
});

但我得到了一个错误,prisma说select应该至少包含一个真正的值。因此,我在选择中添加了id: true。我提出了一个api请求,我看到只有id返回给用户。

根据我的理解,prisma希望我将我关心的所有列添加到select对象中。但是,我需要来自用户的大量列,我正在进行大量的查询来获取用户,我不能每次都只写我需要的所有字段。

所以,我想问你是否有合法的方法来做到这一点。

附言:我不接受;而是使用rawQuery"作为解决方案。

唯一合法的方法是将column: true添加到要包含的列中。这里有排除列的请求,所以如果您可以添加👍与您相关的请求,以便我们可以查看优先级。

https://github.com/prisma/prisma/issues/5042https://github.com/prisma/prisma/issues/7380https://github.com/prisma/prisma/issues/3796

我一直在想如何实现这一点,令人困惑的是,@Ryan帖子中的问题已经存在两年多了,仍未解决。我想出了一个临时的解决办法,那就是为Prisma客户端实现一个中间件功能,该功能在每次调用后手动删除密码字段。

import { PrismaClient } from '@prisma/client'
async function excludePasswordMiddleware(params, next) {
const result = await next(params)
if (params?.model === 'User' && params?.args?.select?.password !== true) {
delete result.password
}
return result
}
const prisma = new PrismaClient()
prisma.$use(excludePasswordMiddlware)

这将检查所查询的模型是否为User,如果使用select查询显式包含密码,则不会删除该字段。这应该允许您在需要时仍然获得密码,例如当您需要验证登录用户时:

async validateUser(email: string, password: string) {
const user = await this.prisma.user.findUnique({
where: { email },
select: {
emailVerified: true,
password: true,
},
})
// Continue to validate user, compare passwords, etc.
return isValid
}

查看以下代码从用户中排除密钥

function exclude(user, ...keys) {
for (let key of keys) {
delete user[key]
}
return user
}
function main() {
const user = await prisma.user.findUnique({ where: 1 })
const userWithoutPassword = exclude(user, 'password')
}

参考主要官方网站

最新更新