1

I am trying to make a PUT request with node.js using Javascript. Basically, what I am trying to do is make it so that an authenticated user is allowed to update a phone number and password. Normally I would have just used req.body in order to have the body be used to make an update request, however the whole body has a username, password and phoneNumber. I am only needing to update the password and phoneNumber. I have a restrict function that is restricting this request except for a logged in registered user, and I also have a model function for my update which is:

function updateUser(changes, id) {
    return db("users")
    .update(changes)
    .where({id})
}

I also am trying to make sure that the password the user decided to update to (or the password they currently have) is hashed. I am using bcryptjs to hash the password. I have a two post request that both encrypts the password, (which is my register function) and one that compares the encryption (my login function). I will include those both just in case you need any background information:

router.post("/register", async (req, res, next) => {
    try {
        const {username, password, phoneNumber} = req.body
        const user = await Users.findBy({username}).first()

        if(user) {
            return res.status(409).json({
                message: "Username is already in use",
            })
        }
        const newUser = await Users.create({
            username,
            password: await bcrypt.hash(password, 14),
            phoneNumber,
        })

        res.status(201).json(newUser)
    } catch (err) {
        next(err)
    }
})


router.post("/login", async(req, res, next) => {
    try {
        const {username, password} = req.body
        const user = await Users.findBy({username}).first()
        
        if(!user) {
            return res.status(401).json({message: "Invalid Username or Password",})
        }

        const passwordValid = await bcrypt.compare(password, user.password)

        if(!passwordValid) {
            return res.status(401).json({message: "Invalid Username or Password",})
        }
        
        const token = jwt.sign({
            userId: user.id,
        }, process.env.JWT_SECRET)
        

        res.cookie("token", token)

        res.json({
            message: `Welcome to your plant page ${user.username}!`
        })
    } catch (err) {
        next(err)
    }
});

When I was trying to start my PUT request, I had started off writing const {phoneNumber, password} = req.body but I am needing to use both phoneNumber and password in the function. Here is an example of what I was starting my code with:

router.put("/:id/updateaccount", restrict(), async(req, res, next) => {
    try {
        const {phoneNumber, password} = req.body
    } catch(err) {
        next(err)
    }
}) 
Natsuko Izuki
  • 443
  • 1
  • 4
  • 10
  • Could you please describe better what you are not able to do, and why you think it fails? It was hard to understand what the question is, although the description is generally good. I would also recommend you to keep logic out of your route files and instead import them from a controller, which in turn can import their helper methods from /utils/ or /services or similar. Otherwise you will get logic spread out in the model, in the routes and the controllers. – anatolhiman Sep 19 '20 at 23:52
  • I am basically trying to make a PUT request and I am having a hard time trying to create one. My last snipet is what I had started to create. – Natsuko Izuki Sep 19 '20 at 23:54
  • Mongoose or Sequelize or other? – anatolhiman Sep 19 '20 at 23:55
  • sqlite3, sorry for the lack of info on that – Natsuko Izuki Sep 19 '20 at 23:56
  • Then I recommend adding Sequelize that work with Sqlite (https://sequelize.org/master/manual/model-querying-basics.html) and have decent documentation (and much help to find here on Stackoverflow). Try this article: https://medium.com/@sarahdherr/sequelizes-update-method-example-included-39dfed6821d and this answer: https://stackoverflow.com/questions/8158244/how-to-update-a-record-using-sequelize-for-node (use findOne or findByPk to retrieve one record from the db, then call ModelName.update( req.body, { ... }) in order to update it. – anatolhiman Sep 20 '20 at 00:08
  • Also, another tip is to keep the API RESTful, where R "represents" a resource, not a verb. A resource is a "thing", not something you do, like "updateuser". So your route could simply be /api/version.../user/:id where you would request to update (PUT or PATCH) the user with ID xxxxxxxxxx. No need for a special route for that. Let put, post, get, etc. be the verbs, and let the routes be the nouns. – anatolhiman Sep 20 '20 at 00:10

1 Answers1

0

I got it figured out after finding some help from someone in my class. I was on the right track with const {phoneNumber, password} = req.body. The rest is this (or this is all of the code):

router.put("/:id/updateaccount", restrict(), async(req, res, next) => {
    try {
        const {phoneNumber, password} = req.body
        const userUpdate = await Users.updateUser({
          phoneNumber, password: await bcrypt.hash(password, 14)
         }, req.params.id)
        
        res.status(200).json({
        userUpdate:userUpdate, message: "You have successfully updated your information",
        })
    } catch(err) {
        next(err)
    }
}) 

I again used bcrypt to encrypt the newly updated password

Natsuko Izuki
  • 443
  • 1
  • 4
  • 10