@@ -124,34 +124,37 @@ export const updateUser = async (id: number, userData: Partial<User>, options: M
124124 const db = await useDb ( options )
125125 const usersTable = options . tables . users
126126
127- const currentUser = await findUserById ( id , options )
128- if ( ! currentUser ) {
129- throw new Error ( 'User not found.' )
127+ // Explicitly define which fields are allowed to be updated.
128+ // This prevents mass-assignment vulnerabilities.
129+ const allowedFields : ( keyof User ) [ ] = [ 'name' , 'email' , 'role' ]
130+ const updates : string [ ] = [ ]
131+ const values : ( string | number ) [ ] = [ ]
132+
133+ for ( const field of allowedFields ) {
134+ if ( userData [ field ] !== undefined ) {
135+ updates . push ( `${ field } = ?` )
136+ values . push ( userData [ field ] )
137+ }
130138 }
131139
132- const fieldsToUpdate = { ...userData }
140+ // If no valid fields are provided, there's nothing to update.
141+ if ( updates . length === 0 ) {
142+ const currentUser = await findUserById ( id , options )
143+ if ( ! currentUser ) {
144+ throw new Error ( 'User not found.' )
145+ }
146+ return currentUser
147+ }
133148
134- // remove from update list
135- delete fieldsToUpdate . id
136- delete fieldsToUpdate . created_at
137- delete fieldsToUpdate . updated_at
138- delete fieldsToUpdate . last_login_at
139- delete fieldsToUpdate . password // TODO: handle password update
149+ // Add the updated_at timestamp and the user ID for the WHERE clause
150+ updates . push ( 'updated_at = CURRENT_TIMESTAMP' )
151+ values . push ( id )
140152
141- if ( Object . keys ( fieldsToUpdate ) . length === 0 ) {
142- return currentUser as UserWithoutPassword
143- }
153+ // Use db.sql with template parts for dynamic column names
154+ const setClause = updates . map ( update => update . replace ( ' = ?' , '' ) ) . join ( ', ' )
144155
145- const dirtyFields = Object . keys ( fieldsToUpdate ) . filter ( key => currentUser [ key as keyof UserWithoutPassword ] != fieldsToUpdate [ key as keyof typeof fieldsToUpdate ] )
156+ await db . sql `UPDATE { ${ usersTable } } SET { ${ setClause } } WHERE id = ${ id } `
146157
147- // Update each field individually for security
148- for ( const key of dirtyFields ) {
149- await db . sql `
150- UPDATE {${ usersTable } }
151- SET {${ key } } = ${ fieldsToUpdate [ key as keyof typeof fieldsToUpdate ] } , updated_at = CURRENT_TIMESTAMP
152- WHERE id = ${ id }
153- `
154- }
155158 const updatedUser = await findUserById ( id , options )
156159
157160 if ( ! updatedUser ) {
0 commit comments