perf(server): index lower user email (#8167)
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "users_email_lowercase_idx" ON "users"(lower("email"))
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { Prisma, PrismaClient } from '@prisma/client';
|
import { Prisma, PrismaClient, User } from '@prisma/client';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Config,
|
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);
|
validators.assertValidEmail(email);
|
||||||
return this.prisma.user.findFirst({
|
const rows = await this.prisma.$queryRaw<
|
||||||
where: {
|
// see [this.defaultUserSelect]
|
||||||
email: {
|
{
|
||||||
equals: email,
|
id: string;
|
||||||
mode: 'insensitive',
|
name: string;
|
||||||
},
|
email: string;
|
||||||
},
|
email_verified: Date | null;
|
||||||
select: this.defaultUserSelect,
|
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`
|
* supposed to be used only for `Credential SignIn`
|
||||||
*/
|
*/
|
||||||
async findUserWithHashedPasswordByEmail(email: string) {
|
async findUserWithHashedPasswordByEmail(email: string): Promise<User | null> {
|
||||||
validators.assertValidEmail(email);
|
validators.assertValidEmail(email);
|
||||||
return this.prisma.user.findFirst({
|
|
||||||
where: {
|
// see https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries#typing-queryraw-results
|
||||||
email: {
|
const rows = await this.prisma.$queryRaw<
|
||||||
equals: email,
|
{
|
||||||
mode: 'insensitive',
|
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) {
|
async signIn(email: string, password: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user