mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor: add 2fa
This commit is contained in:
parent
e1632cbdb3
commit
0e8e92c715
@ -78,7 +78,9 @@ export const ShowUsers = () => {
|
||||
<TableHead className="w-[100px]">Email</TableHead>
|
||||
<TableHead className="text-center">Role</TableHead>
|
||||
<TableHead className="text-center">2FA</TableHead>
|
||||
{/* <TableHead className="text-center">Status</TableHead> */}
|
||||
<TableHead className="text-center">
|
||||
Is Registered
|
||||
</TableHead>
|
||||
<TableHead className="text-center">
|
||||
Created At
|
||||
</TableHead>
|
||||
@ -104,15 +106,15 @@ export const ShowUsers = () => {
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
{/* {user.user.is2FAEnabled
|
||||
? "2FA Enabled"
|
||||
: "2FA Not Enabled"} */}
|
||||
{user.user.twoFactorEnabled
|
||||
? "Enabled"
|
||||
: "Disabled"}
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
{user.user.isRegistered || user.role === "owner"
|
||||
? "Registered"
|
||||
: "Not Registered"}
|
||||
</TableCell>
|
||||
{/* <TableCell className="text-right">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{format(new Date(user.createdAt), "PPpp")}
|
||||
</span>
|
||||
</TableCell> */}
|
||||
<TableCell className="text-right">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{format(new Date(user.createdAt), "PPpp")}
|
||||
@ -134,29 +136,30 @@ export const ShowUsers = () => {
|
||||
<DropdownMenuLabel>
|
||||
Actions
|
||||
</DropdownMenuLabel>
|
||||
{/* {!user.isRegistered && (
|
||||
<DropdownMenuItem
|
||||
className="w-full cursor-pointer"
|
||||
onSelect={(e) => {
|
||||
copy(
|
||||
`${origin}/invitation?token=${user.token}`,
|
||||
);
|
||||
toast.success(
|
||||
"Invitation Copied to clipboard",
|
||||
);
|
||||
}}
|
||||
>
|
||||
Copy Invitation
|
||||
</DropdownMenuItem>
|
||||
)} */}
|
||||
{!user.user.isRegistered &&
|
||||
user.role !== "owner" && (
|
||||
<DropdownMenuItem
|
||||
className="w-full cursor-pointer"
|
||||
onSelect={(e) => {
|
||||
copy(
|
||||
`${origin}/invitation?token=${user.user.token}`,
|
||||
);
|
||||
toast.success(
|
||||
"Invitation Copied to clipboard",
|
||||
);
|
||||
}}
|
||||
>
|
||||
Copy Invitation
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
{/* {user.isRegistered && (
|
||||
{user.user.isRegistered && (
|
||||
<AddUserPermissions
|
||||
userId={user.userId}
|
||||
/>
|
||||
)} */}
|
||||
)}
|
||||
|
||||
{/* {user.role !== "owner" && (
|
||||
{user.role !== "owner" && (
|
||||
<DialogAction
|
||||
title="Delete User"
|
||||
description="Are you sure you want to delete this user?"
|
||||
@ -185,7 +188,7 @@ export const ShowUsers = () => {
|
||||
Delete User
|
||||
</DropdownMenuItem>
|
||||
</DialogAction>
|
||||
)} */}
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
|
@ -25,7 +25,8 @@ WITH inserted_users AS (
|
||||
"stripeSubscriptionId",
|
||||
"serversQuantity",
|
||||
"expirationDate",
|
||||
"createdAt"
|
||||
"createdAt",
|
||||
"two_factor_enabled"
|
||||
)
|
||||
SELECT
|
||||
a."adminId",
|
||||
@ -50,11 +51,30 @@ WITH inserted_users AS (
|
||||
a."stripeSubscriptionId",
|
||||
a."serversQuantity",
|
||||
NOW() + INTERVAL '1 year',
|
||||
NOW()
|
||||
NOW(),
|
||||
COALESCE(auth."is2FAEnabled", false)
|
||||
FROM admin a
|
||||
JOIN auth ON auth.id = a."authId"
|
||||
RETURNING *
|
||||
),
|
||||
inserted_two_factor_admin AS (
|
||||
-- Insertar registros en two_factor para admins con 2FA habilitado
|
||||
INSERT INTO two_factor (
|
||||
id,
|
||||
secret,
|
||||
backup_codes,
|
||||
user_id
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
auth.secret,
|
||||
gen_random_uuid()::text,
|
||||
a."adminId"
|
||||
FROM admin a
|
||||
JOIN auth ON auth.id = a."authId"
|
||||
WHERE auth."is2FAEnabled" = true
|
||||
RETURNING *
|
||||
),
|
||||
inserted_accounts AS (
|
||||
-- Insertar cuentas para los admins
|
||||
INSERT INTO account (
|
||||
@ -120,7 +140,8 @@ inserted_members AS (
|
||||
"canDeleteServices",
|
||||
"accesedProjects",
|
||||
"accesedServices",
|
||||
"expirationDate"
|
||||
"expirationDate",
|
||||
"two_factor_enabled"
|
||||
)
|
||||
SELECT
|
||||
u."userId",
|
||||
@ -141,7 +162,8 @@ inserted_members AS (
|
||||
COALESCE(u."canDeleteServices", false),
|
||||
COALESCE(u."accesedProjects", '{}'),
|
||||
COALESCE(u."accesedServices", '{}'),
|
||||
NOW() + INTERVAL '1 year'
|
||||
NOW() + INTERVAL '1 year',
|
||||
COALESCE(auth."is2FAEnabled", false)
|
||||
FROM "user" u
|
||||
JOIN admin a ON u."adminId" = a."adminId"
|
||||
JOIN auth ON auth.id = u."authId"
|
||||
@ -173,6 +195,25 @@ inserted_member_accounts AS (
|
||||
JOIN auth ON auth.id = u."authId"
|
||||
RETURNING *
|
||||
),
|
||||
inserted_two_factor_members AS (
|
||||
-- Insertar registros en two_factor para miembros con 2FA habilitado
|
||||
INSERT INTO two_factor (
|
||||
id,
|
||||
secret,
|
||||
backup_codes,
|
||||
user_id
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
auth.secret,
|
||||
gen_random_uuid()::text,
|
||||
u."userId"
|
||||
FROM "user" u
|
||||
JOIN admin a ON u."adminId" = a."adminId"
|
||||
JOIN auth ON auth.id = u."authId"
|
||||
WHERE auth."is2FAEnabled" = true
|
||||
RETURNING *
|
||||
),
|
||||
inserted_admin_members AS (
|
||||
-- Insertar miembros en las organizaciones (admins como owners)
|
||||
INSERT INTO member (
|
||||
|
@ -27,6 +27,7 @@ import { type ReactElement, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import superjson from "superjson";
|
||||
|
||||
const registerSchema = z
|
||||
.object({
|
||||
@ -98,9 +99,9 @@ const Invitation = ({ token, invitation, isCloud }: Props) => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.auth?.email) {
|
||||
if (data?.email) {
|
||||
form.reset({
|
||||
email: data?.auth?.email || "",
|
||||
email: data?.email || "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
});
|
||||
@ -109,7 +110,7 @@ const Invitation = ({ token, invitation, isCloud }: Props) => {
|
||||
|
||||
const onSubmit = async (values: Register) => {
|
||||
await mutateAsync({
|
||||
id: data?.authId,
|
||||
id: data?.id,
|
||||
password: values.password,
|
||||
token: token,
|
||||
})
|
||||
@ -254,6 +255,7 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) {
|
||||
const { query } = ctx;
|
||||
|
||||
const token = query.token;
|
||||
console.log("query", query);
|
||||
|
||||
if (typeof token !== "string") {
|
||||
return {
|
||||
@ -266,6 +268,7 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) {
|
||||
|
||||
try {
|
||||
const invitation = await getUserByToken(token);
|
||||
console.log("invitation", invitation);
|
||||
|
||||
if (invitation.isExpired) {
|
||||
return {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import {
|
||||
boolean,
|
||||
integer,
|
||||
pgTable,
|
||||
text,
|
||||
integer,
|
||||
timestamp,
|
||||
boolean,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
export const users_temp = pgTable("users_temp", {
|
||||
|
@ -16,7 +16,16 @@ export const auth = betterAuth({
|
||||
provider: "pg",
|
||||
schema: schema,
|
||||
}),
|
||||
|
||||
socialProviders: {
|
||||
github: {
|
||||
clientId: process.env.GITHUB_CLIENT_ID as string,
|
||||
clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
|
||||
},
|
||||
google: {
|
||||
clientId: process.env.GOOGLE_CLIENT_ID as string,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
|
||||
},
|
||||
},
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
|
||||
|
@ -106,26 +106,25 @@ export const isAdminPresent = async () => {
|
||||
};
|
||||
|
||||
export const getUserByToken = async (token: string) => {
|
||||
// const user = await db.query.users.findFirst({
|
||||
// where: eq(users.token, token),
|
||||
// with: {
|
||||
// auth: {
|
||||
// columns: {
|
||||
// password: false,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// if (!user) {
|
||||
// throw new TRPCError({
|
||||
// code: "NOT_FOUND",
|
||||
// message: "Invitation not found",
|
||||
// });
|
||||
// }
|
||||
// return {
|
||||
// ...user,
|
||||
// isExpired: user.isRegistered,
|
||||
// };
|
||||
const user = await db.query.users_temp.findFirst({
|
||||
where: eq(users_temp.token, token),
|
||||
columns: {
|
||||
id: true,
|
||||
email: true,
|
||||
token: true,
|
||||
isRegistered: true,
|
||||
},
|
||||
});
|
||||
if (!user) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Invitation not found",
|
||||
});
|
||||
}
|
||||
return {
|
||||
...user,
|
||||
isExpired: user.isRegistered,
|
||||
};
|
||||
};
|
||||
|
||||
export const removeUserById = async (userId: string) => {
|
||||
|
@ -29,16 +29,15 @@ class LogRotationManager {
|
||||
}
|
||||
|
||||
private async getStateFromDB(): Promise<boolean> {
|
||||
const setting = await db.query.admins.findFirst({});
|
||||
return setting?.enableLogRotation ?? false;
|
||||
// const setting = await db.query.admins.findFirst({});
|
||||
// return setting?.enableLogRotation ?? false;
|
||||
}
|
||||
|
||||
private async setStateInDB(active: boolean): Promise<void> {
|
||||
const admin = await db.query.admins.findFirst({});
|
||||
|
||||
if (!admin) {
|
||||
return;
|
||||
}
|
||||
// const admin = await db.query.admins.findFirst({});
|
||||
// if (!admin) {
|
||||
// return;
|
||||
// }
|
||||
// await updateAdmin(admin?.authId, {
|
||||
// enableLogRotation: active,
|
||||
// });
|
||||
|
Loading…
Reference in New Issue
Block a user