mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
chore: clean up unused variables and improve error handling across codebase
This commit focuses on removing unused variables, adding placeholder error handling, and generally tidying up various files across the Dokploy application. Changes include: - Removing unused imports and variables - Adding placeholder error handling in catch blocks - Cleaning up commented-out code - Removing deprecated utility files - Improving type safety and code consistency
This commit is contained in:
@@ -130,7 +130,7 @@ const createStringToJSONSchema = (schema: z.ZodTypeAny) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return JSON.parse(str);
|
return JSON.parse(str);
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
ctx.addIssue({ code: "custom", message: "Invalid JSON format" });
|
ctx.addIssue({ code: "custom", message: "Invalid JSON format" });
|
||||||
return z.NEVER;
|
return z.NEVER;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export const UpdateVolume = ({
|
|||||||
serviceType,
|
serviceType,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const utils = api.useUtils();
|
const _utils = api.useUtils();
|
||||||
const { data } = api.mounts.one.useQuery(
|
const { data } = api.mounts.one.useQuery(
|
||||||
{
|
{
|
||||||
mountId,
|
mountId,
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ export const SaveBitbucketProvider = ({ applicationId }: Props) => {
|
|||||||
data: repositories,
|
data: repositories,
|
||||||
isLoading: isLoadingRepositories,
|
isLoading: isLoadingRepositories,
|
||||||
error,
|
error,
|
||||||
isError,
|
|
||||||
} = api.bitbucket.getBitbucketRepositories.useQuery(
|
} = api.bitbucket.getBitbucketRepositories.useQuery(
|
||||||
{
|
{
|
||||||
bitbucketId,
|
bitbucketId,
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
const { mutateAsync: stop, isLoading: isStopping } =
|
const { mutateAsync: stop, isLoading: isStopping } =
|
||||||
api.application.stop.useMutation();
|
api.application.stop.useMutation();
|
||||||
|
|
||||||
const { mutateAsync: deploy, isLoading: isDeploying } =
|
const { mutateAsync: deploy } = api.application.deploy.useMutation();
|
||||||
api.application.deploy.useMutation();
|
|
||||||
|
|
||||||
const { mutateAsync: reload, isLoading: isReloading } =
|
const { mutateAsync: reload, isLoading: isReloading } =
|
||||||
api.application.reload.useMutation();
|
api.application.reload.useMutation();
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ export const ShowPreviewSettings = ({ applicationId }: Props) => {
|
|||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="env"
|
name="env"
|
||||||
render={({ field }) => (
|
render={() => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Secrets
|
<Secrets
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const DeleteService = ({ id, type }: Props) => {
|
|||||||
compose: () =>
|
compose: () =>
|
||||||
api.compose.one.useQuery({ composeId: id }, { enabled: !!id }),
|
api.compose.one.useQuery({ composeId: id }, { enabled: !!id }),
|
||||||
};
|
};
|
||||||
const { data, refetch } = queryMap[type]
|
const { data } = queryMap[type]
|
||||||
? queryMap[type]()
|
? queryMap[type]()
|
||||||
: api.mongo.one.useQuery({ mongoId: id }, { enabled: !!id });
|
: api.mongo.one.useQuery({ mongoId: id }, { enabled: !!id });
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export const ShowDomainsCompose = ({ composeId }: Props) => {
|
|||||||
await deleteDomain({
|
await deleteDomain({
|
||||||
domainId: item.domainId,
|
domainId: item.domainId,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((_data) => {
|
||||||
refetch();
|
refetch();
|
||||||
toast.success("Domain deleted successfully");
|
toast.success("Domain deleted successfully");
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ export const ComposeFileEditor = ({ composeId }: Props) => {
|
|||||||
{ enabled: !!composeId },
|
{ enabled: !!composeId },
|
||||||
);
|
);
|
||||||
|
|
||||||
const { mutateAsync, isLoading, error, isError } =
|
const { mutateAsync, isLoading } = api.compose.update.useMutation();
|
||||||
api.compose.update.useMutation();
|
|
||||||
|
|
||||||
const form = useForm<AddComposeFile>({
|
const form = useForm<AddComposeFile>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -76,7 +75,7 @@ export const ComposeFileEditor = ({ composeId }: Props) => {
|
|||||||
composeId,
|
composeId,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((_e) => {
|
||||||
toast.error("Error updating the Compose config");
|
toast.error("Error updating the Compose config");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ export const SaveBitbucketProviderCompose = ({ composeId }: Props) => {
|
|||||||
data: repositories,
|
data: repositories,
|
||||||
isLoading: isLoadingRepositories,
|
isLoading: isLoadingRepositories,
|
||||||
error,
|
error,
|
||||||
isError,
|
|
||||||
} = api.bitbucket.getBitbucketRepositories.useQuery(
|
} = api.bitbucket.getBitbucketRepositories.useQuery(
|
||||||
{
|
{
|
||||||
bitbucketId,
|
bitbucketId,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export const IsolatedDeployment = ({ composeId }: Props) => {
|
|||||||
composeId,
|
composeId,
|
||||||
isolatedDeployment: formData?.isolatedDeployment || false,
|
isolatedDeployment: formData?.isolatedDeployment || false,
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (_data) => {
|
||||||
randomizeCompose();
|
randomizeCompose();
|
||||||
refetch();
|
refetch();
|
||||||
toast.success("Compose updated");
|
toast.success("Compose updated");
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ type Schema = z.infer<typeof schema>;
|
|||||||
export const RandomizeCompose = ({ composeId }: Props) => {
|
export const RandomizeCompose = ({ composeId }: Props) => {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const [compose, setCompose] = useState<string>("");
|
const [compose, setCompose] = useState<string>("");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [_isOpen, _setIsOpen] = useState(false);
|
||||||
const { mutateAsync, error, isError } =
|
const { mutateAsync, error, isError } =
|
||||||
api.compose.randomizeCompose.useMutation();
|
api.compose.randomizeCompose.useMutation();
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ export const RandomizeCompose = ({ composeId }: Props) => {
|
|||||||
suffix: formData?.suffix || "",
|
suffix: formData?.suffix || "",
|
||||||
randomize: formData?.randomize || false,
|
randomize: formData?.randomize || false,
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (_data) => {
|
||||||
randomizeCompose();
|
randomizeCompose();
|
||||||
refetch();
|
refetch();
|
||||||
toast.success("Compose updated");
|
toast.success("Compose updated");
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const ShowConvertedCompose = ({ composeId }: Props) => {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((_err) => {});
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
|
|||||||
@@ -29,14 +29,6 @@ interface Props {
|
|||||||
data: ContainerMetric[];
|
data: ContainerMetric[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FormattedMetric {
|
|
||||||
timestamp: string;
|
|
||||||
read: number;
|
|
||||||
write: number;
|
|
||||||
readUnit: string;
|
|
||||||
writeUnit: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const chartConfig = {
|
const chartConfig = {
|
||||||
read: {
|
read: {
|
||||||
label: "Read",
|
label: "Read",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ interface Props {
|
|||||||
organizationId?: string;
|
organizationId?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
export function AddOrganization({ organizationId, children }: Props) {
|
export function AddOrganization({ organizationId }: Props) {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { data: organization } = api.organization.one.useQuery(
|
const { data: organization } = api.organization.one.useQuery(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const ShowCustomCommand = ({ id, type }: Props) => {
|
|||||||
mongo: () => api.mongo.update.useMutation(),
|
mongo: () => api.mongo.update.useMutation(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const { mutateAsync, isLoading } = mutationMap[type]
|
const { mutateAsync } = mutationMap[type]
|
||||||
? mutationMap[type]()
|
? mutationMap[type]()
|
||||||
: api.mongo.update.useMutation();
|
: api.mongo.update.useMutation();
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const AddApplication = ({ projectId, projectName }: Props) => {
|
|||||||
projectId,
|
projectId,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((_e) => {
|
||||||
toast.error("Error creating the service");
|
toast.error("Error creating the service");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -434,14 +434,14 @@ export const AddTemplate = ({ projectId }: Props) => {
|
|||||||
});
|
});
|
||||||
toast.promise(promise, {
|
toast.promise(promise, {
|
||||||
loading: "Setting up...",
|
loading: "Setting up...",
|
||||||
success: (data) => {
|
success: (_data) => {
|
||||||
utils.project.one.invalidate({
|
utils.project.one.invalidate({
|
||||||
projectId,
|
projectId,
|
||||||
});
|
});
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
return `${template.name} template created successfully`;
|
return `${template.name} template created successfully`;
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (_err) => {
|
||||||
return `An error ocurred deploying ${template.name} template`;
|
return `An error ocurred deploying ${template.name} template`;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const ShowExternalRedisCredentials = ({ redisId }: Props) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const buildConnectionUrl = () => {
|
const buildConnectionUrl = () => {
|
||||||
const hostname = window.location.hostname;
|
const _hostname = window.location.hostname;
|
||||||
const port = form.watch("externalPort") || data?.externalPort;
|
const port = form.watch("externalPort") || data?.externalPort;
|
||||||
|
|
||||||
return `redis://default:${data?.databasePassword}@${getIp}:${port}`;
|
return `redis://default:${data?.databasePassword}@${getIp}:${port}`;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const getStatusColor = (status: number) => {
|
|||||||
export const columns: ColumnDef<LogEntry>[] = [
|
export const columns: ColumnDef<LogEntry>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "level",
|
accessorKey: "level",
|
||||||
header: ({ column }) => {
|
header: () => {
|
||||||
return <Button variant="ghost">Level</Button>;
|
return <Button variant="ghost">Level</Button>;
|
||||||
},
|
},
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export const RequestsTable = () => {
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: statsLogs, isLoading } = api.settings.readStatsLogs.useQuery(
|
const { data: statsLogs } = api.settings.readStatsLogs.useQuery(
|
||||||
{
|
{
|
||||||
sort: sorting[0],
|
sort: sorting[0],
|
||||||
page: pagination,
|
page: pagination,
|
||||||
@@ -300,7 +300,7 @@ export const RequestsTable = () => {
|
|||||||
</div>
|
</div>
|
||||||
<Sheet
|
<Sheet
|
||||||
open={!!selectedRow}
|
open={!!selectedRow}
|
||||||
onOpenChange={(open) => setSelectedRow(undefined)}
|
onOpenChange={(_open) => setSelectedRow(undefined)}
|
||||||
>
|
>
|
||||||
<SheetContent className="sm:max-w-[740px] flex flex-col">
|
<SheetContent className="sm:max-w-[740px] flex flex-col">
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
|
|||||||
@@ -22,14 +22,11 @@ import {
|
|||||||
extractServices,
|
extractServices,
|
||||||
} from "@/pages/dashboard/project/[projectId]";
|
} from "@/pages/dashboard/project/[projectId]";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import type { findProjectById } from "@dokploy/server/services/project";
|
|
||||||
import { BookIcon, CircuitBoard, GlobeIcon } from "lucide-react";
|
import { BookIcon, CircuitBoard, GlobeIcon } from "lucide-react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { StatusTooltip } from "../shared/status-tooltip";
|
import { StatusTooltip } from "../shared/status-tooltip";
|
||||||
|
|
||||||
type Project = Awaited<ReturnType<typeof findProjectById>>;
|
|
||||||
|
|
||||||
export const SearchCommand = () => {
|
export const SearchCommand = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
@@ -38,7 +35,7 @@ export const SearchCommand = () => {
|
|||||||
const { data } = api.project.all.useQuery(undefined, {
|
const { data } = api.project.all.useQuery(undefined, {
|
||||||
enabled: !!session,
|
enabled: !!session,
|
||||||
});
|
});
|
||||||
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const down = (e: KeyboardEvent) => {
|
const down = (e: KeyboardEvent) => {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export const calculatePrice = (count: number, isAnnual = false) => {
|
|||||||
return count * 3.5;
|
return count * 3.5;
|
||||||
};
|
};
|
||||||
export const ShowBilling = () => {
|
export const ShowBilling = () => {
|
||||||
const { data: servers } = api.server.all.useQuery(undefined);
|
const { data: servers } = api.server.count.useQuery();
|
||||||
const { data: admin } = api.user.get.useQuery();
|
const { data: admin } = api.user.get.useQuery();
|
||||||
const { data, isLoading } = api.stripe.getProducts.useQuery();
|
const { data, isLoading } = api.stripe.getProducts.useQuery();
|
||||||
const { mutateAsync: createCheckoutSession } =
|
const { mutateAsync: createCheckoutSession } =
|
||||||
@@ -71,7 +71,7 @@ export const ShowBilling = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const maxServers = admin?.user.serversQuantity ?? 1;
|
const maxServers = admin?.user.serversQuantity ?? 1;
|
||||||
const percentage = ((servers?.length ?? 0) / maxServers) * 100;
|
const percentage = ((servers ?? 0) / maxServers) * 100;
|
||||||
const safePercentage = Math.min(percentage, 100);
|
const safePercentage = Math.min(percentage, 100);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -102,13 +102,13 @@ export const ShowBilling = () => {
|
|||||||
<div className="space-y-2 flex flex-col">
|
<div className="space-y-2 flex flex-col">
|
||||||
<h3 className="text-lg font-medium">Servers Plan</h3>
|
<h3 className="text-lg font-medium">Servers Plan</h3>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
You have {servers?.length} server on your plan of{" "}
|
You have {servers} server on your plan of{" "}
|
||||||
{admin?.user.serversQuantity} servers
|
{admin?.user.serversQuantity} servers
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<Progress value={safePercentage} className="max-w-lg" />
|
<Progress value={safePercentage} className="max-w-lg" />
|
||||||
</div>
|
</div>
|
||||||
{admin && admin.user.serversQuantity! <= servers?.length! && (
|
{admin && admin.user.serversQuantity! <= (servers ?? 0) && (
|
||||||
<div className="flex flex-row gap-4 p-2 bg-yellow-50 dark:bg-yellow-950 rounded-lg items-center">
|
<div className="flex flex-row gap-4 p-2 bg-yellow-50 dark:bg-yellow-950 rounded-lg items-center">
|
||||||
<AlertTriangle className="text-yellow-600 dark:text-yellow-400" />
|
<AlertTriangle className="text-yellow-600 dark:text-yellow-400" />
|
||||||
<span className="text-sm text-yellow-600 dark:text-yellow-400">
|
<span className="text-sm text-yellow-600 dark:text-yellow-400">
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ export const ShowNodes = () => {
|
|||||||
const { data, isLoading, refetch } = api.cluster.getNodes.useQuery();
|
const { data, isLoading, refetch } = api.cluster.getNodes.useQuery();
|
||||||
const { data: registry } = api.registry.all.useQuery();
|
const { data: registry } = api.registry.all.useQuery();
|
||||||
|
|
||||||
const { mutateAsync: deleteNode, isLoading: isRemoving } =
|
const { mutateAsync: deleteNode } = api.cluster.removeWorker.useMutation();
|
||||||
api.cluster.removeWorker.useMutation();
|
|
||||||
|
|
||||||
const haveAtLeastOneRegistry = !!(registry && registry?.length > 0);
|
const haveAtLeastOneRegistry = !!(registry && registry?.length > 0);
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export const HandleRegistry = ({ registryId }: Props) => {
|
|||||||
serverId: data.serverId,
|
serverId: data.serverId,
|
||||||
registryId: registryId || "",
|
registryId: registryId || "",
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (_data) => {
|
||||||
await utils.registry.all.invalidate();
|
await utils.registry.all.invalidate();
|
||||||
toast.success(registryId ? "Registry updated" : "Registry added");
|
toast.success(registryId ? "Registry updated" : "Registry added");
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ type Schema = z.infer<typeof Schema>;
|
|||||||
export const AddBitbucketProvider = () => {
|
export const AddBitbucketProvider = () => {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const url = useUrl();
|
const _url = useUrl();
|
||||||
const { mutateAsync, error, isError } = api.bitbucket.create.useMutation();
|
const { mutateAsync, error, isError } = api.bitbucket.create.useMutation();
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const router = useRouter();
|
const _router = useRouter();
|
||||||
const form = useForm<Schema>({
|
const form = useForm<Schema>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
username: "",
|
username: "",
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export const ShowGitProviders = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 rounded-lg ">
|
<div className="flex flex-col gap-4 rounded-lg ">
|
||||||
{data?.map((gitProvider, index) => {
|
{data?.map((gitProvider, _index) => {
|
||||||
const isGithub = gitProvider.providerType === "github";
|
const isGithub = gitProvider.providerType === "github";
|
||||||
const isGitlab = gitProvider.providerType === "gitlab";
|
const isGitlab = gitProvider.providerType === "gitlab";
|
||||||
const isBitbucket =
|
const isBitbucket =
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
|
|||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
const { data: notification, refetch } = api.notification.one.useQuery(
|
const { data: notification } = api.notification.one.useQuery(
|
||||||
{
|
{
|
||||||
notificationId: notificationId || "",
|
notificationId: notificationId || "",
|
||||||
},
|
},
|
||||||
@@ -1038,7 +1038,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
toast.success("Connection Success");
|
toast.success("Connection Success");
|
||||||
} catch (err) {
|
} catch (_err) {
|
||||||
toast.error("Error testing the provider");
|
toast.error("Error testing the provider");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const ShowNotifications = () => {
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col gap-4 min-h-[25vh]">
|
<div className="flex flex-col gap-4 min-h-[25vh]">
|
||||||
<div className="flex flex-col gap-4 rounded-lg ">
|
<div className="flex flex-col gap-4 rounded-lg ">
|
||||||
{data?.map((notification, index) => (
|
{data?.map((notification, _index) => (
|
||||||
<div
|
<div
|
||||||
key={notification.notificationId}
|
key={notification.notificationId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export const Disable2FA = () => {
|
|||||||
toast.success("2FA disabled successfully");
|
toast.success("2FA disabled successfully");
|
||||||
utils.auth.get.invalidate();
|
utils.auth.get.invalidate();
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
form.setError("password", {
|
form.setError("password", {
|
||||||
message: "Connection error. Please try again.",
|
message: "Connection error. Please try again.",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,20 +47,8 @@ const PinSchema = z.object({
|
|||||||
type PasswordForm = z.infer<typeof PasswordSchema>;
|
type PasswordForm = z.infer<typeof PasswordSchema>;
|
||||||
type PinForm = z.infer<typeof PinSchema>;
|
type PinForm = z.infer<typeof PinSchema>;
|
||||||
|
|
||||||
type TwoFactorEnableResponse = {
|
|
||||||
totpURI: string;
|
|
||||||
backupCodes: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type TwoFactorSetupData = {
|
|
||||||
qrCodeUrl: string;
|
|
||||||
secret: string;
|
|
||||||
totpURI: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Enable2FA = () => {
|
export const Enable2FA = () => {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { data: session } = authClient.useSession();
|
|
||||||
const [data, setData] = useState<TwoFactorSetupData | null>(null);
|
const [data, setData] = useState<TwoFactorSetupData | null>(null);
|
||||||
const [backupCodes, setBackupCodes] = useState<string[]>([]);
|
const [backupCodes, setBackupCodes] = useState<string[]>([]);
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
|
|||||||
@@ -54,9 +54,7 @@ const randomImages = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const ProfileForm = () => {
|
export const ProfileForm = () => {
|
||||||
const utils = api.useUtils();
|
const _utils = api.useUtils();
|
||||||
const { mutateAsync: disable2FA, isLoading: isDisabling } =
|
|
||||||
api.auth.disable2FA.useMutation();
|
|
||||||
const { data, refetch, isLoading } = api.user.get.useQuery();
|
const { data, refetch, isLoading } = api.user.get.useQuery();
|
||||||
const {
|
const {
|
||||||
mutateAsync,
|
mutateAsync,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
|
|||||||
isLoading: cleanDockerBuilderIsLoading,
|
isLoading: cleanDockerBuilderIsLoading,
|
||||||
} = api.settings.cleanDockerBuilder.useMutation();
|
} = api.settings.cleanDockerBuilder.useMutation();
|
||||||
|
|
||||||
const { mutateAsync: cleanMonitoring, isLoading: cleanMonitoringIsLoading } =
|
const { mutateAsync: cleanMonitoring } =
|
||||||
api.settings.cleanMonitoring.useMutation();
|
api.settings.cleanMonitoring.useMutation();
|
||||||
const {
|
const {
|
||||||
mutateAsync: cleanUnusedImages,
|
mutateAsync: cleanUnusedImages,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export const ToggleDockerCleanup = ({ serverId }: Props) => {
|
|||||||
await refetch();
|
await refetch();
|
||||||
}
|
}
|
||||||
toast.success("Docker Cleanup updated");
|
toast.success("Docker Cleanup updated");
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error("Docker Cleanup Error");
|
toast.error("Docker Cleanup Error");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export const EditScript = ({ serverId }: Props) => {
|
|||||||
command: formData.command || "",
|
command: formData.command || "",
|
||||||
serverId,
|
serverId,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((_data) => {
|
||||||
toast.success("Script modified successfully");
|
toast.success("Script modified successfully");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function GPUSupport({ serverId }: GPUSupportProps) {
|
|||||||
try {
|
try {
|
||||||
await utils.settings.checkGPUStatus.invalidate({ serverId });
|
await utils.settings.checkGPUStatus.invalidate({ serverId });
|
||||||
await refetch();
|
await refetch();
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error("Failed to refresh GPU status");
|
toast.error("Failed to refresh GPU status");
|
||||||
} finally {
|
} finally {
|
||||||
setIsRefreshing(false);
|
setIsRefreshing(false);
|
||||||
@@ -74,7 +74,7 @@ export function GPUSupport({ serverId }: GPUSupportProps) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await setupGPU.mutateAsync({ serverId });
|
await setupGPU.mutateAsync({ serverId });
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
// Error handling is done in mutation's onError
|
// Error handling is done in mutation's onError
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export const HandleServers = ({ serverId }: Props) => {
|
|||||||
sshKeyId: data.sshKeyId || "",
|
sshKeyId: data.sshKeyId || "",
|
||||||
serverId: serverId || "",
|
serverId: serverId || "",
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (_data) => {
|
||||||
await utils.server.all.invalidate();
|
await utils.server.all.invalidate();
|
||||||
refetchServer();
|
refetchServer();
|
||||||
toast.success(serverId ? "Server Updated" : "Server Created");
|
toast.success(serverId ? "Server Updated" : "Server Created");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const SecurityAudit = ({ serverId }: Props) => {
|
|||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const utils = api.useUtils();
|
const _utils = api.useUtils();
|
||||||
return (
|
return (
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const Schema = z.object({
|
|||||||
type Schema = z.infer<typeof Schema>;
|
type Schema = z.infer<typeof Schema>;
|
||||||
|
|
||||||
export const SetupMonitoring = ({ serverId }: Props) => {
|
export const SetupMonitoring = ({ serverId }: Props) => {
|
||||||
const { data, isLoading } = serverId
|
const { data } = serverId
|
||||||
? api.server.one.useQuery(
|
? api.server.one.useQuery(
|
||||||
{
|
{
|
||||||
serverId: serverId || "",
|
serverId: serverId || "",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const ValidateServer = ({ serverId }: Props) => {
|
|||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const utils = api.useUtils();
|
const _utils = api.useUtils();
|
||||||
return (
|
return (
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
|
|||||||
@@ -52,10 +52,10 @@ interface Props {
|
|||||||
|
|
||||||
export const CreateServer = ({ stepper }: Props) => {
|
export const CreateServer = ({ stepper }: Props) => {
|
||||||
const { data: sshKeys } = api.sshKey.all.useQuery();
|
const { data: sshKeys } = api.sshKey.all.useQuery();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, _setIsOpen] = useState(false);
|
||||||
const { data: canCreateMoreServers, refetch } =
|
const { data: canCreateMoreServers, refetch } =
|
||||||
api.stripe.canCreateMoreServers.useQuery();
|
api.stripe.canCreateMoreServers.useQuery();
|
||||||
const { mutateAsync, error, isError } = api.server.create.useMutation();
|
const { mutateAsync } = api.server.create.useMutation();
|
||||||
const cloudSSHKey = sshKeys?.find(
|
const cloudSSHKey = sshKeys?.find(
|
||||||
(sshKey) => sshKey.name === "dokploy-cloud-ssh-key",
|
(sshKey) => sshKey.name === "dokploy-cloud-ssh-key",
|
||||||
);
|
);
|
||||||
@@ -96,7 +96,7 @@ export const CreateServer = ({ stepper }: Props) => {
|
|||||||
username: data.username || "root",
|
username: data.username || "root",
|
||||||
sshKeyId: data.sshKeyId || "",
|
sshKeyId: data.sshKeyId || "",
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (_data) => {
|
||||||
toast.success("Server Created");
|
toast.success("Server Created");
|
||||||
stepper.next();
|
stepper.next();
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -37,15 +37,6 @@ export const Verify = () => {
|
|||||||
);
|
);
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
|
|
||||||
const { data: server } = api.server.one.useQuery(
|
|
||||||
{
|
|
||||||
serverId,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enabled: !!serverId,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ export const ShowInvitations = () => {
|
|||||||
{invitation.status === "pending" && (
|
{invitation.status === "pending" && (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="w-full cursor-pointer"
|
className="w-full cursor-pointer"
|
||||||
onSelect={(e) => {
|
onSelect={(_e) => {
|
||||||
copy(
|
copy(
|
||||||
`${origin}/invitation?token=${invitation.id}`,
|
`${origin}/invitation?token=${invitation.id}`,
|
||||||
);
|
);
|
||||||
@@ -159,7 +159,7 @@ export const ShowInvitations = () => {
|
|||||||
{invitation.status === "pending" && (
|
{invitation.status === "pending" && (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="w-full cursor-pointer"
|
className="w-full cursor-pointer"
|
||||||
onSelect={async (e) => {
|
onSelect={async (_e) => {
|
||||||
const result =
|
const result =
|
||||||
await authClient.organization.cancelInvitation(
|
await authClient.organization.cancelInvitation(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import { AddUserPermissions } from "./add-permissions";
|
|||||||
export const ShowUsers = () => {
|
export const ShowUsers = () => {
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
const { data, isLoading, refetch } = api.user.all.useQuery();
|
const { data, isLoading, refetch } = api.user.all.useQuery();
|
||||||
const { mutateAsync, isLoading: isRemoving } = api.user.remove.useMutation();
|
const { mutateAsync } = api.user.remove.useMutation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import { ShowTraefikActions } from "./servers/actions/show-traefik-actions";
|
|||||||
import { ToggleDockerCleanup } from "./servers/actions/toggle-docker-cleanup";
|
import { ToggleDockerCleanup } from "./servers/actions/toggle-docker-cleanup";
|
||||||
import { UpdateServer } from "./web-server/update-server";
|
import { UpdateServer } from "./web-server/update-server";
|
||||||
|
|
||||||
interface Props {
|
export const WebServer = () => {
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
export const WebServer = ({ className }: Props) => {
|
|
||||||
const { t } = useTranslation("settings");
|
const { t } = useTranslation("settings");
|
||||||
const { data } = api.user.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
|
|||||||
});
|
});
|
||||||
toast.success(t("settings.server.webServer.traefik.portsUpdated"));
|
toast.success(t("settings.server.webServer.traefik.portsUpdated"));
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error(t("settings.server.webServer.traefik.portsUpdateError"));
|
toast.error(t("settings.server.webServer.traefik.portsUpdateError"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ interface Props {
|
|||||||
serverId?: string;
|
serverId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UpdateServerIp = ({ children, serverId }: Props) => {
|
export const UpdateServerIp = ({ children }: Props) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const { data } = api.user.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ export const columns: ColumnDef<ApplicationList>[] = [
|
|||||||
{
|
{
|
||||||
accessorKey: "Logs",
|
accessorKey: "Logs",
|
||||||
accessorFn: (row) => row.Error,
|
accessorFn: (row) => row.Error,
|
||||||
header: ({ column }) => {
|
header: () => {
|
||||||
return <span>Logs</span>;
|
return <span>Logs</span>;
|
||||||
},
|
},
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function DataTable<TData, TValue>({
|
|||||||
const [columnVisibility, setColumnVisibility] =
|
const [columnVisibility, setColumnVisibility] =
|
||||||
React.useState<VisibilityState>({});
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
const [pagination, setPagination] = React.useState({
|
const [_pagination, _setPagination] = React.useState({
|
||||||
pageIndex: 0, //initial page index
|
pageIndex: 0, //initial page index
|
||||||
pageSize: 8, //default page size
|
pageSize: 8, //default page size
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ShowNodeConfig = ({ nodeId, serverId }: Props) => {
|
export const ShowNodeConfig = ({ nodeId, serverId }: Props) => {
|
||||||
const { data, isLoading } = api.swarm.getNodeInfo.useQuery({
|
const { data } = api.swarm.getNodeInfo.useQuery({
|
||||||
nodeId,
|
nodeId,
|
||||||
serverId,
|
serverId,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ const MENU: Menu = {
|
|||||||
url: "/dashboard/monitoring",
|
url: "/dashboard/monitoring",
|
||||||
icon: BarChartHorizontalBigIcon,
|
icon: BarChartHorizontalBigIcon,
|
||||||
// Only enabled in non-cloud environments
|
// Only enabled in non-cloud environments
|
||||||
isEnabled: ({ auth, isCloud }) => !isCloud,
|
isEnabled: ({ isCloud }) => !isCloud,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
isSingle: true,
|
isSingle: true,
|
||||||
@@ -277,7 +277,7 @@ const MENU: Menu = {
|
|||||||
url: "/dashboard/settings/servers",
|
url: "/dashboard/settings/servers",
|
||||||
icon: Server,
|
icon: Server,
|
||||||
// Only enabled for admins
|
// Only enabled for admins
|
||||||
isEnabled: ({ auth, isCloud }) => !!(auth?.role === "owner"),
|
isEnabled: ({ auth }) => !!(auth?.role === "owner"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
isSingle: true,
|
isSingle: true,
|
||||||
@@ -490,8 +490,9 @@ function SidebarLogo() {
|
|||||||
const { state } = useSidebar();
|
const { state } = useSidebar();
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
const { data: user } = api.user.get.useQuery();
|
const { data: user } = api.user.get.useQuery();
|
||||||
const { data: dokployVersion } = api.settings.getDokployVersion.useQuery();
|
// const { data: dokployVersion } = api.settings.getDokployVersion.useQuery();
|
||||||
const { data: session } = authClient.useSession();
|
const { data: session } = authClient.useSession();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: organizations,
|
data: organizations,
|
||||||
refetch,
|
refetch,
|
||||||
@@ -501,12 +502,12 @@ function SidebarLogo() {
|
|||||||
api.organization.delete.useMutation();
|
api.organization.delete.useMutation();
|
||||||
const { isMobile } = useSidebar();
|
const { isMobile } = useSidebar();
|
||||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||||
const utils = api.useUtils();
|
const _utils = api.useUtils();
|
||||||
|
|
||||||
const { data: invitations, refetch: refetchInvitations } =
|
const { data: invitations, refetch: refetchInvitations } =
|
||||||
api.user.getInvitations.useQuery();
|
api.user.getInvitations.useQuery();
|
||||||
|
|
||||||
const [activeTeam, setActiveTeam] = useState<
|
const [_activeTeam, setActiveTeam] = useState<
|
||||||
typeof activeOrganization | null
|
typeof activeOrganization | null
|
||||||
>(null);
|
>(null);
|
||||||
|
|
||||||
@@ -543,7 +544,7 @@ function SidebarLogo() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-start">
|
<div className="flex flex-col items-start">
|
||||||
<p className="text-sm font-medium leading-none">
|
<p className="text-sm font-medium leading-none">
|
||||||
{activeOrganization?.name}
|
{activeOrganization?.name ?? "Select Organization"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -551,7 +552,7 @@ function SidebarLogo() {
|
|||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
className="w-[--radix-dropdown-menu-trigger-width] min-w-64 rounded-lg"
|
className=" rounded-lg"
|
||||||
align="start"
|
align="start"
|
||||||
side={isMobile ? "bottom" : "right"}
|
side={isMobile ? "bottom" : "right"}
|
||||||
sideOffset={4}
|
sideOffset={4}
|
||||||
@@ -570,6 +571,7 @@ function SidebarLogo() {
|
|||||||
}}
|
}}
|
||||||
className="w-full gap-2 p-2"
|
className="w-full gap-2 p-2"
|
||||||
>
|
>
|
||||||
|
<div className="flex flex-col gap-4">{org.name}</div>
|
||||||
<div className="flex size-6 items-center justify-center rounded-sm border">
|
<div className="flex size-6 items-center justify-center rounded-sm border">
|
||||||
<Logo
|
<Logo
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -578,9 +580,8 @@ function SidebarLogo() {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{org.name}
|
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
{(org.ownerId === session?.user?.id || isCloud) && (
|
{org.ownerId === session?.user?.id && (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<AddOrganization organizationId={org.id} />
|
<AddOrganization organizationId={org.id} />
|
||||||
<DialogAction
|
<DialogAction
|
||||||
@@ -618,7 +619,7 @@ function SidebarLogo() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{!isCloud && user?.role === "owner" && (
|
{(user?.role === "owner" || isCloud) && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<AddOrganization />
|
<AddOrganization />
|
||||||
@@ -721,11 +722,11 @@ export default function Page({ children }: Props) {
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const currentPath = router.pathname;
|
const _currentPath = router.pathname;
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
|
|
||||||
const includesProjects = pathname?.includes("/dashboard/project");
|
const includesProjects = pathname?.includes("/dashboard/project");
|
||||||
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
home: filteredHome,
|
home: filteredHome,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const UpdateServerButton = () => {
|
|||||||
latestVersion: null,
|
latestVersion: null,
|
||||||
updateAvailable: false,
|
updateAvailable: false,
|
||||||
});
|
});
|
||||||
const router = useRouter();
|
const _router = useRouter();
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
const { mutateAsync: getUpdateData } =
|
const { mutateAsync: getUpdateData } =
|
||||||
api.settings.getUpdateData.useMutation();
|
api.settings.getUpdateData.useMutation();
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { useRouter } from "next/router";
|
|||||||
import { ModeToggle } from "../ui/modeToggle";
|
import { ModeToggle } from "../ui/modeToggle";
|
||||||
import { SidebarMenuButton } from "../ui/sidebar";
|
import { SidebarMenuButton } from "../ui/sidebar";
|
||||||
|
|
||||||
const AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 7;
|
const _AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 7;
|
||||||
|
|
||||||
export const UserNav = () => {
|
export const UserNav = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const BreadcrumbSidebar = ({ list }: Props) => {
|
|||||||
<Separator orientation="vertical" className="mr-2 h-4" />
|
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||||
<Breadcrumb>
|
<Breadcrumb>
|
||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
{list.map((item, index) => (
|
{list.map((item, _index) => (
|
||||||
<Fragment key={item.name}>
|
<Fragment key={item.name}>
|
||||||
<BreadcrumbItem className="block">
|
<BreadcrumbItem className="block">
|
||||||
<BreadcrumbLink href={item.href} asChild={!!item.href}>
|
<BreadcrumbLink href={item.href} asChild={!!item.href}>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export const DrawerLogs = ({ isOpen, onClose, filteredLogs }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Sheet
|
<Sheet
|
||||||
open={!!isOpen}
|
open={!!isOpen}
|
||||||
onOpenChange={(open) => {
|
onOpenChange={(_open) => {
|
||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const Tree = React.forwardRef<HTMLDivElement, TreeProps>(
|
|||||||
return ids;
|
return ids;
|
||||||
}, [data, initialSlelectedItemId]);
|
}, [data, initialSlelectedItemId]);
|
||||||
|
|
||||||
const { ref: refRoot, width, height } = useResizeObserver();
|
const { ref: refRoot } = useResizeObserver();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={refRoot} className={cn("overflow-y-auto", className)}>
|
<div ref={refRoot} className={cn("overflow-y-auto", className)}>
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ await db
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
for (const project of projects) {
|
for (const project of projects) {
|
||||||
const user = await db.update(schema.projects).set({
|
const _user = await db.update(schema.projects).set({
|
||||||
organizationId: project.user.organizations[0]?.id || "",
|
organizationId: project.user.organizations[0]?.id || "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export default function Custom404({ statusCode, error }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
Error.getInitialProps = ({ res, err, ...rest }: NextPageContext) => {
|
Error.getInitialProps = ({ res, err }: NextPageContext) => {
|
||||||
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
|
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
|
||||||
return { statusCode, error: err };
|
return { statusCode, error: err };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
export default async function handler(
|
export default async function handler(
|
||||||
req: NextApiRequest,
|
_req: NextApiRequest,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
) {
|
) {
|
||||||
return res.status(200).json({ ok: true });
|
return res.status(200).json({ ok: true });
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ export default async function handler(
|
|||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
) {
|
) {
|
||||||
const { code, state, installation_id, setup_action }: Query =
|
const { code, state, installation_id }: Query = req.query as Query;
|
||||||
req.query as Query;
|
|
||||||
|
|
||||||
if (!code) {
|
if (!code) {
|
||||||
return res.status(400).json({ error: "Missing code parameter" });
|
return res.status(400).json({ error: "Missing code parameter" });
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { buffer } from "node:stream/consumers";
|
import { buffer } from "node:stream/consumers";
|
||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
import { server, users_temp } from "@/server/db/schema";
|
import { organization, server, users_temp } from "@/server/db/schema";
|
||||||
import { findUserById } from "@dokploy/server";
|
import { findUserById, type Server } from "@dokploy/server";
|
||||||
import { asc, eq } from "drizzle-orm";
|
import { asc, eq } from "drizzle-orm";
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import Stripe from "stripe";
|
import Stripe from "stripe";
|
||||||
@@ -172,11 +172,11 @@ export default async function handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.update(admins)
|
.update(users_temp)
|
||||||
.set({
|
.set({
|
||||||
serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
|
serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
|
||||||
})
|
})
|
||||||
.where(eq(admins.stripeCustomerId, suscription.customer as string));
|
.where(eq(users_temp.stripeCustomerId, suscription.customer as string));
|
||||||
|
|
||||||
const admin = await findUserByStripeCustomerId(
|
const admin = await findUserByStripeCustomerId(
|
||||||
suscription.customer as string,
|
suscription.customer as string,
|
||||||
@@ -205,11 +205,13 @@ export default async function handler(
|
|||||||
return res.status(400).send("Webhook Error: Admin not found");
|
return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
}
|
||||||
await db
|
await db
|
||||||
.update(admins)
|
.update(users_temp)
|
||||||
.set({
|
.set({
|
||||||
serversQuantity: 0,
|
serversQuantity: 0,
|
||||||
})
|
})
|
||||||
.where(eq(admins.stripeCustomerId, newInvoice.customer as string));
|
.where(
|
||||||
|
eq(users_temp.stripeCustomerId, newInvoice.customer as string),
|
||||||
|
);
|
||||||
|
|
||||||
await disableServers(admin.id);
|
await disableServers(admin.id);
|
||||||
}
|
}
|
||||||
@@ -245,12 +247,18 @@ export default async function handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const disableServers = async (userId: string) => {
|
const disableServers = async (userId: string) => {
|
||||||
await db
|
const organizations = await db.query.organization.findMany({
|
||||||
.update(server)
|
where: eq(organization.ownerId, userId),
|
||||||
.set({
|
});
|
||||||
serverStatus: "inactive",
|
|
||||||
})
|
for (const org of organizations) {
|
||||||
.where(eq(server.userId, userId));
|
await db
|
||||||
|
.update(server)
|
||||||
|
.set({
|
||||||
|
serverStatus: "inactive",
|
||||||
|
})
|
||||||
|
.where(eq(server.organizationId, org.id));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
|
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
|
||||||
@@ -275,11 +283,19 @@ const deactivateServer = async (serverId: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const findServersByUserIdSorted = async (userId: string) => {
|
export const findServersByUserIdSorted = async (userId: string) => {
|
||||||
const servers = await db.query.server.findMany({
|
const organizations = await db.query.organization.findMany({
|
||||||
where: eq(server.userId, userId),
|
where: eq(organization.ownerId, userId),
|
||||||
orderBy: asc(server.createdAt),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const servers: Server[] = [];
|
||||||
|
for (const org of organizations) {
|
||||||
|
const serversByOrg = await db.query.server.findMany({
|
||||||
|
where: eq(server.organizationId, org.id),
|
||||||
|
orderBy: asc(server.createdAt),
|
||||||
|
});
|
||||||
|
servers.push(...serversByOrg);
|
||||||
|
}
|
||||||
|
|
||||||
return servers;
|
return servers;
|
||||||
};
|
};
|
||||||
export const updateServersBasedOnQuantity = async (
|
export const updateServersBasedOnQuantity = async (
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export async function getServerSideProps(
|
|||||||
trpcState: helpers.dehydrate(),
|
trpcState: helpers.dehydrate(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ const BASE_URL = "http://localhost:3001/metrics";
|
|||||||
const DEFAULT_TOKEN = "metrics";
|
const DEFAULT_TOKEN = "metrics";
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const [toggleMonitoring, _setToggleMonitoring] = useLocalStorage(
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useLocalStorage(
|
|
||||||
"monitoring-enabled",
|
"monitoring-enabled",
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ const Project = (
|
|||||||
try {
|
try {
|
||||||
await composeActions.start.mutateAsync({ composeId: serviceId });
|
await composeActions.start.mutateAsync({ composeId: serviceId });
|
||||||
success++;
|
success++;
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error(`Error starting service ${serviceId}`);
|
toast.error(`Error starting service ${serviceId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,7 +281,7 @@ const Project = (
|
|||||||
try {
|
try {
|
||||||
await composeActions.stop.mutateAsync({ composeId: serviceId });
|
await composeActions.stop.mutateAsync({ composeId: serviceId });
|
||||||
success++;
|
success++;
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error(`Error stopping service ${serviceId}`);
|
toast.error(`Error stopping service ${serviceId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -685,7 +685,7 @@ export async function getServerSideProps(
|
|||||||
projectId: params?.projectId,
|
projectId: params?.projectId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ type TabState =
|
|||||||
const Service = (
|
const Service = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
const { applicationId, activeTab } = props;
|
const { applicationId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
@@ -86,7 +86,6 @@ const Service = (
|
|||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pb-10">
|
<div className="pb-10">
|
||||||
@@ -399,7 +398,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ type TabState =
|
|||||||
const Service = (
|
const Service = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
const { composeId, activeTab } = props;
|
const { composeId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
@@ -79,7 +79,6 @@ const Service = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -393,7 +392,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
|
|||||||
const Mariadb = (
|
const Mariadb = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
|
|
||||||
const { mariadbId, activeTab } = props;
|
const { mariadbId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -60,7 +60,6 @@ const Mariadb = (
|
|||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.mariadb.one.useQuery({ mariadbId });
|
const { data } = api.mariadb.one.useQuery({ mariadbId });
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
@@ -342,7 +341,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
|
|||||||
const Mongo = (
|
const Mongo = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
const { mongoId, activeTab } = props;
|
const { mongoId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
@@ -60,7 +60,6 @@ const Mongo = (
|
|||||||
const { data } = api.mongo.one.useQuery({ mongoId });
|
const { data } = api.mongo.one.useQuery({ mongoId });
|
||||||
|
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
@@ -343,7 +342,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -52,14 +52,13 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
|
|||||||
const MySql = (
|
const MySql = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
const { mysqlId, activeTab } = props;
|
const { mysqlId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.mysql.one.useQuery({ mysqlId });
|
const { data } = api.mysql.one.useQuery({ mysqlId });
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
@@ -348,7 +347,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
|
|||||||
const Postgresql = (
|
const Postgresql = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
const { postgresId, activeTab } = props;
|
const { postgresId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
@@ -60,7 +60,6 @@ const Postgresql = (
|
|||||||
const { data } = api.postgres.one.useQuery({ postgresId });
|
const { data } = api.postgres.one.useQuery({ postgresId });
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
|
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -345,7 +344,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ type TabState = "projects" | "monitoring" | "settings" | "advanced";
|
|||||||
const Redis = (
|
const Redis = (
|
||||||
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
props: InferGetServerSidePropsType<typeof getServerSideProps>,
|
||||||
) => {
|
) => {
|
||||||
const [toggleMonitoring, setToggleMonitoring] = useState(false);
|
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
|
||||||
const { redisId, activeTab } = props;
|
const { redisId, activeTab } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
@@ -59,7 +59,6 @@ const Redis = (
|
|||||||
const { data } = api.redis.one.useQuery({ redisId });
|
const { data } = api.redis.one.useQuery({ redisId });
|
||||||
|
|
||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
@@ -335,7 +334,7 @@ export async function getServerSideProps(
|
|||||||
activeTab: (activeTab || "general") as TabState,
|
activeTab: (activeTab || "general") as TabState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export async function getServerSideProps(
|
|||||||
trpcState: helpers.dehydrate(),
|
trpcState: helpers.dehydrate(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export async function getServerSideProps(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const { req, res, resolvedUrl } = ctx;
|
const { req, res } = ctx;
|
||||||
const helpers = createServerSideHelpers({
|
const helpers = createServerSideHelpers({
|
||||||
router: appRouter,
|
router: appRouter,
|
||||||
ctx: {
|
ctx: {
|
||||||
@@ -69,7 +69,7 @@ export async function getServerSideProps(
|
|||||||
trpcState: helpers.dehydrate(),
|
trpcState: helpers.dehydrate(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export async function getServerSideProps(
|
|||||||
trpcState: helpers.dehydrate(),
|
trpcState: helpers.dehydrate(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export async function getServerSideProps(
|
|||||||
trpcState: helpers.dehydrate(),
|
trpcState: helpers.dehydrate(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,18 +43,11 @@ const LoginSchema = z.object({
|
|||||||
password: z.string().min(8),
|
password: z.string().min(8),
|
||||||
});
|
});
|
||||||
|
|
||||||
const TwoFactorSchema = z.object({
|
const _TwoFactorSchema = z.object({
|
||||||
code: z.string().min(6),
|
code: z.string().min(6),
|
||||||
});
|
});
|
||||||
|
|
||||||
const BackupCodeSchema = z.object({
|
|
||||||
code: z.string().min(8, {
|
|
||||||
message: "Backup code must be at least 8 characters",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
type LoginForm = z.infer<typeof LoginSchema>;
|
type LoginForm = z.infer<typeof LoginSchema>;
|
||||||
type BackupCodeForm = z.infer<typeof BackupCodeSchema>;
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
IS_CLOUD: boolean;
|
IS_CLOUD: boolean;
|
||||||
@@ -101,7 +94,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
|
|
||||||
toast.success("Logged in successfully");
|
toast.success("Logged in successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/projects");
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error("An error occurred while logging in");
|
toast.error("An error occurred while logging in");
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoginLoading(false);
|
setIsLoginLoading(false);
|
||||||
@@ -117,7 +110,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
|
|
||||||
setIsTwoFactorLoading(true);
|
setIsTwoFactorLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, error } = await authClient.twoFactor.verifyTotp({
|
const { error } = await authClient.twoFactor.verifyTotp({
|
||||||
code: twoFactorCode.replace(/\s/g, ""),
|
code: twoFactorCode.replace(/\s/g, ""),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -129,7 +122,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
|
|
||||||
toast.success("Logged in successfully");
|
toast.success("Logged in successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/projects");
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error("An error occurred while verifying 2FA code");
|
toast.error("An error occurred while verifying 2FA code");
|
||||||
} finally {
|
} finally {
|
||||||
setIsTwoFactorLoading(false);
|
setIsTwoFactorLoading(false);
|
||||||
@@ -145,7 +138,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
|
|
||||||
setIsBackupCodeLoading(true);
|
setIsBackupCodeLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, error } = await authClient.twoFactor.verifyBackupCode({
|
const { error } = await authClient.twoFactor.verifyBackupCode({
|
||||||
code: backupCode.trim(),
|
code: backupCode.trim(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -159,7 +152,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
|
|
||||||
toast.success("Logged in successfully");
|
toast.success("Logged in successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/projects");
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error("An error occurred while verifying backup code");
|
toast.error("An error occurred while verifying backup code");
|
||||||
} finally {
|
} finally {
|
||||||
setIsBackupCodeLoading(false);
|
setIsBackupCodeLoading(false);
|
||||||
@@ -396,7 +389,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (_error) {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import { authClient } from "@/lib/auth-client";
|
|||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { IS_CLOUD, getUserByToken } from "@dokploy/server";
|
import { IS_CLOUD, getUserByToken } from "@dokploy/server";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { AlertTriangle } from "lucide-react";
|
|
||||||
import type { GetServerSidePropsContext } from "next";
|
import type { GetServerSidePropsContext } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
@@ -90,9 +89,6 @@ const Invitation = ({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const { mutateAsync, error, isError, isSuccess } =
|
|
||||||
api.auth.createUser.useMutation();
|
|
||||||
|
|
||||||
const form = useForm<Register>({
|
const form = useForm<Register>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -115,7 +111,7 @@ const Invitation = ({
|
|||||||
|
|
||||||
const onSubmit = async (values: Register) => {
|
const onSubmit = async (values: Register) => {
|
||||||
try {
|
try {
|
||||||
const { data, error } = await authClient.signUp.email({
|
const { error } = await authClient.signUp.email({
|
||||||
email: values.email,
|
email: values.email,
|
||||||
password: values.password,
|
password: values.password,
|
||||||
name: values.name,
|
name: values.name,
|
||||||
@@ -131,13 +127,13 @@ const Invitation = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await authClient.organization.acceptInvitation({
|
const _result = await authClient.organization.acceptInvitation({
|
||||||
invitationId: token,
|
invitationId: token,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success("Account created successfully");
|
toast.success("Account created successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/projects");
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
toast.error("An error occurred while creating your account");
|
toast.error("An error occurred while creating your account");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -180,14 +176,14 @@ const Invitation = ({
|
|||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="p-3" />
|
<div className="p-3" />
|
||||||
|
|
||||||
{isError && (
|
{/* {isError && (
|
||||||
<div className="mx-5 my-2 flex flex-row items-center gap-2 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
<div className="mx-5 my-2 flex flex-row items-center gap-2 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
||||||
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
||||||
<span className="text-sm text-red-600 dark:text-red-400">
|
<span className="text-sm text-red-600 dark:text-red-400">
|
||||||
{error?.message}
|
{error?.message}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
@@ -313,7 +309,6 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) {
|
|||||||
const { query } = ctx;
|
const { query } = ctx;
|
||||||
|
|
||||||
const token = query.token;
|
const token = query.token;
|
||||||
console.log("query", query);
|
|
||||||
|
|
||||||
if (typeof token !== "string") {
|
if (typeof token !== "string") {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { authClient } from "@/lib/auth-client";
|
import { authClient } from "@/lib/auth-client";
|
||||||
import { api } from "@/utils/api";
|
|
||||||
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
|
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { AlertTriangle } from "lucide-react";
|
import { AlertTriangle } from "lucide-react";
|
||||||
import type { GetServerSidePropsContext } from "next";
|
import type { GetServerSidePropsContext } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { type ReactElement, useEffect } from "react";
|
import { type ReactElement, useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const registerSchema = z
|
const registerSchema = z
|
||||||
@@ -72,15 +72,16 @@ interface Props {
|
|||||||
|
|
||||||
const Register = ({ isCloud }: Props) => {
|
const Register = ({ isCloud }: Props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync, error, isError, data } =
|
const [isError, setIsError] = useState(false);
|
||||||
api.auth.createAdmin.useMutation();
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
|
||||||
const form = useForm<Register>({
|
const form = useForm<Register>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: "Mauricio Siu",
|
name: "Mauricio Siu",
|
||||||
email: "user5@yopmail.com",
|
email: "user5@yopmail.com",
|
||||||
password: "Password1234",
|
password: "Password123",
|
||||||
confirmPassword: "Password1234",
|
confirmPassword: "Password123",
|
||||||
},
|
},
|
||||||
resolver: zodResolver(registerSchema),
|
resolver: zodResolver(registerSchema),
|
||||||
});
|
});
|
||||||
@@ -96,27 +97,19 @@ const Register = ({ isCloud }: Props) => {
|
|||||||
name: values.name,
|
name: values.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
// const { data, error } = await authClient.admin.createUser({
|
if (error) {
|
||||||
// name: values.name,
|
setIsError(true);
|
||||||
// email: values.email,
|
setError(error.message || "An error occurred");
|
||||||
// password: values.password,
|
} else {
|
||||||
// role: "superAdmin",
|
toast.success("User registered successfuly", {
|
||||||
// });
|
duration: 2000,
|
||||||
|
});
|
||||||
// consol/e.log(data, error);
|
if (!isCloud) {
|
||||||
// await mutateAsync({
|
router.push("/");
|
||||||
// email: values.email.toLowerCase(),
|
} else {
|
||||||
// password: values.password,
|
setData(data);
|
||||||
// })
|
}
|
||||||
// .then(() => {
|
}
|
||||||
// toast.success("User registered successfuly", {
|
|
||||||
// duration: 2000,
|
|
||||||
// });
|
|
||||||
// if (!isCloud) {
|
|
||||||
// router.push("/");
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .catch((e) => e);
|
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
@@ -138,15 +131,15 @@ const Register = ({ isCloud }: Props) => {
|
|||||||
</CardDescription>
|
</CardDescription>
|
||||||
<div className="mx-auto w-full max-w-lg bg-transparent">
|
<div className="mx-auto w-full max-w-lg bg-transparent">
|
||||||
{isError && (
|
{isError && (
|
||||||
<div className="mx-5 my-2 flex flex-row items-center gap-2 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
<div className=" my-2 flex flex-row items-center gap-2 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
||||||
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
||||||
<span className="text-sm text-red-600 dark:text-red-400">
|
<span className="text-sm text-red-600 dark:text-red-400">
|
||||||
{error?.message}
|
{error}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{data?.type === "cloud" && (
|
{isCloud && data && (
|
||||||
<AlertBlock type="success" className="mx-4 my-2">
|
<AlertBlock type="success" className="my-2">
|
||||||
<span>
|
<span>
|
||||||
Registered successfully, please check your inbox or spam
|
Registered successfully, please check your inbox or spam
|
||||||
folder to confirm your account.
|
folder to confirm your account.
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export default function Home({ token }: Props) {
|
|||||||
resetPasswordToken: token,
|
resetPasswordToken: token,
|
||||||
password: values.password,
|
password: values.password,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((_data) => {
|
||||||
toast.success("Password reset successfully", {
|
toast.success("Password reset successfully", {
|
||||||
duration: 2000,
|
duration: 2000,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ type AuthResponse = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [temp, setTemp] = useState<AuthResponse>({
|
const [temp, _setTemp] = useState<AuthResponse>({
|
||||||
is2FAEnabled: false,
|
is2FAEnabled: false,
|
||||||
authId: "",
|
authId: "",
|
||||||
});
|
});
|
||||||
const { mutateAsync, isLoading, isError, error } =
|
const { mutateAsync, isLoading, isError, error } =
|
||||||
api.auth.sendResetPasswordEmail.useMutation();
|
api.auth.sendResetPasswordEmail.useMutation();
|
||||||
const router = useRouter();
|
const _router = useRouter();
|
||||||
const form = useForm<Login>({
|
const form = useForm<Login>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
email: "",
|
email: "",
|
||||||
@@ -65,7 +65,7 @@ export default function Home() {
|
|||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
email: values.email,
|
email: values.email,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((_data) => {
|
||||||
toast.success("Email sent", {
|
toast.success("Email sent", {
|
||||||
duration: 2000,
|
duration: 2000,
|
||||||
});
|
});
|
||||||
@@ -150,7 +150,7 @@ export default function Home() {
|
|||||||
Home.getLayout = (page: ReactElement) => {
|
Home.getLayout = (page: ReactElement) => {
|
||||||
return <OnboardingLayout>{page}</OnboardingLayout>;
|
return <OnboardingLayout>{page}</OnboardingLayout>;
|
||||||
};
|
};
|
||||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
export async function getServerSideProps(_context: GetServerSidePropsContext) {
|
||||||
if (!IS_CLOUD) {
|
if (!IS_CLOUD) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import {
|
|||||||
} from "../trpc";
|
} from "../trpc";
|
||||||
|
|
||||||
export const authRouter = createTRPCRouter({
|
export const authRouter = createTRPCRouter({
|
||||||
createAdmin: publicProcedure.mutation(async ({ ctx, input }) => {
|
createAdmin: publicProcedure.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
if (!IS_CLOUD) {
|
if (!IS_CLOUD) {
|
||||||
const admin = await db.query.admins.findFirst({});
|
const admin = await db.query.admins.findFirst({});
|
||||||
@@ -72,9 +72,9 @@ export const authRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
createUser: publicProcedure.mutation(async ({ ctx, input }) => {
|
createUser: publicProcedure.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const token = await getUserByToken(input.token);
|
const _token = await getUserByToken(input.token);
|
||||||
// if (token.isExpired) {
|
// if (token.isExpired) {
|
||||||
// throw new TRPCError({
|
// throw new TRPCError({
|
||||||
// code: "BAD_REQUEST",
|
// code: "BAD_REQUEST",
|
||||||
@@ -103,7 +103,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
login: publicProcedure.mutation(async ({ ctx, input }) => {
|
login: publicProcedure.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const auth = await findAuthByEmail(input.email);
|
const auth = await findAuthByEmail(input.email);
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
logout: protectedProcedure.mutation(async ({ ctx }) => {
|
logout: protectedProcedure.mutation(async ({ ctx }) => {
|
||||||
const { req, res } = ctx;
|
const { req } = ctx;
|
||||||
const { session } = await validateRequest(req);
|
const { session } = await validateRequest(req);
|
||||||
if (!session) return false;
|
if (!session) return false;
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
message: "Password is incorrect",
|
message: "Password is incorrect",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const { req, res } = ctx;
|
const { req } = ctx;
|
||||||
const { session } = await validateRequest(req);
|
const { session } = await validateRequest(req);
|
||||||
if (!session) return false;
|
if (!session) return false;
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
generateToken: protectedProcedure.mutation(async ({ ctx, input }) => {
|
generateToken: protectedProcedure.mutation(async ({ ctx }) => {
|
||||||
const auth = await findUserById(ctx.user.id);
|
const auth = await findUserById(ctx.user.id);
|
||||||
console.log(auth);
|
console.log(auth);
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
email: z.string().min(1).email(),
|
email: z.string().min(1).email(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ input }) => {
|
||||||
if (!IS_CLOUD) {
|
if (!IS_CLOUD) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "NOT_FOUND",
|
code: "NOT_FOUND",
|
||||||
@@ -329,7 +329,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
password: z.string().min(1),
|
password: z.string().min(1),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ input }) => {
|
||||||
if (!IS_CLOUD) {
|
if (!IS_CLOUD) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "NOT_FOUND",
|
code: "NOT_FOUND",
|
||||||
@@ -373,7 +373,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
confirmationToken: z.string().min(1),
|
confirmationToken: z.string().min(1),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ input }) => {
|
||||||
if (!IS_CLOUD) {
|
if (!IS_CLOUD) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "NOT_FOUND",
|
code: "NOT_FOUND",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
mariadb,
|
mariadb,
|
||||||
mongo,
|
mongo,
|
||||||
mysql,
|
mysql,
|
||||||
|
organization,
|
||||||
postgres,
|
postgres,
|
||||||
redis,
|
redis,
|
||||||
server,
|
server,
|
||||||
@@ -102,6 +103,18 @@ export const serverRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
count: protectedProcedure.query(async ({ ctx }) => {
|
||||||
|
const organizations = await db.query.organization.findMany({
|
||||||
|
where: eq(organization.ownerId, ctx.user.id),
|
||||||
|
with: {
|
||||||
|
servers: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const servers = organizations.flatMap((org) => org.servers);
|
||||||
|
|
||||||
|
return servers.length ?? 0;
|
||||||
|
}),
|
||||||
withSSHKey: protectedProcedure.query(async ({ ctx }) => {
|
withSSHKey: protectedProcedure.query(async ({ ctx }) => {
|
||||||
const result = await db.query.server.findMany({
|
const result = await db.query.server.findMany({
|
||||||
orderBy: desc(server.createdAt),
|
orderBy: desc(server.createdAt),
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const stripeRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const items = getStripeItems(input.serverQuantity, input.isAnnual);
|
const items = getStripeItems(input.serverQuantity, input.isAnnual);
|
||||||
const user = await findUserById(ctx.user.ownerId);
|
const user = await findUserById(ctx.user.id);
|
||||||
|
|
||||||
let stripeCustomerId = user.stripeCustomerId;
|
let stripeCustomerId = user.stripeCustomerId;
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ export const stripeRouter = createTRPCRouter({
|
|||||||
customer: stripeCustomerId,
|
customer: stripeCustomerId,
|
||||||
}),
|
}),
|
||||||
metadata: {
|
metadata: {
|
||||||
ownerId: user.id,
|
adminId: user.id,
|
||||||
},
|
},
|
||||||
allow_promotion_codes: true,
|
allow_promotion_codes: true,
|
||||||
success_url: `${WEBSITE_URL}/dashboard/settings/servers?success=true`,
|
success_url: `${WEBSITE_URL}/dashboard/settings/servers?success=true`,
|
||||||
@@ -88,7 +88,7 @@ export const stripeRouter = createTRPCRouter({
|
|||||||
return { sessionId: session.id };
|
return { sessionId: session.id };
|
||||||
}),
|
}),
|
||||||
createCustomerPortalSession: adminProcedure.mutation(async ({ ctx }) => {
|
createCustomerPortalSession: adminProcedure.mutation(async ({ ctx }) => {
|
||||||
const user = await findUserById(ctx.user.ownerId);
|
const user = await findUserById(ctx.user.id);
|
||||||
|
|
||||||
if (!user.stripeCustomerId) {
|
if (!user.stripeCustomerId) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
import bc from "bcrypt";
|
|
||||||
import { drizzle } from "drizzle-orm/postgres-js";
|
import { drizzle } from "drizzle-orm/postgres-js";
|
||||||
import postgres from "postgres";
|
import postgres from "postgres";
|
||||||
|
|
||||||
const connectionString = process.env.DATABASE_URL!;
|
const connectionString = process.env.DATABASE_URL!;
|
||||||
|
|
||||||
const pg = postgres(connectionString, { max: 1 });
|
const pg = postgres(connectionString, { max: 1 });
|
||||||
const db = drizzle(pg);
|
const _db = drizzle(pg);
|
||||||
|
|
||||||
function password(txt: string) {
|
|
||||||
return bc.hashSync(txt, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function seed() {
|
async function seed() {
|
||||||
console.log("> Seed:", process.env.DATABASE_PATH, "\n");
|
console.log("> Seed:", process.env.DATABASE_PATH, "\n");
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const isWSL = async () => {
|
|||||||
const { stdout } = await execAsync("uname -r");
|
const { stdout } = await execAsync("uname -r");
|
||||||
const isWSL = stdout.includes("microsoft");
|
const isWSL = stdout.includes("microsoft");
|
||||||
return isWSL;
|
return isWSL;
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ export const setupDockerContainerTerminalWebSocketServer = (
|
|||||||
throw new Error("No SSH key available for this server");
|
throw new Error("No SSH key available for this server");
|
||||||
|
|
||||||
const conn = new Client();
|
const conn = new Client();
|
||||||
let stdout = "";
|
let _stdout = "";
|
||||||
let stderr = "";
|
let _stderr = "";
|
||||||
conn
|
conn
|
||||||
.once("ready", () => {
|
.once("ready", () => {
|
||||||
conn.exec(
|
conn.exec(
|
||||||
@@ -61,16 +61,16 @@ export const setupDockerContainerTerminalWebSocketServer = (
|
|||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
stream
|
stream
|
||||||
.on("close", (code: number, signal: string) => {
|
.on("close", (code: number, _signal: string) => {
|
||||||
ws.send(`\nContainer closed with code: ${code}\n`);
|
ws.send(`\nContainer closed with code: ${code}\n`);
|
||||||
conn.end();
|
conn.end();
|
||||||
})
|
})
|
||||||
.on("data", (data: string) => {
|
.on("data", (data: string) => {
|
||||||
stdout += data.toString();
|
_stdout += data.toString();
|
||||||
ws.send(data.toString());
|
ws.send(data.toString());
|
||||||
})
|
})
|
||||||
.stderr.on("data", (data) => {
|
.stderr.on("data", (data) => {
|
||||||
stderr += data.toString();
|
_stderr += data.toString();
|
||||||
ws.send(data.toString());
|
ws.send(data.toString());
|
||||||
console.error("Error: ", data.toString());
|
console.error("Error: ", data.toString());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const setupDrawerLogsWebSocketServer = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
wssTerm.on("connection", async (ws, req) => {
|
wssTerm.on("connection", async (ws, req) => {
|
||||||
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
const _url = new URL(req.url || "", `http://${req.headers.host}`);
|
||||||
const { user, session } = await validateRequest(req);
|
const { user, session } = await validateRequest(req);
|
||||||
|
|
||||||
if (!user || !session) {
|
if (!user || !session) {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const setupDeploymentLogsWebSocketServer = (
|
|||||||
ws.close();
|
ws.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (_error) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
// const errorMessage = error?.message as unknown as string;
|
// const errorMessage = error?.message as unknown as string;
|
||||||
// ws.send(errorMessage);
|
// ws.send(errorMessage);
|
||||||
|
|||||||
@@ -144,8 +144,8 @@ export const setupTerminalWebSocketServer = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const conn = new Client();
|
const conn = new Client();
|
||||||
let stdout = "";
|
let _stdout = "";
|
||||||
let stderr = "";
|
let _stderr = "";
|
||||||
|
|
||||||
ws.send("Connecting...\n");
|
ws.send("Connecting...\n");
|
||||||
|
|
||||||
@@ -158,16 +158,16 @@ export const setupTerminalWebSocketServer = (
|
|||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
stream
|
stream
|
||||||
.on("close", (code: number, signal: string) => {
|
.on("close", (code: number, _signal: string) => {
|
||||||
ws.send(`\nContainer closed with code: ${code}\n`);
|
ws.send(`\nContainer closed with code: ${code}\n`);
|
||||||
conn.end();
|
conn.end();
|
||||||
})
|
})
|
||||||
.on("data", (data: string) => {
|
.on("data", (data: string) => {
|
||||||
stdout += data.toString();
|
_stdout += data.toString();
|
||||||
ws.send(data.toString());
|
ws.send(data.toString());
|
||||||
})
|
})
|
||||||
.stderr.on("data", (data) => {
|
.stderr.on("data", (data) => {
|
||||||
stderr += data.toString();
|
_stderr += data.toString();
|
||||||
ws.send(data.toString());
|
ws.send(data.toString());
|
||||||
console.error("Error: ", data.toString());
|
console.error("Error: ", data.toString());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const _mainServiceHash = generateHash(schema.projectName);
|
||||||
|
|
||||||
const domains: DomainSchema[] = [
|
const domains: DomainSchema[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const _mainServiceHash = generateHash(schema.projectName);
|
||||||
const mainDomain = generateRandomDomain(schema);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
|
|
||||||
const domains: DomainSchema[] = [
|
const domains: DomainSchema[] = [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Schema, Template } from "../utils";
|
import type { Schema, Template } from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(_schema: Schema): Template {
|
||||||
const envs = [`CLOUDFLARE_TUNNEL_TOKEN="<INSERT TOKEN>"`];
|
const envs = [`CLOUDFLARE_TUNNEL_TOKEN="<INSERT TOKEN>"`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainDomain = generateRandomDomain(schema);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const secretKeyBase = generateBase64(64);
|
const _secretKeyBase = generateBase64(64);
|
||||||
|
|
||||||
const domains: DomainSchema[] = [
|
const domains: DomainSchema[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export function generate(schema: Schema): Template {
|
|||||||
const mainDomain = generateRandomDomain(schema);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const dbPassword = generatePassword();
|
const dbPassword = generatePassword();
|
||||||
const dbUser = "immich";
|
const dbUser = "immich";
|
||||||
const appSecret = generateBase64(32);
|
const _appSecret = generateBase64(32);
|
||||||
|
|
||||||
const domains: DomainSchema[] = [
|
const domains: DomainSchema[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Schema, Template } from "../utils";
|
import type { Schema, Template } from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(_schema: Schema): Template {
|
||||||
const mounts: Template["mounts"] = [
|
const mounts: Template["mounts"] = [
|
||||||
{
|
{
|
||||||
filePath: "init-mongo.sh",
|
filePath: "init-mongo.sh",
|
||||||
|
|||||||
@@ -28,19 +28,16 @@ export const certificates = pgTable("certificate", {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const certificatesRelations = relations(
|
export const certificatesRelations = relations(certificates, ({ one }) => ({
|
||||||
certificates,
|
server: one(server, {
|
||||||
({ one, many }) => ({
|
fields: [certificates.serverId],
|
||||||
server: one(server, {
|
references: [server.serverId],
|
||||||
fields: [certificates.serverId],
|
|
||||||
references: [server.serverId],
|
|
||||||
}),
|
|
||||||
organization: one(organization, {
|
|
||||||
fields: [certificates.organizationId],
|
|
||||||
references: [organization.id],
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
);
|
organization: one(organization, {
|
||||||
|
fields: [certificates.organizationId],
|
||||||
|
references: [organization.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
export const apiCreateCertificate = createInsertSchema(certificates, {
|
export const apiCreateCertificate = createInsertSchema(certificates, {
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const gitProvider = pgTable("git_provider", {
|
|||||||
.references(() => organization.id, { onDelete: "cascade" }),
|
.references(() => organization.id, { onDelete: "cascade" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
|
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
|
||||||
github: one(github, {
|
github: one(github, {
|
||||||
fields: [gitProvider.gitProviderId],
|
fields: [gitProvider.gitProviderId],
|
||||||
references: [github.gitProviderId],
|
references: [github.gitProviderId],
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const registry = pgTable("registry", {
|
|||||||
.references(() => organization.id, { onDelete: "cascade" }),
|
.references(() => organization.id, { onDelete: "cascade" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const registryRelations = relations(registry, ({ one, many }) => ({
|
export const registryRelations = relations(registry, ({ many }) => ({
|
||||||
applications: many(applications),
|
applications: many(applications),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ import type { IncomingMessage } from "node:http";
|
|||||||
import * as bcrypt from "bcrypt";
|
import * as bcrypt from "bcrypt";
|
||||||
import { betterAuth } from "better-auth";
|
import { betterAuth } from "better-auth";
|
||||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||||
import {
|
import { organization, twoFactor } from "better-auth/plugins";
|
||||||
createAuthMiddleware,
|
|
||||||
organization,
|
|
||||||
twoFactor,
|
|
||||||
} from "better-auth/plugins";
|
|
||||||
import { and, desc, eq } from "drizzle-orm";
|
import { and, desc, eq } from "drizzle-orm";
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
import * as schema from "../db/schema";
|
import * as schema from "../db/schema";
|
||||||
|
import { sendVerificationEmail } from "../verification/send-verification-email";
|
||||||
|
import { IS_CLOUD } from "../constants";
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
@@ -27,9 +25,18 @@ export const auth = betterAuth({
|
|||||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
emailVerification: {
|
||||||
|
sendOnSignUp: true,
|
||||||
|
autoSignInAfterVerification: true,
|
||||||
|
sendVerificationEmail: async ({ user, url }) => {
|
||||||
|
console.log("Sending verification email to", user.email);
|
||||||
|
await sendVerificationEmail(user.email, url);
|
||||||
|
},
|
||||||
|
},
|
||||||
emailAndPassword: {
|
emailAndPassword: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
autoSignIn: !IS_CLOUD,
|
||||||
|
requireEmailVerification: IS_CLOUD,
|
||||||
password: {
|
password: {
|
||||||
async hash(password) {
|
async hash(password) {
|
||||||
return bcrypt.hashSync(password, 10);
|
return bcrypt.hashSync(password, 10);
|
||||||
@@ -39,33 +46,37 @@ export const auth = betterAuth({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hooks: {
|
|
||||||
after: createAuthMiddleware(async (ctx) => {
|
|
||||||
if (ctx.path.startsWith("/sign-up")) {
|
|
||||||
const newSession = ctx.context.newSession;
|
|
||||||
if (ctx.headers?.get("x-dokploy-token")) {
|
|
||||||
} else {
|
|
||||||
const organization = await db
|
|
||||||
.insert(schema.organization)
|
|
||||||
.values({
|
|
||||||
name: "My Organization",
|
|
||||||
ownerId: newSession?.user?.id || "",
|
|
||||||
createdAt: new Date(),
|
|
||||||
})
|
|
||||||
.returning()
|
|
||||||
.then((res) => res[0]);
|
|
||||||
|
|
||||||
await db.insert(schema.member).values({
|
|
||||||
userId: newSession?.user?.id || "",
|
|
||||||
organizationId: organization?.id || "",
|
|
||||||
role: "owner",
|
|
||||||
createdAt: new Date(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
databaseHooks: {
|
databaseHooks: {
|
||||||
|
user: {
|
||||||
|
create: {
|
||||||
|
after: async (user) => {
|
||||||
|
const isAdminPresent = await db.query.member.findFirst({
|
||||||
|
where: eq(schema.member.role, "owner"),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (IS_CLOUD || !isAdminPresent) {
|
||||||
|
await db.transaction(async (tx) => {
|
||||||
|
const organization = await tx
|
||||||
|
.insert(schema.organization)
|
||||||
|
.values({
|
||||||
|
name: "My Organization",
|
||||||
|
ownerId: user.id,
|
||||||
|
createdAt: new Date(),
|
||||||
|
})
|
||||||
|
.returning()
|
||||||
|
.then((res) => res[0]);
|
||||||
|
|
||||||
|
await tx.insert(schema.member).values({
|
||||||
|
userId: user.id,
|
||||||
|
organizationId: organization?.id || "",
|
||||||
|
role: "owner",
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
session: {
|
session: {
|
||||||
create: {
|
create: {
|
||||||
before: async (session) => {
|
before: async (session) => {
|
||||||
@@ -106,7 +117,7 @@ export const auth = betterAuth({
|
|||||||
plugins: [
|
plugins: [
|
||||||
twoFactor(),
|
twoFactor(),
|
||||||
organization({
|
organization({
|
||||||
async sendInvitationEmail(data, request) {
|
async sendInvitationEmail(data, _request) {
|
||||||
const inviteLink = `https://example.com/accept-invitation/${data.id}`;
|
const inviteLink = `https://example.com/accept-invitation/${data.id}`;
|
||||||
// https://example.com/accept-invitation/8jlBi9Tb9isDb8mc8Sb85u1BaJYklKB2
|
// https://example.com/accept-invitation/8jlBi9Tb9isDb8mc8Sb85u1BaJYklKB2
|
||||||
// sendOrganizationInvitation({
|
// sendOrganizationInvitation({
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
// import {
|
|
||||||
// decodeHex,
|
|
||||||
// encodeBase32LowerCaseNoPadding,
|
|
||||||
// encodeHexLowerCase,
|
|
||||||
// } from "@oslojs/encoding";
|
|
||||||
// import { generateRandomString } from "@oslojs/crypto/random";
|
|
||||||
// import { constantTimeEqual } from "@oslojs/crypto/subtle";
|
|
||||||
// import { scrypt } from "./scrypt/index";
|
|
||||||
|
|
||||||
// import type { RandomReader } from "@oslojs/crypto/random";
|
|
||||||
|
|
||||||
// async function generateScryptKey(
|
|
||||||
// data: string,
|
|
||||||
// salt: string,
|
|
||||||
// blockSize = 16,
|
|
||||||
// ): Promise<Uint8Array> {
|
|
||||||
// const encodedData = new TextEncoder().encode(data);
|
|
||||||
// const encodedSalt = new TextEncoder().encode(salt);
|
|
||||||
// const keyUint8Array = await scrypt(encodedData, encodedSalt, {
|
|
||||||
// N: 16384,
|
|
||||||
// r: blockSize,
|
|
||||||
// p: 1,
|
|
||||||
// dkLen: 64,
|
|
||||||
// });
|
|
||||||
// return new Uint8Array(keyUint8Array);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const random: RandomReader = {
|
|
||||||
// read(bytes: Uint8Array): void {
|
|
||||||
// crypto.getRandomValues(bytes);
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
// export function generateId(length: number): string {
|
|
||||||
// const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
// return generateRandomString(random, alphabet, length);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function generateIdFromEntropySize(size: number): string {
|
|
||||||
// const buffer = crypto.getRandomValues(new Uint8Array(size));
|
|
||||||
// return encodeBase32LowerCaseNoPadding(buffer);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export class Scrypt implements PasswordHashingAlgorithm {
|
|
||||||
// async hash(password: string): Promise<string> {
|
|
||||||
// const salt = encodeHexLowerCase(crypto.getRandomValues(new Uint8Array(16)));
|
|
||||||
// const key = await generateScryptKey(password.normalize("NFKC"), salt);
|
|
||||||
// return `${salt}:${encodeHexLowerCase(key)}`;
|
|
||||||
// }
|
|
||||||
// async verify(hash: string, password: string): Promise<boolean> {
|
|
||||||
// const parts = hash.split(":");
|
|
||||||
// if (parts.length !== 2) return false;
|
|
||||||
|
|
||||||
// const [salt, key] = parts;
|
|
||||||
// const targetKey = await generateScryptKey(password.normalize("NFKC"), salt);
|
|
||||||
// return constantTimeEqual(targetKey, decodeHex(key));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export class LegacyScrypt implements PasswordHashingAlgorithm {
|
|
||||||
// async hash(password: string): Promise<string> {
|
|
||||||
// const salt = encodeHexLowerCase(crypto.getRandomValues(new Uint8Array(16)));
|
|
||||||
// const key = await generateScryptKey(password.normalize("NFKC"), salt);
|
|
||||||
// return `s2:${salt}:${encodeHexLowerCase(key)}`;
|
|
||||||
// }
|
|
||||||
// async verify(hash: string, password: string): Promise<boolean> {
|
|
||||||
// const parts = hash.split(":");
|
|
||||||
// if (parts.length === 2) {
|
|
||||||
// const [salt, key] = parts;
|
|
||||||
// const targetKey = await generateScryptKey(
|
|
||||||
// password.normalize("NFKC"),
|
|
||||||
// salt,
|
|
||||||
// 8,
|
|
||||||
// );
|
|
||||||
// const result = constantTimeEqual(targetKey, decodeHex(key));
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
// if (parts.length !== 3) return false;
|
|
||||||
// const [version, salt, key] = parts;
|
|
||||||
// if (version === "s2") {
|
|
||||||
// const targetKey = await generateScryptKey(
|
|
||||||
// password.normalize("NFKC"),
|
|
||||||
// salt,
|
|
||||||
// );
|
|
||||||
// return constantTimeEqual(targetKey, decodeHex(key));
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export interface PasswordHashingAlgorithm {
|
|
||||||
// hash(password: string): Promise<string>;
|
|
||||||
// verify(hash: string, password: string): Promise<boolean>;
|
|
||||||
// }
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
//
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user