diff --git a/server/models/user.js b/server/models/user.js
index c447950caa985fb23109dc588ea6b92d47c2e6ee..ecb620ee4fd24be28c53790163229defa31bfe26 100644
--- a/server/models/user.js
+++ b/server/models/user.js
@@ -2,6 +2,23 @@ const prisma = require("../utils/prisma");
 const { EventLogs } = require("./eventLogs");
 
 const User = {
+  writable: [
+    // Used for generic updates so we can validate keys in request body
+    "username",
+    "password",
+    "pfpFilename",
+    "role",
+    "suspended",
+  ],
+  // validations for the above writable fields.
+  castColumnValue: function (key, value) {
+    switch (key) {
+      case "suspended":
+        return Number(Boolean(value));
+      default:
+        return String(value);
+    }
+  },
   create: async function ({ username, password, role = "default" }) {
     const passwordCheck = this.checkPasswordComplexity(password);
     if (!passwordCheck.checkedOK) {
@@ -42,13 +59,26 @@ const User = {
 
   update: async function (userId, updates = {}) {
     try {
+      if (!userId) throw new Error("No user id provided for update");
       const currentUser = await prisma.users.findUnique({
         where: { id: parseInt(userId) },
       });
-      if (!currentUser) {
-        return { success: false, error: "User not found" };
-      }
+      if (!currentUser) return { success: false, error: "User not found" };
+
+      // Removes non-writable fields for generic updates
+      // and force-casts to the proper type;
+      Object.entries(updates).forEach(([key, value]) => {
+        if (this.writable.includes(key)) {
+          updates[key] = this.castColumnValue(key, value);
+          return;
+        }
+        delete updates[key];
+      });
+
+      if (Object.keys(updates).length === 0)
+        return { success: false, error: "No valid updates applied." };
 
+      // Handle password specific updates
       if (updates.hasOwnProperty("password")) {
         const passwordCheck = this.checkPasswordComplexity(updates.password);
         if (!passwordCheck.checkedOK) {
@@ -78,6 +108,24 @@ const User = {
     }
   },
 
+  // Explicit direct update of user object.
+  // Only use this method when directly setting a key value
+  // that takes no user input for the keys being modified.
+  _update: async function (id = null, data = {}) {
+    if (!id) throw new Error("No user id provided for update");
+
+    try {
+      const user = await prisma.users.update({
+        where: { id },
+        data,
+      });
+      return { user, message: null };
+    } catch (error) {
+      console.error(error.message);
+      return { user: null, message: error.message };
+    }
+  },
+
   get: async function (clause = {}) {
     try {
       const user = await prisma.users.findFirst({ where: clause });
diff --git a/server/utils/AiProviders/openRouter/index.js b/server/utils/AiProviders/openRouter/index.js
index ac72b16794cb785d810fdabb9af4b6e39d3c9753..655839dc3a51a4c930e1ef609c60c417d9825a0b 100644
--- a/server/utils/AiProviders/openRouter/index.js
+++ b/server/utils/AiProviders/openRouter/index.js
@@ -296,7 +296,7 @@ class OpenRouterLLM {
           try {
             JSON.parse(message);
             validJSON = true;
-          } catch { }
+          } catch {}
 
           if (!validJSON) {
             // It can be possible that the chunk decoding is running away
diff --git a/server/utils/PasswordRecovery/index.js b/server/utils/PasswordRecovery/index.js
index fbcbe579971ecb888a322e426a5416e2c94a5f27..2383dd2c3f3ec2bb24beba4d7b0c5dd1d380556b 100644
--- a/server/utils/PasswordRecovery/index.js
+++ b/server/utils/PasswordRecovery/index.js
@@ -22,7 +22,7 @@ async function generateRecoveryCodes(userId) {
   const { error } = await RecoveryCode.createMany(newRecoveryCodes);
   if (!!error) throw new Error(error);
 
-  const { success } = await User.update(userId, {
+  const { user: success } = await User._update(userId, {
     seen_recovery_codes: true,
   });
   if (!success) throw new Error("Failed to generate user recovery codes!");
@@ -80,6 +80,11 @@ async function resetPassword(token, _newPassword = "", confirmPassword = "") {
   // JOI password rules will be enforced inside .update.
   const { error } = await User.update(resetToken.user_id, {
     password: newPassword,
+  });
+
+  // seen_recovery_codes is not publicly writable
+  // so we have to do direct update here
+  await User._update(resetToken.user_id, {
     seen_recovery_codes: false,
   });