From b6cfd73993be4ca3e35af5a21216ca26ceb2f1f0 Mon Sep 17 00:00:00 2001 From: Diego Alzate Date: Wed, 6 Mar 2024 10:10:28 -0500 Subject: [PATCH 1/2] Update user service to check for existing email and username --- src/services/users.ts | 74 +++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/src/services/users.ts b/src/services/users.ts index 5f68ce36..af1b999a 100644 --- a/src/services/users.ts +++ b/src/services/users.ts @@ -1,7 +1,7 @@ import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'; import * as db from '../db'; import type { Request, Response } from 'express'; -import { eq } from 'drizzle-orm'; +import { and, eq, ne, or } from 'drizzle-orm'; import { insertUserSchema } from '../types/users'; import { overwriteUsersToGroups } from './usersToGroups'; import { upsertUserAttributes } from './userAttributes'; @@ -77,25 +77,57 @@ export function updateUser(dbPool: PostgresJsDatabase) { } // update user - const user = await dbPool - .update(db.users) - .set({ - email: body.data.email, - username: body.data.username, - name: body.data.name, - updatedAt: new Date(), - }) - .where(eq(db.users.id, userId)) - .returning(); - - const updatedGroups = await overwriteUsersToGroups(dbPool, userId, body.data.groupIds); - - const updatedUserAttributes = await upsertUserAttributes( - dbPool, - userId, - body.data.userAttributes, - ); - - return res.json({ data: { user, updatedGroups, updatedUserAttributes } }); + try { + // check if username or email already exists and is not the current user + if (body.data.email || body.data.username) { + const existingUser = await dbPool + .select() + .from(db.users) + .where( + or( + and(eq(db.users.email, body.data.email ?? ''), ne(db.users.id, userId)), + and(eq(db.users.username, body.data.username ?? ''), ne(db.users.id, userId)), + ), + ); + + if (existingUser.length > 0) { + const errors = []; + + if (existingUser[0]?.email === body.data.email) { + errors.push('Email already exists'); + } + + if (existingUser[0]?.username === body.data.username) { + errors.push('Username already exists'); + } + + return res.status(400).json({ errors }); + } + } + + const user = await dbPool + .update(db.users) + .set({ + email: body.data.email, + username: body.data.username, + name: body.data.name, + updatedAt: new Date(), + }) + .where(eq(db.users.id, userId)) + .returning(); + + const updatedGroups = await overwriteUsersToGroups(dbPool, userId, body.data.groupIds); + + const updatedUserAttributes = await upsertUserAttributes( + dbPool, + userId, + body.data.userAttributes, + ); + + return res.json({ data: { user, updatedGroups, updatedUserAttributes } }); + } catch (e) { + console.error(`[ERROR] ${JSON.stringify(e)}`); + return res.sendStatus(500); + } }; } From db821cac74c19d83ce9d2e4881db1c766601a8ff Mon Sep 17 00:00:00 2001 From: Diego Alzate Date: Thu, 7 Mar 2024 11:12:08 -0500 Subject: [PATCH 2/2] Refactor insertUserSchema to handle empty strings as null values --- src/types/users.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/types/users.ts b/src/types/users.ts index fd76cb74..ece83923 100644 --- a/src/types/users.ts +++ b/src/types/users.ts @@ -5,7 +5,17 @@ import { users } from '../db'; export const groupIdsSchema = z.string().array(); export const userAttributesSchema = z.record(z.string()); -export const insertUserSchema = createInsertSchema(users).extend({ - groupIds: groupIdsSchema, - userAttributes: userAttributesSchema, -}); +export const insertUserSchema = createInsertSchema(users) + .extend({ + groupIds: groupIdsSchema, + userAttributes: userAttributesSchema, + }) + .transform((data) => { + // make empty strings null + return { + ...data, + email: data.email || null, + username: data.username || null, + name: data.name || null, + }; + });