Browse Source

use transactions for updating user

Pouria Ezzati 1 năm trước cách đây
mục cha
commit
458c2a4820

+ 15 - 27
server/handlers/auth.handler.js

@@ -147,15 +147,11 @@ function login(req, res) {
 async function verify(req, res, next) {
   if (!req.params.verificationToken) return next();
 
-  const user = await query.user.find({
-    verification_token: req.params.verificationToken,
-    verification_expires: [">", utils.dateToUTC(new Date())]
-  });
-
-  if (!user) return next();
-  
-  const [updatedUser] = await query.user.update(
-    { id: user.id },
+  const user = await query.user.update(
+    {
+      verification_token: req.params.verificationToken,
+      verification_expires: [">", utils.dateToUTC(new Date())]
+    },
     {
       verified: true,
       verification_token: null,
@@ -163,7 +159,7 @@ async function verify(req, res, next) {
     }
   );
   
-  if (updatedUser) {
+  if (user) {
     const token = utils.signToken(user);
     utils.deleteCurrentToken(res);
     utils.setToken(res, token);
@@ -185,7 +181,7 @@ async function changePassword(req, res) {
   const salt = await bcrypt.genSalt(12);
   const newpassword = await bcrypt.hash(req.body.newpassword, salt);
   
-  const [user] = await query.user.update({ id: req.user.id }, { password: newpassword });
+  const user = await query.user.update({ id: req.user.id }, { password: newpassword });
   
   if (!user) {
     throw new CustomError("Couldn't change the password. Try again later.");
@@ -211,7 +207,7 @@ async function generateApiKey(req, res) {
     redis.remove.user(req.user);
   }
   
-  const [user] = await query.user.update({ id: req.user.id }, { apikey });
+  const user = await query.user.update({ id: req.user.id }, { apikey });
   
   if (!user) {
     throw new CustomError("Couldn't generate API key. Please try again later.");
@@ -228,7 +224,7 @@ async function generateApiKey(req, res) {
 }
 
 async function resetPasswordRequest(req, res) {
-  const [user] = await query.user.update(
+  const user = await query.user.update(
     { email: req.body.email },
     {
       reset_password_token: uuid(),
@@ -258,14 +254,14 @@ async function resetPassword(req, res, next) {
   const resetPasswordToken = req.params.resetPasswordToken;
 
   if (resetPasswordToken) {
-    const [user] = await query.user.update(
+    const user = await query.user.update(
       {
         reset_password_token: resetPasswordToken,
         reset_password_expires: [">", utils.dateToUTC(new Date())]
       },
       { reset_password_expires: null, reset_password_token: null }
     );
-  
+
     if (user) {
       const token = utils.signToken(user);
       utils.deleteCurrentToken(res);
@@ -289,15 +285,15 @@ async function changeEmailRequest(req, res) {
     throw new CustomError(error, 401);
   }
   
-  const currentUser = await query.user.find({ email });
+  const user = await query.user.find({ email });
   
-  if (currentUser) {
+  if (user) {
     const error = "Can't use this email address.";
     res.locals.errors = { email: error };
     throw new CustomError(error, 400);
   }
   
-  const [updatedUser] = await query.user.update(
+  const updatedUser = await query.user.update(
     { id: req.user.id },
     {
       change_email_address: email,
@@ -306,10 +302,6 @@ async function changeEmailRequest(req, res) {
     }
   );
   
-  if (env.REDIS_ENABLED) {
-    redis.remove.user(updatedUser);
-  }
-  
   if (updatedUser) {
     await mail.changeEmail({ ...updatedUser, email });
   }
@@ -338,7 +330,7 @@ async function changeEmail(req, res, next) {
   
     if (!foundUser) return next();
   
-    const [user] = await query.user.update(
+    const user = await query.user.update(
       { id: foundUser.id },
       {
         change_email_token: null,
@@ -348,10 +340,6 @@ async function changeEmail(req, res, next) {
       }
     );
   
-    if (env.REDIS_ENABLED) {
-      redis.remove.user(foundUser);
-    }
-  
     if (user) {
       const token = utils.signToken(user);
       utils.deleteCurrentToken(res);

+ 1 - 1
server/handlers/validators.handler.js

@@ -535,7 +535,7 @@ async function malware(user, target) {
   if (!isMalware.data || !isMalware.data.matches) return;
 
   if (user) {
-    const [updatedUser] = await query.user.update(
+    const updatedUser = await query.user.update(
       { id: user.id },
       { cooldown: utils.dateToUTC(new Date()) },
       { increments: ["malicious_attempts"] }

+ 22 - 17
server/queries/user.queries.js

@@ -63,28 +63,33 @@ async function add(params, user) {
 }
 
 async function update(match, update, methods) {
-  const query = knex("users");
+  const user = await knex.transaction(async function(trx) {
+    const query = trx("users");
+    Object.entries(match).forEach(([key, value]) => {
+      query.andWhere(key, ...(Array.isArray(value) ? value : [value]));
+    });
 
-  Object.entries(match).forEach(([key, value]) => {
-    query.andWhere(key, ...(Array.isArray(value) ? value : [value]));
+    const user = await query.select("id").first();
+    if (!user) return null;
+    
+    const updateQuery = trx("users").where("id", user.id);
+    if (methods?.increments) {
+      methods.increments.forEach(columnName => {
+        updateQuery.increment(columnName);
+      });
+    }
+    
+    await updateQuery.update({ ...update, updated_at: utils.dateToUTC(new Date()) });
+    const updatedUser = await trx("users").where("id", user.id).first();
+
+    return updatedUser;
   });
 
-  const updateQuery = query.clone();
-  if (methods?.increments) {
-    methods.increments.forEach(columnName => {
-      updateQuery.increment(columnName);
-    });
+  if (env.REDIS_ENABLED && user) {
+    redis.remove.user(user);
   }
-  
-  await updateQuery.update({ ...update, updated_at: utils.dateToUTC(new Date()) });
 
-  const users = await query.select("*");
-
-  if (env.REDIS_ENABLED) {
-    users.forEach(redis.remove.user);
-  }
-  
-  return users;
+  return user;
 }
 
 async function remove(user) {