Search code examples
node.jsapiexpresstypeorm

How to correctly update an entity with express and typeorm


I'm looking for the best way to update a User entity with typeorm and express.

I have something like this (I have reduced, but there are many other attributes) :

class User {
  id: string;
  lastname: string;
  firstname: string;
  email: string;
  password: string;
  isAdmin: boolean;
}

And I have a path to update user's attributes like :

app.patch("/users/me", ensureAuthenticated, UserController.update);

Now (and it's my question), how to properly update the user? I don't want the user to be able to add themselves as an admin.

So I have :

export const update = async (req: Request, res: Response) => {
  const { sub } = res.locals.token;
  const { lastname, firstname, phone, email } = req.body;

  const userRepository = getRepository(User);
  const currentUser = await userRepository.findOne({ id: sub });

  const newUserData: User = {
    ...currentUser,
    lastname: lastname || currentUser.lastname,
    firstname: firstname || currentUser.firstname,
    phone: phone || currentUser.phone,
    email: email || currentUser.email
  };

  await userRepository
    .update({ id: sub }, newUserData)
    .then(r => {
      return res.status(204).send();
    })
    .catch(err => {
      logger.error(err);
      return res.status(500).json({ error: "Error." });
    });
};

With that, I'm sure to update the right attributes, and the user can't update admin. But I find it very verbose to create a new object and fill in the informations.

Do you have a better way to do it? Thanks.


Solution

  • You can follow the DTO pattern.

    For example:

    class UserDto {
        // define properties
        constructor(data: any) {
            // validate data
            ...
        }
    }
    
    const userDto = new UserDto(req.body);                                          
    
    await userRepository
        .update({ id: sub }, userDto)
        .then(r => {
            ...
        })
        .catch(err => {
            ...
        });
    

    The nestjs framework has a good example of how you can set up a DTO pattern generically. But it's easy enough to roll your own using class-validator and class-transformer which will make the validation a lot more declarative.