mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor: update invitation
This commit is contained in:
parent
4a1a14aeb4
commit
e7db0ccb70
@ -36,7 +36,7 @@ export const SearchCommand = () => {
|
||||
const router = useRouter();
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [search, setSearch] = React.useState("");
|
||||
const { data: session } = authClient.getSession();
|
||||
const { data: session } = authClient.useSession();
|
||||
const { data } = api.project.all.useQuery(undefined, {
|
||||
enabled: !!session,
|
||||
});
|
||||
|
@ -10,12 +10,14 @@ import {
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { api } from "@/utils/api";
|
||||
import { format } from "date-fns";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const AddGithubProvider = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||
const { data } = api.auth.get.useQuery();
|
||||
const [manifest, setManifest] = useState("");
|
||||
const [isOrganization, setIsOrganization] = useState(false);
|
||||
@ -25,7 +27,7 @@ export const AddGithubProvider = () => {
|
||||
const url = document.location.origin;
|
||||
const manifest = JSON.stringify(
|
||||
{
|
||||
redirect_url: `${origin}/api/providers/github/setup?authId=${data?.id}`,
|
||||
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id}`,
|
||||
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}`,
|
||||
url: origin,
|
||||
hook_attributes: {
|
||||
@ -93,8 +95,8 @@ export const AddGithubProvider = () => {
|
||||
<form
|
||||
action={
|
||||
isOrganization
|
||||
? `https://github.com/organizations/${organizationName}/settings/apps/new?state=gh_init:${data?.id}`
|
||||
: `https://github.com/settings/apps/new?state=gh_init:${data?.id}`
|
||||
? `https://github.com/organizations/${organizationName}/settings/apps/new?state=gh_init:${activeOrganization?.id}`
|
||||
: `https://github.com/settings/apps/new?state=gh_init:${activeOrganization?.id}`
|
||||
}
|
||||
method="post"
|
||||
>
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
@ -40,6 +41,7 @@ export const AddUser = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const utils = api.useUtils();
|
||||
|
||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||
const { mutateAsync, isError, error, isLoading } =
|
||||
api.admin.createUserInvitation.useMutation();
|
||||
|
||||
@ -54,17 +56,23 @@ export const AddUser = () => {
|
||||
}, [form, form.formState.isSubmitSuccessful, form.reset]);
|
||||
|
||||
const onSubmit = async (data: AddUser) => {
|
||||
await mutateAsync({
|
||||
const result = await authClient.organization.inviteMember({
|
||||
email: data.email.toLowerCase(),
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Invitation created");
|
||||
await utils.user.all.invalidate();
|
||||
setOpen(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error creating the invitation");
|
||||
role: "user",
|
||||
organizationId: activeOrganization?.id,
|
||||
});
|
||||
console.log(result);
|
||||
// await mutateAsync({
|
||||
// email: data.email.toLowerCase(),
|
||||
// })
|
||||
// .then(async () => {
|
||||
// toast.success("Invitation created");
|
||||
// await utils.user.all.invalidate();
|
||||
// setOpen(false);
|
||||
// })
|
||||
// .catch(() => {
|
||||
// toast.error("Error creating the invitation");
|
||||
// });
|
||||
};
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
|
@ -2,6 +2,6 @@ import { organizationClient } from "better-auth/client/plugins";
|
||||
import { createAuthClient } from "better-auth/react";
|
||||
|
||||
export const authClient = createAuthClient({
|
||||
baseURL: "http://localhost:3000", // the base url of your auth server
|
||||
// baseURL: "http://localhost:3000", // the base url of your auth server
|
||||
plugins: [organizationClient()],
|
||||
});
|
||||
|
30
apps/dokploy/pages/accept-invitation/[accept-invitation].tsx
Normal file
30
apps/dokploy/pages/accept-invitation/[accept-invitation].tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
export const AcceptInvitation = () => {
|
||||
const { query } = useRouter();
|
||||
|
||||
const invitationId = query["accept-invitation"];
|
||||
|
||||
// const { data: organization } = api.organization.getById.useQuery({
|
||||
// id: id as string
|
||||
// })
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const result = await authClient.organization.acceptInvitation({
|
||||
invitationId: invitationId as string,
|
||||
});
|
||||
console.log(result);
|
||||
}}
|
||||
>
|
||||
Accept Invitation
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AcceptInvitation;
|
@ -1,10 +1,12 @@
|
||||
import { db } from "@/server/db";
|
||||
import { github } from "@/server/db/schema";
|
||||
import {
|
||||
auth,
|
||||
createGithub,
|
||||
findAdminByAuthId,
|
||||
findAuthById,
|
||||
findUserByAuthId,
|
||||
findUserById,
|
||||
} from "@dokploy/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
@ -28,7 +30,7 @@ export default async function handler(
|
||||
return res.status(400).json({ error: "Missing code parameter" });
|
||||
}
|
||||
const [action, value] = state?.split(":");
|
||||
// Value could be the authId or the githubProviderId
|
||||
// Value could be the organizationId or the githubProviderId
|
||||
|
||||
if (action === "gh_init") {
|
||||
const octokit = new Octokit({});
|
||||
@ -39,17 +41,6 @@ export default async function handler(
|
||||
},
|
||||
);
|
||||
|
||||
const auth = await findAuthById(value as string);
|
||||
|
||||
let adminId = "";
|
||||
if (auth.role === "owner") {
|
||||
const admin = await findAdminByAuthId(auth.id);
|
||||
adminId = admin.adminId;
|
||||
} else {
|
||||
const user = await findUserByAuthId(auth.id);
|
||||
adminId = user.adminId;
|
||||
}
|
||||
|
||||
await createGithub(
|
||||
{
|
||||
name: data.name,
|
||||
@ -60,7 +51,7 @@ export default async function handler(
|
||||
githubWebhookSecret: data.webhook_secret,
|
||||
githubPrivateKey: data.pem,
|
||||
},
|
||||
adminId,
|
||||
value as string,
|
||||
);
|
||||
} else if (action === "gh_setup") {
|
||||
await db
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
apiUpdateBitbucket,
|
||||
} from "@/server/db/schema";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
createBitbucket,
|
||||
findBitbucketById,
|
||||
getBitbucketBranches,
|
||||
@ -37,11 +36,9 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this bitbucket provider",
|
||||
@ -59,14 +56,11 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
},
|
||||
});
|
||||
|
||||
if (IS_CLOUD) {
|
||||
// TODO: mAyBe a rEfaCtoR 🤫
|
||||
result = result.filter(
|
||||
(provider) =>
|
||||
provider.gitProvider.organizationId ===
|
||||
ctx.session.activeOrganizationId,
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}),
|
||||
|
||||
@ -75,11 +69,9 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this bitbucket provider",
|
||||
@ -94,11 +86,9 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
input.bitbucketId || "",
|
||||
);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this bitbucket provider",
|
||||
@ -112,11 +102,9 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
try {
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this bitbucket provider",
|
||||
@ -137,11 +125,9 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this bitbucket provider",
|
||||
@ -149,7 +135,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateBitbucket(input.bitbucketId, {
|
||||
...input,
|
||||
userId: ctx.user.ownerId,
|
||||
organizationId: ctx.session.activeOrganizationId,
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
apiUpdateGithub,
|
||||
} from "@/server/db/schema";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
findGithubById,
|
||||
getGithubBranches,
|
||||
getGithubRepositories,
|
||||
@ -24,7 +23,6 @@ export const githubRouter = createTRPCRouter({
|
||||
githubProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this github provider",
|
||||
@ -40,7 +38,6 @@ export const githubRouter = createTRPCRouter({
|
||||
githubProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this github provider",
|
||||
@ -71,14 +68,11 @@ export const githubRouter = createTRPCRouter({
|
||||
},
|
||||
});
|
||||
|
||||
if (IS_CLOUD) {
|
||||
// TODO: mAyBe a rEfaCtoR 🤫
|
||||
result = result.filter(
|
||||
(provider) =>
|
||||
provider.gitProvider.organizationId ===
|
||||
ctx.session.activeOrganizationId,
|
||||
);
|
||||
}
|
||||
|
||||
const filtered = result
|
||||
.filter((provider) => haveGithubRequirements(provider))
|
||||
@ -100,11 +94,9 @@ export const githubRouter = createTRPCRouter({
|
||||
try {
|
||||
const githubProvider = await findGithubById(input.githubId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
githubProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this github provider",
|
||||
@ -124,11 +116,9 @@ export const githubRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const githubProvider = await findGithubById(input.githubId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
githubProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this github provider",
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
|
||||
import { db } from "@/server/db";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
createGitlab,
|
||||
findGitlabById,
|
||||
getGitlabBranches,
|
||||
@ -43,7 +42,6 @@ export const gitlabRouter = createTRPCRouter({
|
||||
gitlabProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this Gitlab provider",
|
||||
@ -58,14 +56,11 @@ export const gitlabRouter = createTRPCRouter({
|
||||
},
|
||||
});
|
||||
|
||||
if (IS_CLOUD) {
|
||||
// TODO: mAyBe a rEfaCtoR 🤫
|
||||
result = result.filter(
|
||||
(provider) =>
|
||||
provider.gitProvider.organizationId ===
|
||||
ctx.session.activeOrganizationId,
|
||||
);
|
||||
}
|
||||
const filtered = result
|
||||
.filter((provider) => haveGitlabRequirements(provider))
|
||||
.map((provider) => {
|
||||
@ -87,7 +82,6 @@ export const gitlabRouter = createTRPCRouter({
|
||||
gitlabProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this Gitlab provider",
|
||||
@ -104,7 +98,6 @@ export const gitlabRouter = createTRPCRouter({
|
||||
gitlabProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this Gitlab provider",
|
||||
@ -121,7 +114,6 @@ export const gitlabRouter = createTRPCRouter({
|
||||
gitlabProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this Gitlab provider",
|
||||
@ -145,7 +137,6 @@ export const gitlabRouter = createTRPCRouter({
|
||||
gitlabProvider.gitProvider.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this Gitlab provider",
|
||||
|
@ -71,7 +71,7 @@ export const projectRouter = createTRPCRouter({
|
||||
.input(apiFindOneProject)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "member") {
|
||||
const { accessedServices } = await findUserByAuthId(ctx.user.id);
|
||||
const { accessedServices } = await findUserById(ctx.user.id);
|
||||
|
||||
await checkProjectAccess(ctx.user.id, "access", input.projectId);
|
||||
|
||||
|
@ -4,8 +4,8 @@ import { db } from "@dokploy/server/db";
|
||||
import { member } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
|
||||
import { z } from "zod";
|
||||
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
|
||||
export const userRouter = createTRPCRouter({
|
||||
all: adminProcedure.query(async ({ ctx }) => {
|
||||
return await db.query.member.findMany({
|
||||
|
@ -34,14 +34,14 @@ void app.prepare().then(async () => {
|
||||
});
|
||||
|
||||
// WEBSOCKET
|
||||
// setupDrawerLogsWebSocketServer(server);
|
||||
// setupDeploymentLogsWebSocketServer(server);
|
||||
// setupDockerContainerLogsWebSocketServer(server);
|
||||
// setupDockerContainerTerminalWebSocketServer(server);
|
||||
// setupTerminalWebSocketServer(server);
|
||||
// if (!IS_CLOUD) {
|
||||
// setupDockerStatsMonitoringSocketServer(server);
|
||||
// }
|
||||
setupDrawerLogsWebSocketServer(server);
|
||||
setupDeploymentLogsWebSocketServer(server);
|
||||
setupDockerContainerLogsWebSocketServer(server);
|
||||
setupDockerContainerTerminalWebSocketServer(server);
|
||||
setupTerminalWebSocketServer(server);
|
||||
if (!IS_CLOUD) {
|
||||
setupDockerStatsMonitoringSocketServer(server);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === "production" && !IS_CLOUD) {
|
||||
setupDirectories();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type http from "node:http";
|
||||
import { findServerById, validateWebSocketRequest } from "@dokploy/server";
|
||||
import { findServerById, validateRequest } from "@dokploy/server";
|
||||
import { spawn } from "node-pty";
|
||||
import { Client } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
@ -35,7 +35,7 @@ export const setupDockerContainerLogsWebSocketServer = (
|
||||
const since = url.searchParams.get("since");
|
||||
const serverId = url.searchParams.get("serverId");
|
||||
const runType = url.searchParams.get("runType");
|
||||
const { user, session } = await validateWebSocketRequest(req);
|
||||
const { user, session } = await validateRequest(req);
|
||||
|
||||
if (!containerId) {
|
||||
ws.close(4000, "containerId no provided");
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type http from "node:http";
|
||||
import { findServerById, validateWebSocketRequest } from "@dokploy/server";
|
||||
import { findServerById, validateRequest } from "@dokploy/server";
|
||||
import { spawn } from "node-pty";
|
||||
import { Client } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
@ -32,7 +32,7 @@ export const setupDockerContainerTerminalWebSocketServer = (
|
||||
const containerId = url.searchParams.get("containerId");
|
||||
const activeWay = url.searchParams.get("activeWay");
|
||||
const serverId = url.searchParams.get("serverId");
|
||||
const { user, session } = await validateWebSocketRequest(req);
|
||||
const { user, session } = await validateRequest(req);
|
||||
|
||||
if (!containerId) {
|
||||
ws.close(4000, "containerId no provided");
|
||||
|
@ -4,7 +4,7 @@ import {
|
||||
execAsync,
|
||||
getLastAdvancedStatsFile,
|
||||
recordAdvancedStats,
|
||||
validateWebSocketRequest,
|
||||
validateRequest,
|
||||
} from "@dokploy/server";
|
||||
import { WebSocketServer } from "ws";
|
||||
|
||||
@ -36,7 +36,7 @@ export const setupDockerStatsMonitoringSocketServer = (
|
||||
| "application"
|
||||
| "stack"
|
||||
| "docker-compose";
|
||||
const { user, session } = await validateWebSocketRequest(req);
|
||||
const { user, session } = await validateRequest(req);
|
||||
|
||||
if (!appName) {
|
||||
ws.close(4000, "appName no provided");
|
||||
|
@ -3,6 +3,7 @@ import { applyWSSHandler } from "@trpc/server/adapters/ws";
|
||||
import { WebSocketServer } from "ws";
|
||||
import { appRouter } from "../api/root";
|
||||
import { createTRPCContext } from "../api/trpc";
|
||||
import { validateRequest } from "@dokploy/server/index";
|
||||
|
||||
export const setupDrawerLogsWebSocketServer = (
|
||||
server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>,
|
||||
@ -32,5 +33,11 @@ export const setupDrawerLogsWebSocketServer = (
|
||||
|
||||
wssTerm.on("connection", async (ws, req) => {
|
||||
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
||||
const { user, session } = await validateRequest(req);
|
||||
|
||||
if (!user || !session) {
|
||||
ws.close();
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import type http from "node:http";
|
||||
import { findServerById, validateWebSocketRequest } from "@dokploy/server";
|
||||
import { findServerById, validateRequest } from "@dokploy/server";
|
||||
import { Client } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
|
||||
@ -29,7 +29,7 @@ export const setupDeploymentLogsWebSocketServer = (
|
||||
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
||||
const logPath = url.searchParams.get("logPath");
|
||||
const serverId = url.searchParams.get("serverId");
|
||||
const { user, session } = await validateWebSocketRequest(req);
|
||||
const { user, session } = await validateRequest(req);
|
||||
|
||||
if (!logPath) {
|
||||
console.log("logPath no provided");
|
||||
|
@ -1,9 +1,5 @@
|
||||
import type http from "node:http";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
findServerById,
|
||||
validateWebSocketRequest,
|
||||
} from "@dokploy/server";
|
||||
import { IS_CLOUD, findServerById, validateRequest } from "@dokploy/server";
|
||||
import { publicIpv4, publicIpv6 } from "public-ip";
|
||||
import { Client, type ConnectConfig } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
@ -71,7 +67,7 @@ export const setupTerminalWebSocketServer = (
|
||||
wssTerm.on("connection", async (ws, req) => {
|
||||
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
||||
const serverId = url.searchParams.get("serverId");
|
||||
const { user, session } = await validateWebSocketRequest(req);
|
||||
const { user, session } = await validateRequest(req);
|
||||
if (!user || !session || !serverId) {
|
||||
ws.close();
|
||||
return;
|
||||
|
@ -1,6 +1,3 @@
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { findAdminByAuthId } from "@dokploy/server/services/admin";
|
||||
import { findUserByAuthId } from "@dokploy/server/services/user";
|
||||
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle";
|
||||
import { TimeSpan } from "lucia";
|
||||
import { Lucia } from "lucia/dist/core.js";
|
||||
@ -42,78 +39,3 @@ export type ReturnValidateToken = Promise<{
|
||||
user: (User & { authId: string; adminId: string }) | null;
|
||||
session: Session | null;
|
||||
}>;
|
||||
|
||||
export async function validateRequest(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
): ReturnValidateToken {
|
||||
console.log(session);
|
||||
const sessionId = lucia.readSessionCookie(req.headers.cookie ?? "");
|
||||
|
||||
if (!sessionId) {
|
||||
return {
|
||||
user: null,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
const result = await lucia.validateSession(sessionId);
|
||||
if (result?.session?.fresh) {
|
||||
res.appendHeader(
|
||||
"Set-Cookie",
|
||||
lucia.createSessionCookie(result.session.id).serialize(),
|
||||
);
|
||||
}
|
||||
if (!result.session) {
|
||||
res.appendHeader(
|
||||
"Set-Cookie",
|
||||
lucia.createBlankSessionCookie().serialize(),
|
||||
);
|
||||
}
|
||||
if (result.user) {
|
||||
try {
|
||||
if (result.user?.rol === "owner") {
|
||||
const admin = await findAdminByAuthId(result.user.id);
|
||||
result.user.adminId = admin.adminId;
|
||||
} else if (result.user?.rol === "member") {
|
||||
const userResult = await findUserByAuthId(result.user.id);
|
||||
result.user.adminId = userResult.adminId;
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
user: null,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
session: result.session,
|
||||
...((result.user && {
|
||||
user: {
|
||||
authId: result.user.id,
|
||||
email: result.user.email,
|
||||
rol: result.user.rol,
|
||||
id: result.user.id,
|
||||
secret: result.user.secret,
|
||||
adminId: result.user.adminId,
|
||||
},
|
||||
}) || {
|
||||
user: null,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export async function validateWebSocketRequest(
|
||||
req: IncomingMessage,
|
||||
): Promise<{ user: User; session: Session } | { user: null; session: null }> {
|
||||
const sessionId = lucia.readSessionCookie(req.headers.cookie ?? "");
|
||||
|
||||
if (!sessionId) {
|
||||
return {
|
||||
user: null,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
const result = await lucia.validateSession(sessionId);
|
||||
return result;
|
||||
}
|
||||
|
@ -21,79 +21,79 @@ export const luciaToken = new Lucia(adapter, {
|
||||
},
|
||||
});
|
||||
|
||||
export const validateBearerToken = async (
|
||||
req: IncomingMessage,
|
||||
): ReturnValidateToken => {
|
||||
const authorizationHeader = req.headers.authorization;
|
||||
const sessionId = luciaToken.readBearerToken(authorizationHeader ?? "");
|
||||
if (!sessionId) {
|
||||
return {
|
||||
user: null,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
const result = await luciaToken.validateSession(sessionId);
|
||||
// export const validateBearerToken = async (
|
||||
// req: IncomingMessage,
|
||||
// ): ReturnValidateToken => {
|
||||
// const authorizationHeader = req.headers.authorization;
|
||||
// const sessionId = luciaToken.readBearerToken(authorizationHeader ?? "");
|
||||
// if (!sessionId) {
|
||||
// return {
|
||||
// user: null,
|
||||
// session: null,
|
||||
// };
|
||||
// }
|
||||
// const result = await luciaToken.validateSession(sessionId);
|
||||
|
||||
if (result.user) {
|
||||
if (result.user?.rol === "owner") {
|
||||
const admin = await findAdminByAuthId(result.user.id);
|
||||
result.user.adminId = admin.adminId;
|
||||
} else if (result.user?.rol === "member") {
|
||||
const userResult = await findUserByAuthId(result.user.id);
|
||||
result.user.adminId = userResult.adminId;
|
||||
}
|
||||
}
|
||||
return {
|
||||
session: result.session,
|
||||
...((result.user && {
|
||||
user: {
|
||||
adminId: result.user.adminId,
|
||||
authId: result.user.id,
|
||||
email: result.user.email,
|
||||
rol: result.user.rol,
|
||||
id: result.user.id,
|
||||
secret: result.user.secret,
|
||||
},
|
||||
}) || {
|
||||
user: null,
|
||||
}),
|
||||
};
|
||||
};
|
||||
// if (result.user) {
|
||||
// if (result.user?.rol === "owner") {
|
||||
// const admin = await findAdminByAuthId(result.user.id);
|
||||
// result.user.adminId = admin.adminId;
|
||||
// } else if (result.user?.rol === "member") {
|
||||
// const userResult = await findUserByAuthId(result.user.id);
|
||||
// result.user.adminId = userResult.adminId;
|
||||
// }
|
||||
// }
|
||||
// return {
|
||||
// session: result.session,
|
||||
// ...((result.user && {
|
||||
// user: {
|
||||
// adminId: result.user.adminId,
|
||||
// authId: result.user.id,
|
||||
// email: result.user.email,
|
||||
// rol: result.user.rol,
|
||||
// id: result.user.id,
|
||||
// secret: result.user.secret,
|
||||
// },
|
||||
// }) || {
|
||||
// user: null,
|
||||
// }),
|
||||
// };
|
||||
// };
|
||||
|
||||
export const validateBearerTokenAPI = async (
|
||||
authorizationHeader: string,
|
||||
): ReturnValidateToken => {
|
||||
const sessionId = luciaToken.readBearerToken(authorizationHeader ?? "");
|
||||
if (!sessionId) {
|
||||
return {
|
||||
user: null,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
const result = await luciaToken.validateSession(sessionId);
|
||||
// export const validateBearerTokenAPI = async (
|
||||
// authorizationHeader: string,
|
||||
// ): ReturnValidateToken => {
|
||||
// const sessionId = luciaToken.readBearerToken(authorizationHeader ?? "");
|
||||
// if (!sessionId) {
|
||||
// return {
|
||||
// user: null,
|
||||
// session: null,
|
||||
// };
|
||||
// }
|
||||
// const result = await luciaToken.validateSession(sessionId);
|
||||
|
||||
if (result.user) {
|
||||
if (result.user?.rol === "owner") {
|
||||
const admin = await findAdminByAuthId(result.user.id);
|
||||
result.user.adminId = admin.adminId;
|
||||
} else if (result.user?.rol === "member") {
|
||||
const userResult = await findUserByAuthId(result.user.id);
|
||||
result.user.adminId = userResult.adminId;
|
||||
}
|
||||
}
|
||||
return {
|
||||
session: result.session,
|
||||
...((result.user && {
|
||||
user: {
|
||||
adminId: result.user.adminId,
|
||||
authId: result.user.id,
|
||||
email: result.user.email,
|
||||
rol: result.user.rol,
|
||||
id: result.user.id,
|
||||
secret: result.user.secret,
|
||||
},
|
||||
}) || {
|
||||
user: null,
|
||||
}),
|
||||
};
|
||||
};
|
||||
// if (result.user) {
|
||||
// if (result.user?.rol === "owner") {
|
||||
// const admin = await findAdminByAuthId(result.user.id);
|
||||
// result.user.adminId = admin.adminId;
|
||||
// } else if (result.user?.rol === "member") {
|
||||
// const userResult = await findUserByAuthId(result.user.id);
|
||||
// result.user.adminId = userResult.adminId;
|
||||
// }
|
||||
// }
|
||||
// return {
|
||||
// session: result.session,
|
||||
// ...((result.user && {
|
||||
// user: {
|
||||
// adminId: result.user.adminId,
|
||||
// authId: result.user.id,
|
||||
// email: result.user.email,
|
||||
// rol: result.user.rol,
|
||||
// id: result.user.id,
|
||||
// secret: result.user.secret,
|
||||
// },
|
||||
// }) || {
|
||||
// user: null,
|
||||
// }),
|
||||
// };
|
||||
// };
|
||||
|
@ -84,7 +84,22 @@ export const auth = betterAuth({
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [organization()],
|
||||
plugins: [
|
||||
organization({
|
||||
async sendInvitationEmail(data, request) {
|
||||
const inviteLink = `https://example.com/accept-invitation/${data.id}`;
|
||||
// https://example.com/accept-invitation/8jlBi9Tb9isDb8mc8Sb85u1BaJYklKB2
|
||||
// sendOrganizationInvitation({
|
||||
// email: data.email,
|
||||
// invitedByUsername: data.inviter.user.name,
|
||||
// invitedByEmail: data.inviter.user.email,
|
||||
// teamName: data.organization.name,
|
||||
// inviteLink
|
||||
// })
|
||||
console.log("Invitation link", inviteLink);
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const validateRequest = async (request: IncomingMessage) => {
|
||||
|
@ -185,11 +185,11 @@ export const deployApplication = async ({
|
||||
});
|
||||
|
||||
try {
|
||||
const admin = await findUserById(application.project.userId);
|
||||
// const admin = await findUserById(application.project.userId);
|
||||
|
||||
if (admin.cleanupCacheApplications) {
|
||||
await cleanupFullDocker(application?.serverId);
|
||||
}
|
||||
// if (admin.cleanupCacheApplications) {
|
||||
// await cleanupFullDocker(application?.serverId);
|
||||
// }
|
||||
|
||||
if (application.sourceType === "github") {
|
||||
await cloneGithubRepository({
|
||||
@ -220,7 +220,7 @@ export const deployApplication = async ({
|
||||
applicationName: application.name,
|
||||
applicationType: "application",
|
||||
buildLink,
|
||||
userId: application.project.userId,
|
||||
organizationId: application.project.organizationId,
|
||||
domains: application.domains,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -233,7 +233,7 @@ export const deployApplication = async ({
|
||||
// @ts-ignore
|
||||
errorMessage: error?.message || "Error building",
|
||||
buildLink,
|
||||
userId: application.project.userId,
|
||||
organizationId: application.project.organizationId,
|
||||
});
|
||||
|
||||
throw error;
|
||||
@ -260,11 +260,11 @@ export const rebuildApplication = async ({
|
||||
});
|
||||
|
||||
try {
|
||||
const admin = await findUserById(application.project.userId);
|
||||
// const admin = await findUserById(application.project.userId);
|
||||
|
||||
if (admin.cleanupCacheApplications) {
|
||||
await cleanupFullDocker(application?.serverId);
|
||||
}
|
||||
// if (admin.cleanupCacheApplications) {
|
||||
// await cleanupFullDocker(application?.serverId);
|
||||
// }
|
||||
if (application.sourceType === "github") {
|
||||
await buildApplication(application, deployment.logPath);
|
||||
} else if (application.sourceType === "gitlab") {
|
||||
@ -309,11 +309,11 @@ export const deployRemoteApplication = async ({
|
||||
|
||||
try {
|
||||
if (application.serverId) {
|
||||
const admin = await findUserById(application.project.userId);
|
||||
// const admin = await findUserById(application.project.userId);
|
||||
|
||||
if (admin.cleanupCacheApplications) {
|
||||
await cleanupFullDocker(application?.serverId);
|
||||
}
|
||||
// if (admin.cleanupCacheApplications) {
|
||||
// await cleanupFullDocker(application?.serverId);
|
||||
// }
|
||||
let command = "set -e;";
|
||||
if (application.sourceType === "github") {
|
||||
command += await getGithubCloneCommand({
|
||||
@ -352,7 +352,7 @@ export const deployRemoteApplication = async ({
|
||||
applicationName: application.name,
|
||||
applicationType: "application",
|
||||
buildLink,
|
||||
userId: application.project.userId,
|
||||
organizationId: application.project.organizationId,
|
||||
domains: application.domains,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -376,7 +376,7 @@ export const deployRemoteApplication = async ({
|
||||
// @ts-ignore
|
||||
errorMessage: error?.message || "Error building",
|
||||
buildLink,
|
||||
userId: application.project.userId,
|
||||
organizationId: application.project.organizationId,
|
||||
});
|
||||
|
||||
throw error;
|
||||
@ -454,11 +454,11 @@ export const deployPreviewApplication = async ({
|
||||
application.env = `${application.previewEnv}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain}`;
|
||||
application.buildArgs = application.previewBuildArgs;
|
||||
|
||||
const admin = await findUserById(application.project.userId);
|
||||
// const admin = await findUserById(application.project.userId);
|
||||
|
||||
if (admin.cleanupCacheOnPreviews) {
|
||||
await cleanupFullDocker(application?.serverId);
|
||||
}
|
||||
// if (admin.cleanupCacheOnPreviews) {
|
||||
// await cleanupFullDocker(application?.serverId);
|
||||
// }
|
||||
|
||||
if (application.sourceType === "github") {
|
||||
await cloneGithubRepository({
|
||||
@ -568,11 +568,11 @@ export const deployRemotePreviewApplication = async ({
|
||||
application.buildArgs = application.previewBuildArgs;
|
||||
|
||||
if (application.serverId) {
|
||||
const admin = await findUserById(application.project.userId);
|
||||
// const admin = await findUserById(application.project.userId);
|
||||
|
||||
if (admin.cleanupCacheOnPreviews) {
|
||||
await cleanupFullDocker(application?.serverId);
|
||||
}
|
||||
// if (admin.cleanupCacheOnPreviews) {
|
||||
// await cleanupFullDocker(application?.serverId);
|
||||
// }
|
||||
let command = "set -e;";
|
||||
if (application.sourceType === "github") {
|
||||
command += await getGithubCloneCommand({
|
||||
@ -637,11 +637,11 @@ export const rebuildRemoteApplication = async ({
|
||||
|
||||
try {
|
||||
if (application.serverId) {
|
||||
const admin = await findUserById(application.project.userId);
|
||||
// const admin = await findUserById(application.project.userId);
|
||||
|
||||
if (admin.cleanupCacheApplications) {
|
||||
await cleanupFullDocker(application?.serverId);
|
||||
}
|
||||
// if (admin.cleanupCacheApplications) {
|
||||
// await cleanupFullDocker(application?.serverId);
|
||||
// }
|
||||
if (application.sourceType !== "docker") {
|
||||
let command = "set -e;";
|
||||
command += getBuildCommand(application, deployment.logPath);
|
||||
|
@ -217,10 +217,10 @@ export const deployCompose = async ({
|
||||
});
|
||||
|
||||
try {
|
||||
const admin = await findUserById(compose.project.userId);
|
||||
if (admin.cleanupCacheOnCompose) {
|
||||
await cleanupFullDocker(compose?.serverId);
|
||||
}
|
||||
// const admin = await findUserById(compose.project.userId);
|
||||
// if (admin.cleanupCacheOnCompose) {
|
||||
// await cleanupFullDocker(compose?.serverId);
|
||||
// }
|
||||
if (compose.sourceType === "github") {
|
||||
await cloneGithubRepository({
|
||||
...compose,
|
||||
@ -247,7 +247,7 @@ export const deployCompose = async ({
|
||||
applicationName: compose.name,
|
||||
applicationType: "compose",
|
||||
buildLink,
|
||||
userId: compose.project.userId,
|
||||
organizationId: compose.project.organizationId,
|
||||
domains: compose.domains,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -262,7 +262,7 @@ export const deployCompose = async ({
|
||||
// @ts-ignore
|
||||
errorMessage: error?.message || "Error building",
|
||||
buildLink,
|
||||
userId: compose.project.userId,
|
||||
organizationId: compose.project.organizationId,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@ -286,10 +286,10 @@ export const rebuildCompose = async ({
|
||||
});
|
||||
|
||||
try {
|
||||
const admin = await findUserById(compose.project.userId);
|
||||
if (admin.cleanupCacheOnCompose) {
|
||||
await cleanupFullDocker(compose?.serverId);
|
||||
}
|
||||
// const admin = await findUserById(compose.project.userId);
|
||||
// if (admin.cleanupCacheOnCompose) {
|
||||
// await cleanupFullDocker(compose?.serverId);
|
||||
// }
|
||||
if (compose.serverId) {
|
||||
await getBuildComposeCommand(compose, deployment.logPath);
|
||||
} else {
|
||||
@ -332,10 +332,10 @@ export const deployRemoteCompose = async ({
|
||||
});
|
||||
try {
|
||||
if (compose.serverId) {
|
||||
const admin = await findUserById(compose.project.userId);
|
||||
if (admin.cleanupCacheOnCompose) {
|
||||
await cleanupFullDocker(compose?.serverId);
|
||||
}
|
||||
// const admin = await findUserById(compose.project.userId);
|
||||
// if (admin.cleanupCacheOnCompose) {
|
||||
// await cleanupFullDocker(compose?.serverId);
|
||||
// }
|
||||
let command = "set -e;";
|
||||
|
||||
if (compose.sourceType === "github") {
|
||||
@ -381,7 +381,7 @@ export const deployRemoteCompose = async ({
|
||||
applicationName: compose.name,
|
||||
applicationType: "compose",
|
||||
buildLink,
|
||||
userId: compose.project.userId,
|
||||
organizationId: compose.project.organizationId,
|
||||
domains: compose.domains,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -406,7 +406,7 @@ export const deployRemoteCompose = async ({
|
||||
// @ts-ignore
|
||||
errorMessage: error?.message || "Error building",
|
||||
buildLink,
|
||||
userId: compose.project.userId,
|
||||
organizationId: compose.project.organizationId,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@ -430,10 +430,10 @@ export const rebuildRemoteCompose = async ({
|
||||
});
|
||||
|
||||
try {
|
||||
const admin = await findUserById(compose.project.userId);
|
||||
if (admin.cleanupCacheOnCompose) {
|
||||
await cleanupFullDocker(compose?.serverId);
|
||||
}
|
||||
// const admin = await findUserById(compose.project.userId);
|
||||
// if (admin.cleanupCacheOnCompose) {
|
||||
// await cleanupFullDocker(compose?.serverId);
|
||||
// }
|
||||
if (compose.serverId) {
|
||||
await getBuildComposeCommand(compose, deployment.logPath);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreatePreviewDeployment,
|
||||
deployments,
|
||||
organization,
|
||||
previewDeployments,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
@ -154,11 +155,14 @@ export const createPreviewDeployment = async (
|
||||
const application = await findApplicationById(schema.applicationId);
|
||||
const appName = `preview-${application.appName}-${generatePassword(6)}`;
|
||||
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(organization.id, application.project.organizationId),
|
||||
});
|
||||
const generateDomain = await generateWildcardDomain(
|
||||
application.previewWildcard || "*.traefik.me",
|
||||
appName,
|
||||
application.server?.ipAddress || "",
|
||||
application.project.userId,
|
||||
org?.ownerId || "",
|
||||
);
|
||||
|
||||
const octokit = authGithub(application?.github as Github);
|
||||
|
@ -5,8 +5,6 @@ import {
|
||||
execAsync,
|
||||
execAsyncRemote,
|
||||
} from "@dokploy/server/utils/process/execAsync";
|
||||
import { findAdminById } from "./admin";
|
||||
// import packageInfo from "../../../package.json";
|
||||
|
||||
export interface IUpdateData {
|
||||
latestVersion: string | null;
|
||||
|
@ -20,17 +20,17 @@ export type User = typeof users_temp.$inferSelect;
|
||||
// };
|
||||
|
||||
export const findUserByAuthId = async (authId: string) => {
|
||||
const userR = await db.query.user.findFirst({
|
||||
where: eq(user.id, authId),
|
||||
with: {},
|
||||
});
|
||||
if (!userR) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "User not found",
|
||||
});
|
||||
}
|
||||
return userR;
|
||||
// const userR = await db.query.user.findFirst({
|
||||
// where: eq(user.id, authId),
|
||||
// with: {},
|
||||
// });
|
||||
// if (!userR) {
|
||||
// throw new TRPCError({
|
||||
// code: "NOT_FOUND",
|
||||
// message: "User not found",
|
||||
// });
|
||||
// }
|
||||
// return userR;
|
||||
};
|
||||
|
||||
export const findUsers = async (adminId: string) => {
|
||||
|
@ -18,7 +18,7 @@ interface Props {
|
||||
applicationType: string;
|
||||
errorMessage: string;
|
||||
buildLink: string;
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
}
|
||||
|
||||
export const sendBuildErrorNotifications = async ({
|
||||
@ -27,14 +27,14 @@ export const sendBuildErrorNotifications = async ({
|
||||
applicationType,
|
||||
errorMessage,
|
||||
buildLink,
|
||||
userId,
|
||||
organizationId,
|
||||
}: Props) => {
|
||||
const date = new Date();
|
||||
const unixDate = ~~(Number(date) / 1000);
|
||||
const notificationList = await db.query.notifications.findMany({
|
||||
where: and(
|
||||
eq(notifications.appBuildError, true),
|
||||
eq(notifications.userId, userId),
|
||||
eq(notifications.organizationId, organizationId),
|
||||
),
|
||||
with: {
|
||||
email: true,
|
||||
|
@ -18,7 +18,7 @@ interface Props {
|
||||
applicationName: string;
|
||||
applicationType: string;
|
||||
buildLink: string;
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
domains: Domain[];
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ export const sendBuildSuccessNotifications = async ({
|
||||
applicationName,
|
||||
applicationType,
|
||||
buildLink,
|
||||
userId,
|
||||
organizationId,
|
||||
domains,
|
||||
}: Props) => {
|
||||
const date = new Date();
|
||||
@ -35,7 +35,7 @@ export const sendBuildSuccessNotifications = async ({
|
||||
const notificationList = await db.query.notifications.findMany({
|
||||
where: and(
|
||||
eq(notifications.appDeploy, true),
|
||||
eq(notifications.userId, userId),
|
||||
eq(notifications.organizationId, organizationId),
|
||||
),
|
||||
with: {
|
||||
email: true,
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
} from "./utils";
|
||||
|
||||
export const sendDockerCleanupNotifications = async (
|
||||
userId: string,
|
||||
organizationId: string,
|
||||
message = "Docker cleanup for dokploy",
|
||||
) => {
|
||||
const date = new Date();
|
||||
@ -21,7 +21,7 @@ export const sendDockerCleanupNotifications = async (
|
||||
const notificationList = await db.query.notifications.findMany({
|
||||
where: and(
|
||||
eq(notifications.dockerCleanup, true),
|
||||
eq(notifications.userId, userId),
|
||||
eq(notifications.organizationId, organizationId),
|
||||
),
|
||||
with: {
|
||||
email: true,
|
||||
|
Loading…
Reference in New Issue
Block a user