perf(server): index lower user email (#8167)

This commit is contained in:
forehalo
2024-09-09 04:43:59 +00:00
parent a7ecfea3b5
commit 32f673fa3d
2 changed files with 66 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
import { Injectable, Logger } from '@nestjs/common';
import { Prisma, PrismaClient } from '@prisma/client';
import { Prisma, PrismaClient, User } from '@prisma/client';
import {
Config,
@@ -106,32 +106,76 @@ export class UserService {
});
}
async findUserByEmail(email: string) {
async findUserByEmail(
email: string
): Promise<Pick<User, keyof typeof this.defaultUserSelect> | null> {
validators.assertValidEmail(email);
return this.prisma.user.findFirst({
where: {
email: {
equals: email,
mode: 'insensitive',
},
},
select: this.defaultUserSelect,
});
const rows = await this.prisma.$queryRaw<
// see [this.defaultUserSelect]
{
id: string;
name: string;
email: string;
email_verified: Date | null;
avatar_url: string | null;
registered: boolean;
created_at: Date;
}[]
>`
SELECT "id", "name", "email", "email_verified", "avatar_url", "registered", "created_at"
FROM "users"
WHERE lower("email") = lower(${email})
`;
const user = rows[0];
if (!user) {
return null;
}
return {
...user,
emailVerifiedAt: user.email_verified,
avatarUrl: user.avatar_url,
createdAt: user.created_at,
};
}
/**
* supposed to be used only for `Credential SignIn`
*/
async findUserWithHashedPasswordByEmail(email: string) {
async findUserWithHashedPasswordByEmail(email: string): Promise<User | null> {
validators.assertValidEmail(email);
return this.prisma.user.findFirst({
where: {
email: {
equals: email,
mode: 'insensitive',
},
},
});
// see https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries#typing-queryraw-results
const rows = await this.prisma.$queryRaw<
{
id: string;
name: string;
email: string;
password: string | null;
email_verified: Date | null;
avatar_url: string | null;
registered: boolean;
created_at: Date;
}[]
>`
SELECT *
FROM "users"
WHERE lower("email") = lower(${email})
`;
const user = rows[0];
if (!user) {
return null;
}
return {
...user,
emailVerifiedAt: user.email_verified,
avatarUrl: user.avatar_url,
createdAt: user.created_at,
};
}
async signIn(email: string, password: string) {