Сброс пароля с помощью Node, Express, JWT, в Typeorm SQL

#node.js #typescript #jwt #nodemailer

#node.js #typescript #jwt #nodemailer

Вопрос:

У меня возникла проблема с моей функцией сброса пароля ( changepass ), и, вероятно, это небольшая ошибка в моем коде.

После обработки нового пароля через nodemailer и успешного входа в систему я пытаюсь реализовать следующую функциональность, позволяющую пользователю обновлять свой пароль.

Мое промежуточное программное обеспечение auth отлично работает во всех других функциях после входа пользователя в систему.

При входе в систему я отправляю старый и новый пароль в теле и новый токен в Bearer Token поле. Удивительно, но я возвращаю статус 204, поскольку он проработал весь путь.

На терминале я продолжаю получать следующее:

  1. const id = res.locals.userId; -> undefined;
  2. No metadata found. There is more than once class-validator version installed probably. You need to flatten your dependencies.

Функция определенно что-то делает, но она больше не может входить в систему ни со старым, ни с новым паролем, поэтому мне нужно снова запросить новый пароль через nodemailer.

Кто-нибудь знает, в чем моя ошибка?


Сброс пароля (где проблема):

 async changepass(req: Request, res: Response) {
    // Get ID from JWT
    const id = res.locals.userId;
    console.log(id)
    // Get parameters from the body
    const { oldPassword, newPassword } = req.body;

    if (!(oldPassword amp;amp; newPassword)) {
        res.status(400).send();
    }

    // Get user from the database
    const userRepository = getRepository(User);
    // let user = await userRepository.findOneOrFail(id);
    let user = User as any;
    try {
        user = await userRepository.findOneOrFail(id);
    } catch (id) {
        res.status(401).send();
    }

    // Check if old password matches
    if (!user.checkIfUnencryptedPasswordIsValid(oldPassword)) {
        res.status(401).send();
        return;
    }

    // Validate the model (Password length)
    user.password = newPassword;
    const errors = await validate(user);
    if (errors.length > 0) {
        res.status(400).send(errors);
        return;
    }
    // Hash the new password and save
    user.hashPassword();
    userRepository.save(user);

    res.status(204).send();
},
 

Вход пользователя:

 async login(req: Request, res: Response) {
    // Get user from database
    const userRepository = getRepository(User);
    const { email, password } = req.body;

    // Check if useremail and password are set
    if (!(email amp;amp; password)) {
        console.error('Empty name or password!');
        return res.status(400).send({
            error: 'Empty name or password'
        });
    }
    
    const user = await userRepository.findOne({ where: { email } });

    if(!user) {
        return res.sendStatus(401);
    }
    
    // Check if encrypted password match : checkIfUnenc... função vemm do model
    if (!user.checkIfUnencryptedPasswordIsValid(password)) {
        return res.status(401).send({
            error: 'Cannot match encrypted password'
        });
    }     
    
    // Sing JWT, valid for 1 hour
    const token = jwt.sign(
        { id: user.id, email: user.email }, //payload do token, informações do user
        config.jwtSecret, //chave secreta que autoriza, ideal no .env
        { expiresIn: "1d" }
    );
    
    // Send the jwt in the response
    res.json({
        user,
        token
    });
},
 

Маршрут:

 //change password route
routes.post('/users/changepass', checkJwt, UserController.changepass);
 

Промежуточное ПО аутентификации:

 interface TokenPayload {
    id: number;
    iat: string;
    exp: string;
}

export default function checkJwt(req: Request, res: Response, next: NextFunction) {

    const { authorization } = req.headers;
    // console.log(authorization)

    if(!authorization) {
        return res.sendStatus(401)
    }

    const token = authorization.replace("Bearer", "").trim(); //apenas remover a palavra "Bearer" e espaço

    try {
        const data = jwt.verify(token, config.jwtSecret)
        //console.log(data) -> data traz no log o id, iat, exp, então tenho que tipar o data com interface

        const { id } = data as TokenPayload; 
    
        req.userId  = id;  
        console.log(id)
    } catch {
        return res.sendStatus(401);
    }
    next();
}