mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-16 04:35:24 +02:00
feat(password-update): enhance password update functionality across database routers
- Added confirmation password field and validation to the `UpdateDatabasePassword` component. - Refactored password update logic in MariaDB, MongoDB, MySQL, Postgres, and Redis routers to utilize database transactions for improved reliability. - Ensured consistent handling of password updates across all database types, enhancing user experience and security.
This commit is contained in:
@@ -24,9 +24,15 @@ import {
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
const updatePasswordSchema = z.object({
|
||||
password: z.string().min(1, "Password is required"),
|
||||
});
|
||||
const updatePasswordSchema = z
|
||||
.object({
|
||||
password: z.string().min(1, "Password is required"),
|
||||
confirmPassword: z.string().min(1, "Please confirm the password"),
|
||||
})
|
||||
.refine((data) => data.password === data.confirmPassword, {
|
||||
message: "Passwords do not match",
|
||||
path: ["confirmPassword"],
|
||||
});
|
||||
|
||||
type UpdatePassword = z.infer<typeof updatePasswordSchema>;
|
||||
|
||||
@@ -44,7 +50,7 @@ export const UpdateDatabasePassword = ({
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
const form = useForm<UpdatePassword>({
|
||||
defaultValues: { password: "" },
|
||||
defaultValues: { password: "", confirmPassword: "" },
|
||||
resolver: zodResolver(updatePasswordSchema),
|
||||
});
|
||||
|
||||
@@ -122,6 +128,23 @@ export const UpdateDatabasePassword = ({
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="confirmPassword"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Confirm {label}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder={`Confirm new ${label.toLowerCase()}`}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<Button isLoading={isPending} type="submit">
|
||||
Update
|
||||
|
||||
@@ -400,17 +400,22 @@ export const mariadbRouter = createTRPCRouter({
|
||||
docker exec "$CONTAINER_ID" mariadb -u root -p'${databaseRootPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;"
|
||||
`;
|
||||
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
await db.transaction(async (tx) => {
|
||||
const setData =
|
||||
type === "root"
|
||||
? { databaseRootPassword: password }
|
||||
: { databasePassword: password };
|
||||
await tx
|
||||
.update(mariadbTable)
|
||||
.set(setData)
|
||||
.where(eq(mariadbTable.mariadbId, mariadbId));
|
||||
|
||||
if (type === "root") {
|
||||
await updateMariadbById(mariadbId, { databaseRootPassword: password });
|
||||
} else {
|
||||
await updateMariadbById(mariadbId, { databasePassword: password });
|
||||
}
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
});
|
||||
|
||||
await audit(ctx, {
|
||||
action: "update",
|
||||
|
||||
@@ -419,13 +419,18 @@ export const mongoRouter = createTRPCRouter({
|
||||
docker exec "$CONTAINER_ID" mongosh -u '${databaseUser}' -p '${databasePassword}' --authenticationDatabase admin --eval "db.getSiblingDB('admin').changeUserPassword('${databaseUser}', '${password}')"
|
||||
`;
|
||||
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
await db.transaction(async (tx) => {
|
||||
await tx
|
||||
.update(mongoTable)
|
||||
.set({ databasePassword: password })
|
||||
.where(eq(mongoTable.mongoId, mongoId));
|
||||
|
||||
await updateMongoById(mongoId, { databasePassword: password });
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
});
|
||||
|
||||
await audit(ctx, {
|
||||
action: "update",
|
||||
|
||||
@@ -408,8 +408,6 @@ export const mysqlRouter = createTRPCRouter({
|
||||
const { appName, serverId, databaseUser, databaseRootPassword } = my;
|
||||
|
||||
const containerCmd = getServiceContainerCommand(appName);
|
||||
const authPassword =
|
||||
type === "root" ? databaseRootPassword : databaseRootPassword;
|
||||
const targetUser = type === "root" ? "root" : databaseUser;
|
||||
|
||||
const command = `
|
||||
@@ -418,20 +416,25 @@ export const mysqlRouter = createTRPCRouter({
|
||||
echo "No running container found for ${appName}" >&2
|
||||
exit 1
|
||||
fi
|
||||
docker exec "$CONTAINER_ID" mysql -u root -p'${authPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;"
|
||||
docker exec "$CONTAINER_ID" mysql -u root -p'${databaseRootPassword}' -e "ALTER USER '${targetUser}'@'%' IDENTIFIED BY '${password}'; FLUSH PRIVILEGES;"
|
||||
`;
|
||||
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
await db.transaction(async (tx) => {
|
||||
const setData =
|
||||
type === "root"
|
||||
? { databaseRootPassword: password }
|
||||
: { databasePassword: password };
|
||||
await tx
|
||||
.update(mysqlTable)
|
||||
.set(setData)
|
||||
.where(eq(mysqlTable.mysqlId, mysqlId));
|
||||
|
||||
if (type === "root") {
|
||||
await updateMySqlById(mysqlId, { databaseRootPassword: password });
|
||||
} else {
|
||||
await updateMySqlById(mysqlId, { databasePassword: password });
|
||||
}
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
});
|
||||
|
||||
await audit(ctx, {
|
||||
action: "update",
|
||||
|
||||
@@ -424,13 +424,19 @@ export const postgresRouter = createTRPCRouter({
|
||||
fi
|
||||
docker exec "$CONTAINER_ID" psql -U ${databaseUser} -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"
|
||||
`;
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
|
||||
await updatePostgresById(postgresId, { databasePassword: password });
|
||||
await db.transaction(async (tx) => {
|
||||
await tx
|
||||
.update(postgresTable)
|
||||
.set({ databasePassword: password })
|
||||
.where(eq(postgresTable.postgresId, postgresId));
|
||||
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
});
|
||||
|
||||
await audit(ctx, {
|
||||
action: "update",
|
||||
|
||||
@@ -406,13 +406,18 @@ export const redisRouter = createTRPCRouter({
|
||||
docker exec "$CONTAINER_ID" redis-cli -a '${databasePassword}' CONFIG SET requirepass '${password}'
|
||||
`;
|
||||
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
await db.transaction(async (tx) => {
|
||||
await tx
|
||||
.update(redisTable)
|
||||
.set({ databasePassword: password })
|
||||
.where(eq(redisTable.redisId, redisId));
|
||||
|
||||
await updateRedisById(redisId, { databasePassword: password });
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
await execAsync(command, { shell: "/bin/bash" });
|
||||
}
|
||||
});
|
||||
|
||||
await audit(ctx, {
|
||||
action: "update",
|
||||
|
||||
Reference in New Issue
Block a user