From dada3049a84768c134f127c447e4489fb9bfd87e Mon Sep 17 00:00:00 2001 From: Shuvo Date: Mon, 31 Aug 2026 22:33:08 +0600 Subject: [PATCH] feat: allow reset-password script to target a specific user by email Previously reset-password only reset the owner account's password. Passing an email as an argument now resets that specific user's password instead, while omitting it keeps the existing owner-reset behavior. Also scopes the update to the credential (password-based) account row via providerId, and fixes the success check to verify a row was actually updated instead of always reporting success. --- CONTRIBUTING.md | 10 +++++++++- apps/dokploy/reset-password.ts | 32 ++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4fa0dd358..daf538b1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -120,12 +120,20 @@ pnpm run docker:push ## Password Reset -In the case you lost your password, you can reset it using the following command +In the case you lost your password, you can reset the owner's password using the following command ```bash pnpm run reset-password ``` +To reset the password of a specific user instead, pass their email as an argument + +```bash +pnpm run reset-password -- user@example.com +``` + +Both commands print the new randomly generated password to the console. + If you want to test the webhooks on development mode using localtunnel, make sure to install [`localtunnel`](https://localtunnel.app/) ```bash diff --git a/apps/dokploy/reset-password.ts b/apps/dokploy/reset-password.ts index 5b1db9bcf..9d42ac8d9 100644 --- a/apps/dokploy/reset-password.ts +++ b/apps/dokploy/reset-password.ts @@ -1,30 +1,50 @@ import { findOwner, generateRandomPassword } from "@dokploy/server"; import { db } from "@dokploy/server/db"; -import { account } from "@dokploy/server/db/schema"; -import { eq } from "drizzle-orm"; +import { account, user } from "@dokploy/server/db/schema"; +import { and, eq } from "drizzle-orm"; (async () => { try { + const email = process.argv[2]; + const randomPassword = await generateRandomPassword(); - const result = await findOwner(); + let userId: string; + + if (email) { + const foundUser = await db.query.user.findFirst({ + where: eq(user.email, email), + }); + + if (!foundUser) { + console.log(`User not found for email: ${email}`); + process.exit(1); + } + + userId = foundUser.id; + } else { + const owner = await findOwner(); + userId = owner.userId; + } const update = await db .update(account) .set({ password: randomPassword.hashedPassword, }) - .where(eq(account.userId, result.userId)); + .where(and(eq(account.userId, userId), eq(account.providerId, "credential"))); - if (update) { + if (update.count > 0) { console.log("Password reset successful"); console.log("New password: ", randomPassword.randomPassword); } else { - console.log("Password reset failed"); + console.log("Password reset failed: no credential account found for this user"); + process.exit(1); } process.exit(0); } catch (error) { console.log("Error resetting password", error); + process.exit(1); } })();