Merge pull request #4048 from AlejandroGispert/fix/3981-login-email-case

fix: make signin email case-insensitive
This commit is contained in:
Mike Cao
2026-04-01 23:25:56 -04:00
committed by GitHub
3 changed files with 37 additions and 23 deletions
+9 -6
View File
@@ -24,7 +24,10 @@ export async function GET(request: Request, { params }: { params: Promise<{ user
return json(user);
}
export async function POST(request: Request, { params }: { params: Promise<{ userId: string }> }) {
export async function POST(
request: Request,
{ params }: { params: Promise<{ userId: string }> },
) {
const schema = z.object({
username: z.string().max(255).optional(),
password: z.string().min(8).max(255).optional(),
@@ -63,15 +66,15 @@ export async function POST(request: Request, { params }: { params: Promise<{ use
}
if (username && auth.user.isAdmin) {
data.username = username;
data.username = username.toLowerCase();
}
// Check when username changes
if (data.username && user.username !== data.username) {
const user = await getUserByUsername(username);
const existingUser = await getUserByUsername(username);
if (user) {
return badRequest({ message: 'User already exists' });
if (existingUser && existingUser.id !== userId) {
return badRequest({ message: "User already exists" });
}
}
@@ -97,7 +100,7 @@ export async function DELETE(
}
if (userId === auth.user.id) {
return badRequest({ message: 'You cannot delete yourself.' });
return badRequest({ message: "You cannot delete yourself." });
}
await deleteUser(userId);
+5 -3
View File
@@ -28,15 +28,17 @@ export async function POST(request: Request) {
const { id, username, password, role } = body;
const existingUser = await getUserByUsername(username, { showDeleted: true });
const existingUser = await getUserByUsername(username, {
showDeleted: true,
});
if (existingUser) {
return badRequest({ message: 'User already exists' });
return badRequest({ message: "User already exists" });
}
const user = await createUser({
id: id || uuid(),
username,
username: username.toLowerCase(),
password: hashPassword(password),
role: role ?? ROLES.user,
});
+23 -14
View File
@@ -1,8 +1,8 @@
import { Prisma } from '@/generated/prisma/client';
import { ROLES } from '@/lib/constants';
import { getRandomChars } from '@/lib/generate';
import prisma from '@/lib/prisma';
import type { QueryFilters, Role } from '@/lib/types';
import { Prisma } from "@/generated/prisma/client";
import { ROLES } from "@/lib/constants";
import { getRandomChars } from "@/lib/generate";
import prisma from "@/lib/prisma";
import type { QueryFilters, Role } from "@/lib/types";
import UserFindManyArgs = Prisma.UserFindManyArgs;
@@ -11,7 +11,10 @@ export interface GetUserOptions {
showDeleted?: boolean;
}
async function findUser(criteria: Prisma.UserFindUniqueArgs, options: GetUserOptions = {}) {
async function findUser(
criteria: Prisma.UserFindUniqueArgs,
options: GetUserOptions = {},
) {
const { includePassword = false, showDeleted = false } = options;
return prisma.client.user.findUnique({
@@ -41,27 +44,33 @@ export async function getUser(userId: string, options: GetUserOptions = {}) {
);
}
export async function getUserByUsername(username: string, options: GetUserOptions = {}) {
return findUser({ where: { username } }, options);
export async function getUserByUsername(
username: string,
options: GetUserOptions = {},
) {
return findUser({ where: { username: username.toLowerCase() } }, options);
}
export async function getUsers(criteria: UserFindManyArgs, filters: QueryFilters = {}) {
export async function getUsers(
criteria: UserFindManyArgs,
filters: QueryFilters = {},
) {
const { search } = filters;
const where: Prisma.UserWhereInput = {
...criteria.where,
...prisma.getSearchParameters(search, [{ username: 'contains' }]),
...prisma.getSearchParameters(search, [{ username: "contains" }]),
deletedAt: null,
};
return prisma.pagedQuery(
'user',
"user",
{
...criteria,
where,
},
{
orderBy: 'createdAt',
orderBy: "createdAt",
sortDescending: true,
...filters,
},
@@ -110,7 +119,7 @@ export async function deleteUser(userId: string) {
let websiteIds = [];
if (websites.length > 0) {
websiteIds = websites.map(a => a.id);
websiteIds = websites.map((a) => a.id);
}
const teams = await client.team.findMany({
@@ -124,7 +133,7 @@ export async function deleteUser(userId: string) {
},
});
const teamIds = teams.map(a => a.id);
const teamIds = teams.map((a) => a.id);
if (cloudMode) {
return transaction([