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:
Mauricio Siu 2025-02-22 20:35:21 -06:00
parent 1a415b96c9
commit 8ab6d6b282
132 changed files with 375 additions and 471 deletions

View File

@ -130,7 +130,7 @@ const createStringToJSONSchema = (schema: z.ZodTypeAny) => {
}
try {
return JSON.parse(str);
} catch (e) {
} catch (_e) {
ctx.addIssue({ code: "custom", message: "Invalid JSON format" });
return z.NEVER;
}

View File

@ -77,7 +77,7 @@ export const UpdateVolume = ({
serviceType,
}: Props) => {
const [isOpen, setIsOpen] = useState(false);
const utils = api.useUtils();
const _utils = api.useUtils();
const { data } = api.mounts.one.useQuery(
{
mountId,

View File

@ -84,7 +84,6 @@ export const SaveBitbucketProvider = ({ applicationId }: Props) => {
data: repositories,
isLoading: isLoadingRepositories,
error,
isError,
} = api.bitbucket.getBitbucketRepositories.useQuery(
{
bitbucketId,

View File

@ -27,8 +27,7 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
const { mutateAsync: stop, isLoading: isStopping } =
api.application.stop.useMutation();
const { mutateAsync: deploy, isLoading: isDeploying } =
api.application.deploy.useMutation();
const { mutateAsync: deploy } = api.application.deploy.useMutation();
const { mutateAsync: reload, isLoading: isReloading } =
api.application.reload.useMutation();

View File

@ -279,7 +279,7 @@ export const ShowPreviewSettings = ({ applicationId }: Props) => {
<FormField
control={form.control}
name="env"
render={({ field }) => (
render={() => (
<FormItem>
<FormControl>
<Secrets

View File

@ -60,7 +60,7 @@ export const DeleteService = ({ id, type }: Props) => {
compose: () =>
api.compose.one.useQuery({ composeId: id }, { enabled: !!id }),
};
const { data, refetch } = queryMap[type]
const { data } = queryMap[type]
? queryMap[type]()
: api.mongo.one.useQuery({ mongoId: id }, { enabled: !!id });

View File

@ -118,7 +118,7 @@ export const ShowDomainsCompose = ({ composeId }: Props) => {
await deleteDomain({
domainId: item.domainId,
})
.then((data) => {
.then((_data) => {
refetch();
toast.success("Domain deleted successfully");
})

View File

@ -35,8 +35,7 @@ export const ComposeFileEditor = ({ composeId }: Props) => {
{ enabled: !!composeId },
);
const { mutateAsync, isLoading, error, isError } =
api.compose.update.useMutation();
const { mutateAsync, isLoading } = api.compose.update.useMutation();
const form = useForm<AddComposeFile>({
defaultValues: {
@ -76,7 +75,7 @@ export const ComposeFileEditor = ({ composeId }: Props) => {
composeId,
});
})
.catch((e) => {
.catch((_e) => {
toast.error("Error updating the Compose config");
});
};

View File

@ -84,7 +84,6 @@ export const SaveBitbucketProviderCompose = ({ composeId }: Props) => {
data: repositories,
isLoading: isLoadingRepositories,
error,
isError,
} = api.bitbucket.getBitbucketRepositories.useQuery(
{
bitbucketId,

View File

@ -70,7 +70,7 @@ export const IsolatedDeployment = ({ composeId }: Props) => {
composeId,
isolatedDeployment: formData?.isolatedDeployment || false,
})
.then(async (data) => {
.then(async (_data) => {
randomizeCompose();
refetch();
toast.success("Compose updated");

View File

@ -39,7 +39,7 @@ type Schema = z.infer<typeof schema>;
export const RandomizeCompose = ({ composeId }: Props) => {
const utils = api.useUtils();
const [compose, setCompose] = useState<string>("");
const [isOpen, setIsOpen] = useState(false);
const [_isOpen, _setIsOpen] = useState(false);
const { mutateAsync, error, isError } =
api.compose.randomizeCompose.useMutation();
@ -76,7 +76,7 @@ export const RandomizeCompose = ({ composeId }: Props) => {
suffix: formData?.suffix || "",
randomize: formData?.randomize || false,
})
.then(async (data) => {
.then(async (_data) => {
randomizeCompose();
refetch();
toast.success("Compose updated");

View File

@ -40,7 +40,7 @@ export const ShowConvertedCompose = ({ composeId }: Props) => {
.then(() => {
refetch();
})
.catch((err) => {});
.catch((_err) => {});
}
}, [isOpen]);

View File

@ -29,14 +29,6 @@ interface Props {
data: ContainerMetric[];
}
interface FormattedMetric {
timestamp: string;
read: number;
write: number;
readUnit: string;
writeUnit: string;
}
const chartConfig = {
read: {
label: "Read",

View File

@ -20,7 +20,7 @@ interface Props {
organizationId?: string;
children?: React.ReactNode;
}
export function AddOrganization({ organizationId, children }: Props) {
export function AddOrganization({ organizationId }: Props) {
const utils = api.useUtils();
const { data: organization } = api.organization.one.useQuery(
{

View File

@ -53,7 +53,7 @@ export const ShowCustomCommand = ({ id, type }: Props) => {
mongo: () => api.mongo.update.useMutation(),
};
const { mutateAsync, isLoading } = mutationMap[type]
const { mutateAsync } = mutationMap[type]
? mutationMap[type]()
: api.mongo.update.useMutation();

View File

@ -103,7 +103,7 @@ export const AddApplication = ({ projectId, projectName }: Props) => {
projectId,
});
})
.catch((e) => {
.catch((_e) => {
toast.error("Error creating the service");
});
};

View File

@ -434,14 +434,14 @@ export const AddTemplate = ({ projectId }: Props) => {
});
toast.promise(promise, {
loading: "Setting up...",
success: (data) => {
success: (_data) => {
utils.project.one.invalidate({
projectId,
});
setOpen(false);
return `${template.name} template created successfully`;
},
error: (err) => {
error: (_err) => {
return `An error ocurred deploying ${template.name} template`;
},
});

View File

@ -79,7 +79,7 @@ export const ShowExternalRedisCredentials = ({ redisId }: Props) => {
useEffect(() => {
const buildConnectionUrl = () => {
const hostname = window.location.hostname;
const _hostname = window.location.hostname;
const port = form.watch("externalPort") || data?.externalPort;
return `redis://default:${data?.databasePassword}@${getIp}:${port}`;

View File

@ -24,7 +24,7 @@ export const getStatusColor = (status: number) => {
export const columns: ColumnDef<LogEntry>[] = [
{
accessorKey: "level",
header: ({ column }) => {
header: () => {
return <Button variant="ghost">Level</Button>;
},
cell: ({ row }) => {

View File

@ -92,7 +92,7 @@ export const RequestsTable = () => {
pageSize: 10,
});
const { data: statsLogs, isLoading } = api.settings.readStatsLogs.useQuery(
const { data: statsLogs } = api.settings.readStatsLogs.useQuery(
{
sort: sorting[0],
page: pagination,
@ -300,7 +300,7 @@ export const RequestsTable = () => {
</div>
<Sheet
open={!!selectedRow}
onOpenChange={(open) => setSelectedRow(undefined)}
onOpenChange={(_open) => setSelectedRow(undefined)}
>
<SheetContent className="sm:max-w-[740px] flex flex-col">
<SheetHeader>

View File

@ -22,14 +22,11 @@ import {
extractServices,
} from "@/pages/dashboard/project/[projectId]";
import { api } from "@/utils/api";
import type { findProjectById } from "@dokploy/server/services/project";
import { BookIcon, CircuitBoard, GlobeIcon } from "lucide-react";
import { useRouter } from "next/router";
import React from "react";
import { StatusTooltip } from "../shared/status-tooltip";
type Project = Awaited<ReturnType<typeof findProjectById>>;
export const SearchCommand = () => {
const router = useRouter();
const [open, setOpen] = React.useState(false);
@ -38,7 +35,7 @@ export const SearchCommand = () => {
const { data } = api.project.all.useQuery(undefined, {
enabled: !!session,
});
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
React.useEffect(() => {
const down = (e: KeyboardEvent) => {

View File

@ -38,7 +38,7 @@ export const calculatePrice = (count: number, isAnnual = false) => {
return count * 3.5;
};
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, isLoading } = api.stripe.getProducts.useQuery();
const { mutateAsync: createCheckoutSession } =
@ -71,7 +71,7 @@ export const ShowBilling = () => {
});
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);
return (
@ -102,13 +102,13 @@ export const ShowBilling = () => {
<div className="space-y-2 flex flex-col">
<h3 className="text-lg font-medium">Servers Plan</h3>
<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
</p>
<div>
<Progress value={safePercentage} className="max-w-lg" />
</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">
<AlertTriangle className="text-yellow-600 dark:text-yellow-400" />
<span className="text-sm text-yellow-600 dark:text-yellow-400">

View File

@ -41,8 +41,7 @@ export const ShowNodes = () => {
const { data, isLoading, refetch } = api.cluster.getNodes.useQuery();
const { data: registry } = api.registry.all.useQuery();
const { mutateAsync: deleteNode, isLoading: isRemoving } =
api.cluster.removeWorker.useMutation();
const { mutateAsync: deleteNode } = api.cluster.removeWorker.useMutation();
const haveAtLeastOneRegistry = !!(registry && registry?.length > 0);
return (

View File

@ -131,7 +131,7 @@ export const HandleRegistry = ({ registryId }: Props) => {
serverId: data.serverId,
registryId: registryId || "",
})
.then(async (data) => {
.then(async (_data) => {
await utils.registry.all.invalidate();
toast.success(registryId ? "Registry updated" : "Registry added");
setIsOpen(false);

View File

@ -47,10 +47,10 @@ type Schema = z.infer<typeof Schema>;
export const AddBitbucketProvider = () => {
const utils = api.useUtils();
const [isOpen, setIsOpen] = useState(false);
const url = useUrl();
const _url = useUrl();
const { mutateAsync, error, isError } = api.bitbucket.create.useMutation();
const { data: auth } = api.user.get.useQuery();
const router = useRouter();
const _router = useRouter();
const form = useForm<Schema>({
defaultValues: {
username: "",

View File

@ -102,7 +102,7 @@ export const ShowGitProviders = () => {
</div>
<div className="flex flex-col gap-4 rounded-lg ">
{data?.map((gitProvider, index) => {
{data?.map((gitProvider, _index) => {
const isGithub = gitProvider.providerType === "github";
const isGitlab = gitProvider.providerType === "gitlab";
const isBitbucket =

View File

@ -136,7 +136,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
const [visible, setVisible] = useState(false);
const { data: isCloud } = api.settings.isCloud.useQuery();
const { data: notification, refetch } = api.notification.one.useQuery(
const { data: notification } = api.notification.one.useQuery(
{
notificationId: notificationId || "",
},
@ -1038,7 +1038,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
});
}
toast.success("Connection Success");
} catch (err) {
} catch (_err) {
toast.error("Error testing the provider");
}
}}

View File

@ -56,7 +56,7 @@ export const ShowNotifications = () => {
) : (
<div className="flex flex-col gap-4 min-h-[25vh]">
<div className="flex flex-col gap-4 rounded-lg ">
{data?.map((notification, index) => (
{data?.map((notification, _index) => (
<div
key={notification.notificationId}
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"

View File

@ -63,7 +63,7 @@ export const Disable2FA = () => {
toast.success("2FA disabled successfully");
utils.auth.get.invalidate();
setIsOpen(false);
} catch (error) {
} catch (_error) {
form.setError("password", {
message: "Connection error. Please try again.",
});

View File

@ -47,20 +47,8 @@ const PinSchema = z.object({
type PasswordForm = z.infer<typeof PasswordSchema>;
type PinForm = z.infer<typeof PinSchema>;
type TwoFactorEnableResponse = {
totpURI: string;
backupCodes: string[];
};
type TwoFactorSetupData = {
qrCodeUrl: string;
secret: string;
totpURI: string;
};
export const Enable2FA = () => {
const utils = api.useUtils();
const { data: session } = authClient.useSession();
const [data, setData] = useState<TwoFactorSetupData | null>(null);
const [backupCodes, setBackupCodes] = useState<string[]>([]);
const [isDialogOpen, setIsDialogOpen] = useState(false);

View File

@ -54,9 +54,7 @@ const randomImages = [
];
export const ProfileForm = () => {
const utils = api.useUtils();
const { mutateAsync: disable2FA, isLoading: isDisabling } =
api.auth.disable2FA.useMutation();
const _utils = api.useUtils();
const { data, refetch, isLoading } = api.user.get.useQuery();
const {
mutateAsync,

View File

@ -26,7 +26,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
isLoading: cleanDockerBuilderIsLoading,
} = api.settings.cleanDockerBuilder.useMutation();
const { mutateAsync: cleanMonitoring, isLoading: cleanMonitoringIsLoading } =
const { mutateAsync: cleanMonitoring } =
api.settings.cleanMonitoring.useMutation();
const {
mutateAsync: cleanUnusedImages,

View File

@ -36,7 +36,7 @@ export const ToggleDockerCleanup = ({ serverId }: Props) => {
await refetch();
}
toast.success("Docker Cleanup updated");
} catch (error) {
} catch (_error) {
toast.error("Docker Cleanup Error");
}
};

View File

@ -82,7 +82,7 @@ export const EditScript = ({ serverId }: Props) => {
command: formData.command || "",
serverId,
})
.then((data) => {
.then((_data) => {
toast.success("Script modified successfully");
})
.catch(() => {

View File

@ -56,7 +56,7 @@ export function GPUSupport({ serverId }: GPUSupportProps) {
try {
await utils.settings.checkGPUStatus.invalidate({ serverId });
await refetch();
} catch (error) {
} catch (_error) {
toast.error("Failed to refresh GPU status");
} finally {
setIsRefreshing(false);
@ -74,7 +74,7 @@ export function GPUSupport({ serverId }: GPUSupportProps) {
try {
await setupGPU.mutateAsync({ serverId });
} catch (error) {
} catch (_error) {
// Error handling is done in mutation's onError
}
};

View File

@ -118,7 +118,7 @@ export const HandleServers = ({ serverId }: Props) => {
sshKeyId: data.sshKeyId || "",
serverId: serverId || "",
})
.then(async (data) => {
.then(async (_data) => {
await utils.server.all.invalidate();
refetchServer();
toast.success(serverId ? "Server Updated" : "Server Created");

View File

@ -25,7 +25,7 @@ export const SecurityAudit = ({ serverId }: Props) => {
enabled: !!serverId,
},
);
const utils = api.useUtils();
const _utils = api.useUtils();
return (
<CardContent className="p-0">
<div className="flex flex-col gap-4">

View File

@ -80,7 +80,7 @@ const Schema = z.object({
type Schema = z.infer<typeof Schema>;
export const SetupMonitoring = ({ serverId }: Props) => {
const { data, isLoading } = serverId
const { data } = serverId
? api.server.one.useQuery(
{
serverId: serverId || "",

View File

@ -25,7 +25,7 @@ export const ValidateServer = ({ serverId }: Props) => {
enabled: !!serverId,
},
);
const utils = api.useUtils();
const _utils = api.useUtils();
return (
<CardContent className="p-0">
<div className="flex flex-col gap-4">

View File

@ -52,10 +52,10 @@ interface Props {
export const CreateServer = ({ stepper }: Props) => {
const { data: sshKeys } = api.sshKey.all.useQuery();
const [isOpen, setIsOpen] = useState(false);
const [isOpen, _setIsOpen] = useState(false);
const { data: canCreateMoreServers, refetch } =
api.stripe.canCreateMoreServers.useQuery();
const { mutateAsync, error, isError } = api.server.create.useMutation();
const { mutateAsync } = api.server.create.useMutation();
const cloudSSHKey = sshKeys?.find(
(sshKey) => sshKey.name === "dokploy-cloud-ssh-key",
);
@ -96,7 +96,7 @@ export const CreateServer = ({ stepper }: Props) => {
username: data.username || "root",
sshKeyId: data.sshKeyId || "",
})
.then(async (data) => {
.then(async (_data) => {
toast.success("Server Created");
stepper.next();
})

View File

@ -37,15 +37,6 @@ export const Verify = () => {
);
const [isRefreshing, setIsRefreshing] = useState(false);
const { data: server } = api.server.one.useQuery(
{
serverId,
},
{
enabled: !!serverId,
},
);
return (
<CardContent className="p-0">
<div className="flex flex-col gap-4">

View File

@ -143,7 +143,7 @@ export const ShowInvitations = () => {
{invitation.status === "pending" && (
<DropdownMenuItem
className="w-full cursor-pointer"
onSelect={(e) => {
onSelect={(_e) => {
copy(
`${origin}/invitation?token=${invitation.id}`,
);
@ -159,7 +159,7 @@ export const ShowInvitations = () => {
{invitation.status === "pending" && (
<DropdownMenuItem
className="w-full cursor-pointer"
onSelect={async (e) => {
onSelect={async (_e) => {
const result =
await authClient.organization.cancelInvitation(
{

View File

@ -35,7 +35,7 @@ import { AddUserPermissions } from "./add-permissions";
export const ShowUsers = () => {
const { data: isCloud } = api.settings.isCloud.useQuery();
const { data, isLoading, refetch } = api.user.all.useQuery();
const { mutateAsync, isLoading: isRemoving } = api.user.remove.useMutation();
const { mutateAsync } = api.user.remove.useMutation();
return (
<div className="w-full">

View File

@ -14,10 +14,7 @@ import { ShowTraefikActions } from "./servers/actions/show-traefik-actions";
import { ToggleDockerCleanup } from "./servers/actions/toggle-docker-cleanup";
import { UpdateServer } from "./web-server/update-server";
interface Props {
className?: string;
}
export const WebServer = ({ className }: Props) => {
export const WebServer = () => {
const { t } = useTranslation("settings");
const { data } = api.user.get.useQuery();

View File

@ -99,7 +99,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
});
toast.success(t("settings.server.webServer.traefik.portsUpdated"));
setOpen(false);
} catch (error) {
} catch (_error) {
toast.error(t("settings.server.webServer.traefik.portsUpdateError"));
}
};

View File

@ -43,7 +43,7 @@ interface Props {
serverId?: string;
}
export const UpdateServerIp = ({ children, serverId }: Props) => {
export const UpdateServerIp = ({ children }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const { data } = api.user.get.useQuery();

View File

@ -214,7 +214,7 @@ export const columns: ColumnDef<ApplicationList>[] = [
{
accessorKey: "Logs",
accessorFn: (row) => row.Error,
header: ({ column }) => {
header: () => {
return <span>Logs</span>;
},
cell: ({ row }) => {

View File

@ -48,7 +48,7 @@ export function DataTable<TData, TValue>({
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const [pagination, setPagination] = React.useState({
const [_pagination, _setPagination] = React.useState({
pageIndex: 0, //initial page index
pageSize: 8, //default page size
});

View File

@ -17,7 +17,7 @@ interface Props {
}
export const ShowNodeConfig = ({ nodeId, serverId }: Props) => {
const { data, isLoading } = api.swarm.getNodeInfo.useQuery({
const { data } = api.swarm.getNodeInfo.useQuery({
nodeId,
serverId,
});

View File

@ -157,7 +157,7 @@ const MENU: Menu = {
url: "/dashboard/monitoring",
icon: BarChartHorizontalBigIcon,
// Only enabled in non-cloud environments
isEnabled: ({ auth, isCloud }) => !isCloud,
isEnabled: ({ isCloud }) => !isCloud,
},
{
isSingle: true,
@ -277,7 +277,7 @@ const MENU: Menu = {
url: "/dashboard/settings/servers",
icon: Server,
// Only enabled for admins
isEnabled: ({ auth, isCloud }) => !!(auth?.role === "owner"),
isEnabled: ({ auth }) => !!(auth?.role === "owner"),
},
{
isSingle: true,
@ -490,8 +490,9 @@ function SidebarLogo() {
const { state } = useSidebar();
const { data: isCloud } = api.settings.isCloud.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: organizations,
refetch,
@ -501,12 +502,12 @@ function SidebarLogo() {
api.organization.delete.useMutation();
const { isMobile } = useSidebar();
const { data: activeOrganization } = authClient.useActiveOrganization();
const utils = api.useUtils();
const _utils = api.useUtils();
const { data: invitations, refetch: refetchInvitations } =
api.user.getInvitations.useQuery();
const [activeTeam, setActiveTeam] = useState<
const [_activeTeam, setActiveTeam] = useState<
typeof activeOrganization | null
>(null);
@ -543,7 +544,7 @@ function SidebarLogo() {
</div>
<div className="flex flex-col items-start">
<p className="text-sm font-medium leading-none">
{activeOrganization?.name}
{activeOrganization?.name ?? "Select Organization"}
</p>
</div>
</div>
@ -551,7 +552,7 @@ function SidebarLogo() {
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-[--radix-dropdown-menu-trigger-width] min-w-64 rounded-lg"
className=" rounded-lg"
align="start"
side={isMobile ? "bottom" : "right"}
sideOffset={4}
@ -570,6 +571,7 @@ function SidebarLogo() {
}}
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">
<Logo
className={cn(
@ -578,9 +580,8 @@ function SidebarLogo() {
)}
/>
</div>
{org.name}
</DropdownMenuItem>
{(org.ownerId === session?.user?.id || isCloud) && (
{org.ownerId === session?.user?.id && (
<div className="flex items-center gap-2">
<AddOrganization organizationId={org.id} />
<DialogAction
@ -618,7 +619,7 @@ function SidebarLogo() {
)}
</div>
))}
{!isCloud && user?.role === "owner" && (
{(user?.role === "owner" || isCloud) && (
<>
<DropdownMenuSeparator />
<AddOrganization />
@ -721,11 +722,11 @@ export default function Page({ children }: Props) {
const router = useRouter();
const pathname = usePathname();
const currentPath = router.pathname;
const _currentPath = router.pathname;
const { data: auth } = api.user.get.useQuery();
const includesProjects = pathname?.includes("/dashboard/project");
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
const {
home: filteredHome,

View File

@ -11,7 +11,7 @@ export const UpdateServerButton = () => {
latestVersion: null,
updateAvailable: false,
});
const router = useRouter();
const _router = useRouter();
const { data: isCloud } = api.settings.isCloud.useQuery();
const { mutateAsync: getUpdateData } =
api.settings.getUpdateData.useMutation();

View File

@ -24,7 +24,7 @@ import { useRouter } from "next/router";
import { ModeToggle } from "../ui/modeToggle";
import { SidebarMenuButton } from "../ui/sidebar";
const AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 7;
const _AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 7;
export const UserNav = () => {
const router = useRouter();

View File

@ -26,7 +26,7 @@ export const BreadcrumbSidebar = ({ list }: Props) => {
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>
{list.map((item, index) => (
{list.map((item, _index) => (
<Fragment key={item.name}>
<BreadcrumbItem className="block">
<BreadcrumbLink href={item.href} asChild={!!item.href}>

View File

@ -43,7 +43,7 @@ export const DrawerLogs = ({ isOpen, onClose, filteredLogs }: Props) => {
return (
<Sheet
open={!!isOpen}
onOpenChange={(open) => {
onOpenChange={(_open) => {
onClose();
}}
>

View File

@ -85,7 +85,7 @@ const Tree = React.forwardRef<HTMLDivElement, TreeProps>(
return ids;
}, [data, initialSlelectedItemId]);
const { ref: refRoot, width, height } = useResizeObserver();
const { ref: refRoot } = useResizeObserver();
return (
<div ref={refRoot} className={cn("overflow-y-auto", className)}>

View File

@ -136,7 +136,7 @@ await db
},
});
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 || "",
});
}

View File

@ -90,7 +90,7 @@ export default function Custom404({ statusCode, error }: Props) {
}
// @ts-ignore
Error.getInitialProps = ({ res, err, ...rest }: NextPageContext) => {
Error.getInitialProps = ({ res, err }: NextPageContext) => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
return { statusCode, error: err };
};

View File

@ -1,7 +1,7 @@
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
_req: NextApiRequest,
res: NextApiResponse,
) {
return res.status(200).json({ ok: true });

View File

@ -16,8 +16,7 @@ export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
const { code, state, installation_id, setup_action }: Query =
req.query as Query;
const { code, state, installation_id }: Query = req.query as Query;
if (!code) {
return res.status(400).json({ error: "Missing code parameter" });

View File

@ -1,7 +1,7 @@
import { buffer } from "node:stream/consumers";
import { db } from "@/server/db";
import { server, users_temp } from "@/server/db/schema";
import { findUserById } from "@dokploy/server";
import { organization, server, users_temp } from "@/server/db/schema";
import { findUserById, type Server } from "@dokploy/server";
import { asc, eq } from "drizzle-orm";
import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
@ -172,11 +172,11 @@ export default async function handler(
}
await db
.update(admins)
.update(users_temp)
.set({
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(
suscription.customer as string,
@ -205,11 +205,13 @@ export default async function handler(
return res.status(400).send("Webhook Error: Admin not found");
}
await db
.update(admins)
.update(users_temp)
.set({
serversQuantity: 0,
})
.where(eq(admins.stripeCustomerId, newInvoice.customer as string));
.where(
eq(users_temp.stripeCustomerId, newInvoice.customer as string),
);
await disableServers(admin.id);
}
@ -245,12 +247,18 @@ export default async function handler(
}
const disableServers = async (userId: string) => {
const organizations = await db.query.organization.findMany({
where: eq(organization.ownerId, userId),
});
for (const org of organizations) {
await db
.update(server)
.set({
serverStatus: "inactive",
})
.where(eq(server.userId, userId));
.where(eq(server.organizationId, org.id));
}
};
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
@ -275,10 +283,18 @@ const deactivateServer = async (serverId: string) => {
};
export const findServersByUserIdSorted = async (userId: string) => {
const servers = await db.query.server.findMany({
where: eq(server.userId, userId),
const organizations = await db.query.organization.findMany({
where: eq(organization.ownerId, userId),
});
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;
};

View File

@ -72,7 +72,7 @@ export async function getServerSideProps(
trpcState: helpers.dehydrate(),
},
};
} catch (error) {
} catch (_error) {
return {
props: {},
};

View File

@ -15,8 +15,7 @@ const BASE_URL = "http://localhost:3001/metrics";
const DEFAULT_TOKEN = "metrics";
const Dashboard = () => {
const { data: isCloud } = api.settings.isCloud.useQuery();
const [toggleMonitoring, setToggleMonitoring] = useLocalStorage(
const [toggleMonitoring, _setToggleMonitoring] = useLocalStorage(
"monitoring-enabled",
false,
);

View File

@ -261,7 +261,7 @@ const Project = (
try {
await composeActions.start.mutateAsync({ composeId: serviceId });
success++;
} catch (error) {
} catch (_error) {
toast.error(`Error starting service ${serviceId}`);
}
}
@ -281,7 +281,7 @@ const Project = (
try {
await composeActions.stop.mutateAsync({ composeId: serviceId });
success++;
} catch (error) {
} catch (_error) {
toast.error(`Error stopping service ${serviceId}`);
}
}
@ -685,7 +685,7 @@ export async function getServerSideProps(
projectId: params?.projectId,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -65,7 +65,7 @@ type TabState =
const Service = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { applicationId, activeTab } = props;
const router = useRouter();
const { projectId } = router.query;
@ -86,7 +86,6 @@ const Service = (
const { data: isCloud } = api.settings.isCloud.useQuery();
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
return (
<div className="pb-10">
@ -399,7 +398,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -59,7 +59,7 @@ type TabState =
const Service = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { composeId, activeTab } = props;
const router = useRouter();
const { projectId } = router.query;
@ -79,7 +79,6 @@ const Service = (
);
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
return (
@ -393,7 +392,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -52,7 +52,7 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
const Mariadb = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { mariadbId, activeTab } = props;
const router = useRouter();
@ -60,7 +60,6 @@ const Mariadb = (
const [tab, setSab] = useState<TabState>(activeTab);
const { data } = api.mariadb.one.useQuery({ mariadbId });
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
@ -342,7 +341,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -52,7 +52,7 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
const Mongo = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { mongoId, activeTab } = props;
const router = useRouter();
const { projectId } = router.query;
@ -60,7 +60,6 @@ const Mongo = (
const { data } = api.mongo.one.useQuery({ mongoId });
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
@ -343,7 +342,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -52,14 +52,13 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
const MySql = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { mysqlId, activeTab } = props;
const router = useRouter();
const { projectId } = router.query;
const [tab, setSab] = useState<TabState>(activeTab);
const { data } = api.mysql.one.useQuery({ mysqlId });
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
@ -348,7 +347,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -52,7 +52,7 @@ type TabState = "projects" | "monitoring" | "settings" | "backups" | "advanced";
const Postgresql = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { postgresId, activeTab } = props;
const router = useRouter();
const { projectId } = router.query;
@ -60,7 +60,6 @@ const Postgresql = (
const { data } = api.postgres.one.useQuery({ postgresId });
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
return (
@ -345,7 +344,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -51,7 +51,7 @@ type TabState = "projects" | "monitoring" | "settings" | "advanced";
const Redis = (
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) => {
const [toggleMonitoring, setToggleMonitoring] = useState(false);
const [_toggleMonitoring, _setToggleMonitoring] = useState(false);
const { redisId, activeTab } = props;
const router = useRouter();
const { projectId } = router.query;
@ -59,7 +59,6 @@ const Redis = (
const { data } = api.redis.one.useQuery({ redisId });
const { data: auth } = api.user.get.useQuery();
const { data: monitoring } = api.user.getMetricsToken.useQuery();
const { data: isCloud } = api.settings.isCloud.useQuery();
@ -335,7 +334,7 @@ export async function getServerSideProps(
activeTab: (activeTab || "general") as TabState,
},
};
} catch (error) {
} catch (_error) {
return {
redirect: {
permanent: false,

View File

@ -68,7 +68,7 @@ export async function getServerSideProps(
trpcState: helpers.dehydrate(),
},
};
} catch (error) {
} catch (_error) {
return {
props: {},
};

View File

@ -33,7 +33,7 @@ export async function getServerSideProps(
},
};
}
const { req, res, resolvedUrl } = ctx;
const { req, res } = ctx;
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {
@ -69,7 +69,7 @@ export async function getServerSideProps(
trpcState: helpers.dehydrate(),
},
};
} catch (error) {
} catch (_error) {
return {
props: {},
};

View File

@ -72,7 +72,7 @@ export async function getServerSideProps(
trpcState: helpers.dehydrate(),
},
};
} catch (error) {
} catch (_error) {
return {
props: {},
};

View File

@ -72,7 +72,7 @@ export async function getServerSideProps(
trpcState: helpers.dehydrate(),
},
};
} catch (error) {
} catch (_error) {
return {
props: {},
};

View File

@ -43,18 +43,11 @@ const LoginSchema = z.object({
password: z.string().min(8),
});
const TwoFactorSchema = z.object({
const _TwoFactorSchema = z.object({
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 BackupCodeForm = z.infer<typeof BackupCodeSchema>;
interface Props {
IS_CLOUD: boolean;
@ -101,7 +94,7 @@ export default function Home({ IS_CLOUD }: Props) {
toast.success("Logged in successfully");
router.push("/dashboard/projects");
} catch (error) {
} catch (_error) {
toast.error("An error occurred while logging in");
} finally {
setIsLoginLoading(false);
@ -117,7 +110,7 @@ export default function Home({ IS_CLOUD }: Props) {
setIsTwoFactorLoading(true);
try {
const { data, error } = await authClient.twoFactor.verifyTotp({
const { error } = await authClient.twoFactor.verifyTotp({
code: twoFactorCode.replace(/\s/g, ""),
});
@ -129,7 +122,7 @@ export default function Home({ IS_CLOUD }: Props) {
toast.success("Logged in successfully");
router.push("/dashboard/projects");
} catch (error) {
} catch (_error) {
toast.error("An error occurred while verifying 2FA code");
} finally {
setIsTwoFactorLoading(false);
@ -145,7 +138,7 @@ export default function Home({ IS_CLOUD }: Props) {
setIsBackupCodeLoading(true);
try {
const { data, error } = await authClient.twoFactor.verifyBackupCode({
const { error } = await authClient.twoFactor.verifyBackupCode({
code: backupCode.trim(),
});
@ -159,7 +152,7 @@ export default function Home({ IS_CLOUD }: Props) {
toast.success("Logged in successfully");
router.push("/dashboard/projects");
} catch (error) {
} catch (_error) {
toast.error("An error occurred while verifying backup code");
} finally {
setIsBackupCodeLoading(false);
@ -396,7 +389,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
},
};
}
} catch (error) {}
} catch (_error) {}
return {
props: {

View File

@ -16,7 +16,6 @@ import { authClient } from "@/lib/auth-client";
import { api } from "@/utils/api";
import { IS_CLOUD, getUserByToken } from "@dokploy/server";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import type { GetServerSidePropsContext } from "next";
import Link from "next/link";
import { useRouter } from "next/router";
@ -90,9 +89,6 @@ const Invitation = ({
},
);
const { mutateAsync, error, isError, isSuccess } =
api.auth.createUser.useMutation();
const form = useForm<Register>({
defaultValues: {
name: "",
@ -115,7 +111,7 @@ const Invitation = ({
const onSubmit = async (values: Register) => {
try {
const { data, error } = await authClient.signUp.email({
const { error } = await authClient.signUp.email({
email: values.email,
password: values.password,
name: values.name,
@ -131,13 +127,13 @@ const Invitation = ({
return;
}
const result = await authClient.organization.acceptInvitation({
const _result = await authClient.organization.acceptInvitation({
invitationId: token,
});
toast.success("Account created successfully");
router.push("/dashboard/projects");
} catch (error) {
} catch (_error) {
toast.error("An error occurred while creating your account");
}
};
@ -180,14 +176,14 @@ const Invitation = ({
<div className="w-full">
<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">
<AlertTriangle className="text-red-600 dark:text-red-400" />
<span className="text-sm text-red-600 dark:text-red-400">
{error?.message}
</span>
</div>
)}
)} */}
<CardContent className="p-0">
<Form {...form}>
@ -313,7 +309,6 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) {
const { query } = ctx;
const token = query.token;
console.log("query", query);
if (typeof token !== "string") {
return {

View File

@ -13,15 +13,15 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth-client";
import { api } from "@/utils/api";
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import type { GetServerSidePropsContext } from "next";
import Link from "next/link";
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 { toast } from "sonner";
import { z } from "zod";
const registerSchema = z
@ -72,15 +72,16 @@ interface Props {
const Register = ({ isCloud }: Props) => {
const router = useRouter();
const { mutateAsync, error, isError, data } =
api.auth.createAdmin.useMutation();
const [isError, setIsError] = useState(false);
const [error, setError] = useState<string | null>(null);
const [data, setData] = useState<any>(null);
const form = useForm<Register>({
defaultValues: {
name: "Mauricio Siu",
email: "user5@yopmail.com",
password: "Password1234",
confirmPassword: "Password1234",
password: "Password123",
confirmPassword: "Password123",
},
resolver: zodResolver(registerSchema),
});
@ -96,27 +97,19 @@ const Register = ({ isCloud }: Props) => {
name: values.name,
});
// const { data, error } = await authClient.admin.createUser({
// name: values.name,
// email: values.email,
// password: values.password,
// role: "superAdmin",
// });
// consol/e.log(data, error);
// await mutateAsync({
// email: values.email.toLowerCase(),
// password: values.password,
// })
// .then(() => {
// toast.success("User registered successfuly", {
// duration: 2000,
// });
// if (!isCloud) {
// router.push("/");
// }
// })
// .catch((e) => e);
if (error) {
setIsError(true);
setError(error.message || "An error occurred");
} else {
toast.success("User registered successfuly", {
duration: 2000,
});
if (!isCloud) {
router.push("/");
} else {
setData(data);
}
}
};
return (
<div className="">
@ -138,15 +131,15 @@ const Register = ({ isCloud }: Props) => {
</CardDescription>
<div className="mx-auto w-full max-w-lg bg-transparent">
{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" />
<span className="text-sm text-red-600 dark:text-red-400">
{error?.message}
{error}
</span>
</div>
)}
{data?.type === "cloud" && (
<AlertBlock type="success" className="mx-4 my-2">
{isCloud && data && (
<AlertBlock type="success" className="my-2">
<span>
Registered successfully, please check your inbox or spam
folder to confirm your account.

View File

@ -77,7 +77,7 @@ export default function Home({ token }: Props) {
resetPasswordToken: token,
password: values.password,
})
.then((data) => {
.then((_data) => {
toast.success("Password reset successfully", {
duration: 2000,
});

View File

@ -43,13 +43,13 @@ type AuthResponse = {
};
export default function Home() {
const [temp, setTemp] = useState<AuthResponse>({
const [temp, _setTemp] = useState<AuthResponse>({
is2FAEnabled: false,
authId: "",
});
const { mutateAsync, isLoading, isError, error } =
api.auth.sendResetPasswordEmail.useMutation();
const router = useRouter();
const _router = useRouter();
const form = useForm<Login>({
defaultValues: {
email: "",
@ -65,7 +65,7 @@ export default function Home() {
await mutateAsync({
email: values.email,
})
.then((data) => {
.then((_data) => {
toast.success("Email sent", {
duration: 2000,
});
@ -150,7 +150,7 @@ export default function Home() {
Home.getLayout = (page: ReactElement) => {
return <OnboardingLayout>{page}</OnboardingLayout>;
};
export async function getServerSideProps(context: GetServerSidePropsContext) {
export async function getServerSideProps(_context: GetServerSidePropsContext) {
if (!IS_CLOUD) {
return {
redirect: {

View File

@ -33,7 +33,7 @@ import {
} from "../trpc";
export const authRouter = createTRPCRouter({
createAdmin: publicProcedure.mutation(async ({ ctx, input }) => {
createAdmin: publicProcedure.mutation(async ({ input }) => {
try {
if (!IS_CLOUD) {
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 {
const token = await getUserByToken(input.token);
const _token = await getUserByToken(input.token);
// if (token.isExpired) {
// throw new TRPCError({
// code: "BAD_REQUEST",
@ -103,7 +103,7 @@ export const authRouter = createTRPCRouter({
}
}),
login: publicProcedure.mutation(async ({ ctx, input }) => {
login: publicProcedure.mutation(async ({ input }) => {
try {
const auth = await findAuthByEmail(input.email);
@ -169,7 +169,7 @@ export const authRouter = createTRPCRouter({
}),
logout: protectedProcedure.mutation(async ({ ctx }) => {
const { req, res } = ctx;
const { req } = ctx;
const { session } = await validateRequest(req);
if (!session) return false;
@ -229,7 +229,7 @@ export const authRouter = createTRPCRouter({
message: "Password is incorrect",
});
}
const { req, res } = ctx;
const { req } = ctx;
const { session } = await validateRequest(req);
if (!session) return false;
@ -245,7 +245,7 @@ export const authRouter = createTRPCRouter({
return true;
}),
generateToken: protectedProcedure.mutation(async ({ ctx, input }) => {
generateToken: protectedProcedure.mutation(async ({ ctx }) => {
const auth = await findUserById(ctx.user.id);
console.log(auth);
@ -276,7 +276,7 @@ export const authRouter = createTRPCRouter({
email: z.string().min(1).email(),
}),
)
.mutation(async ({ ctx, input }) => {
.mutation(async ({ input }) => {
if (!IS_CLOUD) {
throw new TRPCError({
code: "NOT_FOUND",
@ -329,7 +329,7 @@ export const authRouter = createTRPCRouter({
password: z.string().min(1),
}),
)
.mutation(async ({ ctx, input }) => {
.mutation(async ({ input }) => {
if (!IS_CLOUD) {
throw new TRPCError({
code: "NOT_FOUND",
@ -373,7 +373,7 @@ export const authRouter = createTRPCRouter({
confirmationToken: z.string().min(1),
}),
)
.mutation(async ({ ctx, input }) => {
.mutation(async ({ input }) => {
if (!IS_CLOUD) {
throw new TRPCError({
code: "NOT_FOUND",

View File

@ -12,6 +12,7 @@ import {
mariadb,
mongo,
mysql,
organization,
postgres,
redis,
server,
@ -102,6 +103,18 @@ export const serverRouter = createTRPCRouter({
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 }) => {
const result = await db.query.server.findMany({
orderBy: desc(server.createdAt),

View File

@ -56,7 +56,7 @@ export const stripeRouter = createTRPCRouter({
});
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;
@ -78,7 +78,7 @@ export const stripeRouter = createTRPCRouter({
customer: stripeCustomerId,
}),
metadata: {
ownerId: user.id,
adminId: user.id,
},
allow_promotion_codes: true,
success_url: `${WEBSITE_URL}/dashboard/settings/servers?success=true`,
@ -88,7 +88,7 @@ export const stripeRouter = createTRPCRouter({
return { sessionId: session.id };
}),
createCustomerPortalSession: adminProcedure.mutation(async ({ ctx }) => {
const user = await findUserById(ctx.user.ownerId);
const user = await findUserById(ctx.user.id);
if (!user.stripeCustomerId) {
throw new TRPCError({

View File

@ -1,15 +1,10 @@
import bc from "bcrypt";
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
const connectionString = process.env.DATABASE_URL!;
const pg = postgres(connectionString, { max: 1 });
const db = drizzle(pg);
function password(txt: string) {
return bc.hashSync(txt, 10);
}
const _db = drizzle(pg);
async function seed() {
console.log("> Seed:", process.env.DATABASE_PATH, "\n");

View File

@ -6,7 +6,7 @@ export const isWSL = async () => {
const { stdout } = await execAsync("uname -r");
const isWSL = stdout.includes("microsoft");
return isWSL;
} catch (error) {
} catch (_error) {
return false;
}
};

View File

@ -50,8 +50,8 @@ export const setupDockerContainerTerminalWebSocketServer = (
throw new Error("No SSH key available for this server");
const conn = new Client();
let stdout = "";
let stderr = "";
let _stdout = "";
let _stderr = "";
conn
.once("ready", () => {
conn.exec(
@ -61,16 +61,16 @@ export const setupDockerContainerTerminalWebSocketServer = (
if (err) throw err;
stream
.on("close", (code: number, signal: string) => {
.on("close", (code: number, _signal: string) => {
ws.send(`\nContainer closed with code: ${code}\n`);
conn.end();
})
.on("data", (data: string) => {
stdout += data.toString();
_stdout += data.toString();
ws.send(data.toString());
})
.stderr.on("data", (data) => {
stderr += data.toString();
_stderr += data.toString();
ws.send(data.toString());
console.error("Error: ", data.toString());
});

View File

@ -32,7 +32,7 @@ export const setupDrawerLogsWebSocketServer = (
});
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);
if (!user || !session) {

View File

@ -103,7 +103,7 @@ export const setupDeploymentLogsWebSocketServer = (
ws.close();
});
}
} catch (error) {
} catch (_error) {
// @ts-ignore
// const errorMessage = error?.message as unknown as string;
// ws.send(errorMessage);

View File

@ -144,8 +144,8 @@ export const setupTerminalWebSocketServer = (
}
const conn = new Client();
let stdout = "";
let stderr = "";
let _stdout = "";
let _stderr = "";
ws.send("Connecting...\n");
@ -158,16 +158,16 @@ export const setupTerminalWebSocketServer = (
if (err) throw err;
stream
.on("close", (code: number, signal: string) => {
.on("close", (code: number, _signal: string) => {
ws.send(`\nContainer closed with code: ${code}\n`);
conn.end();
})
.on("data", (data: string) => {
stdout += data.toString();
_stdout += data.toString();
ws.send(data.toString());
})
.stderr.on("data", (data) => {
stderr += data.toString();
_stderr += data.toString();
ws.send(data.toString());
console.error("Error: ", data.toString());
});

View File

@ -7,7 +7,7 @@ import {
} from "../utils";
export function generate(schema: Schema): Template {
const mainServiceHash = generateHash(schema.projectName);
const _mainServiceHash = generateHash(schema.projectName);
const domains: DomainSchema[] = [
{

View File

@ -7,7 +7,7 @@ import {
} from "../utils";
export function generate(schema: Schema): Template {
const mainServiceHash = generateHash(schema.projectName);
const _mainServiceHash = generateHash(schema.projectName);
const mainDomain = generateRandomDomain(schema);
const domains: DomainSchema[] = [

View File

@ -1,6 +1,6 @@
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>"`];
return {

View File

@ -8,7 +8,7 @@ import {
export function generate(schema: Schema): Template {
const mainDomain = generateRandomDomain(schema);
const secretKeyBase = generateBase64(64);
const _secretKeyBase = generateBase64(64);
const domains: DomainSchema[] = [
{

View File

@ -11,7 +11,7 @@ export function generate(schema: Schema): Template {
const mainDomain = generateRandomDomain(schema);
const dbPassword = generatePassword();
const dbUser = "immich";
const appSecret = generateBase64(32);
const _appSecret = generateBase64(32);
const domains: DomainSchema[] = [
{

View File

@ -1,6 +1,6 @@
import type { Schema, Template } from "../utils";
export function generate(schema: Schema): Template {
export function generate(_schema: Schema): Template {
const mounts: Template["mounts"] = [
{
filePath: "init-mongo.sh",

View File

@ -28,9 +28,7 @@ export const certificates = pgTable("certificate", {
}),
});
export const certificatesRelations = relations(
certificates,
({ one, many }) => ({
export const certificatesRelations = relations(certificates, ({ one }) => ({
server: one(server, {
fields: [certificates.serverId],
references: [server.serverId],
@ -39,8 +37,7 @@ export const certificatesRelations = relations(
fields: [certificates.organizationId],
references: [organization.id],
}),
}),
);
}));
export const apiCreateCertificate = createInsertSchema(certificates, {
name: z.string().min(1),

View File

@ -29,7 +29,7 @@ export const gitProvider = pgTable("git_provider", {
.references(() => organization.id, { onDelete: "cascade" }),
});
export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
github: one(github, {
fields: [gitProvider.gitProviderId],
references: [github.gitProviderId],

View File

@ -32,7 +32,7 @@ export const registry = pgTable("registry", {
.references(() => organization.id, { onDelete: "cascade" }),
});
export const registryRelations = relations(registry, ({ one, many }) => ({
export const registryRelations = relations(registry, ({ many }) => ({
applications: many(applications),
}));

View File

@ -2,14 +2,12 @@ import type { IncomingMessage } from "node:http";
import * as bcrypt from "bcrypt";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import {
createAuthMiddleware,
organization,
twoFactor,
} from "better-auth/plugins";
import { organization, twoFactor } from "better-auth/plugins";
import { and, desc, eq } from "drizzle-orm";
import { db } from "../db";
import * as schema from "../db/schema";
import { sendVerificationEmail } from "../verification/send-verification-email";
import { IS_CLOUD } from "../constants";
export const auth = betterAuth({
database: drizzleAdapter(db, {
@ -27,9 +25,18 @@ export const auth = betterAuth({
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: {
enabled: true,
autoSignIn: !IS_CLOUD,
requireEmailVerification: IS_CLOUD,
password: {
async hash(password) {
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
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: newSession?.user?.id || "",
ownerId: user.id,
createdAt: new Date(),
})
.returning()
.then((res) => res[0]);
await db.insert(schema.member).values({
userId: newSession?.user?.id || "",
await tx.insert(schema.member).values({
userId: user.id,
organizationId: organization?.id || "",
role: "owner",
createdAt: new Date(),
});
});
}
}
}),
},
databaseHooks: {
},
},
session: {
create: {
before: async (session) => {
@ -106,7 +117,7 @@ export const auth = betterAuth({
plugins: [
twoFactor(),
organization({
async sendInvitationEmail(data, request) {
async sendInvitationEmail(data, _request) {
const inviteLink = `https://example.com/accept-invitation/${data.id}`;
// https://example.com/accept-invitation/8jlBi9Tb9isDb8mc8Sb85u1BaJYklKB2
// sendOrganizationInvitation({

View File

@ -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>;
// }

View File

@ -1 +0,0 @@
//

Some files were not shown because too many files have changed in this diff Show More