mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Compare commits
26 Commits
v0.18.4
...
feat/bette
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b71f963cc | ||
|
|
1c5cc5a0db | ||
|
|
d233f2c764 | ||
|
|
1bbb4c9b64 | ||
|
|
6ec60b6bab | ||
|
|
55abac3f2f | ||
|
|
b6c29ccf05 | ||
|
|
ca217affe6 | ||
|
|
5c24281f72 | ||
|
|
bc901bcb25 | ||
|
|
7c0d223e17 | ||
|
|
74ee024cf9 | ||
|
|
140a871275 | ||
|
|
d1f72a2e20 | ||
|
|
0d525398a8 | ||
|
|
7c62408070 | ||
|
|
23f1ce17de | ||
|
|
60eee55f2d | ||
|
|
8f562eefc1 | ||
|
|
6179cef1ee | ||
|
|
b7112b89fd | ||
|
|
1db6ba94f4 | ||
|
|
afd3d2eea3 | ||
|
|
8bd72a8a34 | ||
|
|
fafc238e70 | ||
|
|
c04bf3c7e0 |
@@ -21,6 +21,7 @@ import {
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PlusIcon, SquarePen } from "lucide-react";
|
||||
@@ -97,6 +98,18 @@ export const HandleProject = ({ projectId }: Props) => {
|
||||
);
|
||||
});
|
||||
};
|
||||
// useEffect(() => {
|
||||
// const getUsers = async () => {
|
||||
// const users = await authClient.admin.listUsers({
|
||||
// query: {
|
||||
// limit: 100,
|
||||
// },
|
||||
// });
|
||||
// console.log(users);
|
||||
// };
|
||||
|
||||
// getUsers();
|
||||
// });
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
|
||||
@@ -57,7 +57,7 @@ export const ShowProjects = () => {
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
const { mutateAsync } = api.project.remove.useMutation();
|
||||
@@ -91,7 +91,7 @@ export const ShowProjects = () => {
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
{(auth?.rol === "admin" || user?.canCreateProjects) && (
|
||||
{(auth?.role === "owner" || user?.canCreateProjects) && (
|
||||
<div className="">
|
||||
<HandleProject />
|
||||
</div>
|
||||
@@ -293,7 +293,7 @@ export const ShowProjects = () => {
|
||||
<div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{(auth?.rol === "admin" ||
|
||||
{(auth?.role === "owner" ||
|
||||
user?.canDeleteProjects) && (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger className="w-full">
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from "@/components/ui/command";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import {
|
||||
type Services,
|
||||
extractServices,
|
||||
@@ -35,8 +36,10 @@ export const SearchCommand = () => {
|
||||
const router = useRouter();
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
const { data } = api.project.all.useQuery();
|
||||
const { data: session } = authClient.getSession();
|
||||
const { data } = api.project.all.useQuery(undefined, {
|
||||
enabled: !!session,
|
||||
});
|
||||
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
||||
|
||||
React.useEffect(() => {
|
||||
|
||||
@@ -15,7 +15,7 @@ export const ShowWelcomeDokploy = () => {
|
||||
|
||||
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
||||
|
||||
if (!isCloud || data?.rol !== "admin") {
|
||||
if (!isCloud || data?.role !== "admin") {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -24,14 +24,14 @@ export const ShowWelcomeDokploy = () => {
|
||||
!isLoading &&
|
||||
isCloud &&
|
||||
!localStorage.getItem("hasSeenCloudWelcomeModal") &&
|
||||
data?.rol === "admin"
|
||||
data?.role === "owner"
|
||||
) {
|
||||
setOpen(true);
|
||||
}
|
||||
}, [isCloud, isLoading]);
|
||||
|
||||
const handleClose = (isOpen: boolean) => {
|
||||
if (data?.rol === "admin") {
|
||||
if (data?.role === "owner") {
|
||||
setOpen(isOpen);
|
||||
if (!isOpen) {
|
||||
localStorage.setItem("hasSeenCloudWelcomeModal", "true"); // Establece el flag al cerrar el modal
|
||||
|
||||
@@ -51,7 +51,7 @@ export const GenerateToken = () => {
|
||||
<Label>Token</Label>
|
||||
<ToggleVisibilityInput
|
||||
placeholder="Token"
|
||||
value={data?.token || ""}
|
||||
value={data?.user?.token || ""}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -73,9 +73,9 @@ export const ProfileForm = () => {
|
||||
|
||||
const form = useForm<Profile>({
|
||||
defaultValues: {
|
||||
email: data?.email || "",
|
||||
email: data?.user?.email || "",
|
||||
password: "",
|
||||
image: data?.image || "",
|
||||
image: data?.user?.image || "",
|
||||
currentPassword: "",
|
||||
},
|
||||
resolver: zodResolver(profileSchema),
|
||||
@@ -84,14 +84,14 @@ export const ProfileForm = () => {
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
form.reset({
|
||||
email: data?.email || "",
|
||||
email: data?.user?.email || "",
|
||||
password: "",
|
||||
image: data?.image || "",
|
||||
image: data?.user?.image || "",
|
||||
currentPassword: "",
|
||||
});
|
||||
|
||||
if (data.email) {
|
||||
generateSHA256Hash(data.email).then((hash) => {
|
||||
if (data.user.email) {
|
||||
generateSHA256Hash(data.user.email).then((hash) => {
|
||||
setGravatarHash(hash);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ const MENU: Menu = {
|
||||
// Only enabled for admins and users with access to Traefik files in non-cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!(
|
||||
(auth?.rol === "admin" || user?.canAccessToTraefikFiles) &&
|
||||
(auth?.role === "owner" || user?.canAccessToTraefikFiles) &&
|
||||
!isCloud
|
||||
),
|
||||
},
|
||||
@@ -166,7 +166,7 @@ const MENU: Menu = {
|
||||
icon: BlocksIcon,
|
||||
// Only enabled for admins and users with access to Docker in non-cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!((auth?.rol === "admin" || user?.canAccessToDocker) && !isCloud),
|
||||
!!((auth?.role === "owner" || user?.canAccessToDocker) && !isCloud),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -175,7 +175,7 @@ const MENU: Menu = {
|
||||
icon: PieChart,
|
||||
// Only enabled for admins and users with access to Docker in non-cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!((auth?.rol === "admin" || user?.canAccessToDocker) && !isCloud),
|
||||
!!((auth?.role === "owner" || user?.canAccessToDocker) && !isCloud),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -184,7 +184,7 @@ const MENU: Menu = {
|
||||
icon: Forward,
|
||||
// Only enabled for admins and users with access to Docker in non-cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!((auth?.rol === "admin" || user?.canAccessToDocker) && !isCloud),
|
||||
!!((auth?.role === "owner" || user?.canAccessToDocker) && !isCloud),
|
||||
},
|
||||
|
||||
// Legacy unused menu, adjusted to the new structure
|
||||
@@ -252,7 +252,7 @@ const MENU: Menu = {
|
||||
icon: Activity,
|
||||
// Only enabled for admins in non-cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!(auth?.rol === "admin" && !isCloud),
|
||||
!!(auth?.role === "owner" && !isCloud),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -266,7 +266,7 @@ const MENU: Menu = {
|
||||
url: "/dashboard/settings/servers",
|
||||
icon: Server,
|
||||
// Only enabled for admins
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -274,7 +274,7 @@ const MENU: Menu = {
|
||||
icon: Users,
|
||||
url: "/dashboard/settings/users",
|
||||
// Only enabled for admins
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -283,7 +283,7 @@ const MENU: Menu = {
|
||||
url: "/dashboard/settings/ssh-keys",
|
||||
// Only enabled for admins and users with access to SSH keys
|
||||
isEnabled: ({ auth, user }) =>
|
||||
!!(auth?.rol === "admin" || user?.canAccessToSSHKeys),
|
||||
!!(auth?.role === "owner" || user?.canAccessToSSHKeys),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -292,7 +292,7 @@ const MENU: Menu = {
|
||||
icon: GitBranch,
|
||||
// Only enabled for admins and users with access to Git providers
|
||||
isEnabled: ({ auth, user }) =>
|
||||
!!(auth?.rol === "admin" || user?.canAccessToGitProviders),
|
||||
!!(auth?.role === "owner" || user?.canAccessToGitProviders),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -300,7 +300,7 @@ const MENU: Menu = {
|
||||
url: "/dashboard/settings/registry",
|
||||
icon: Package,
|
||||
// Only enabled for admins
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -308,7 +308,7 @@ const MENU: Menu = {
|
||||
url: "/dashboard/settings/destinations",
|
||||
icon: Database,
|
||||
// Only enabled for admins
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
|
||||
},
|
||||
|
||||
{
|
||||
@@ -317,7 +317,7 @@ const MENU: Menu = {
|
||||
url: "/dashboard/settings/certificates",
|
||||
icon: ShieldCheck,
|
||||
// Only enabled for admins
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -326,7 +326,7 @@ const MENU: Menu = {
|
||||
icon: Boxes,
|
||||
// Only enabled for admins in non-cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!(auth?.rol === "admin" && !isCloud),
|
||||
!!(auth?.role === "owner" && !isCloud),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -334,7 +334,7 @@ const MENU: Menu = {
|
||||
url: "/dashboard/settings/notifications",
|
||||
icon: Bell,
|
||||
// Only enabled for admins
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
|
||||
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
@@ -343,7 +343,7 @@ const MENU: Menu = {
|
||||
icon: CreditCard,
|
||||
// Only enabled for admins in cloud environments
|
||||
isEnabled: ({ auth, user, isCloud }) =>
|
||||
!!(auth?.rol === "admin" && isCloud),
|
||||
!!(auth?.role === "owner" && isCloud),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -537,7 +537,7 @@ export default function Page({ children }: Props) {
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -557,7 +557,7 @@ export default function Page({ children }: Props) {
|
||||
|
||||
// const showProjectsButton =
|
||||
// currentPath === "/dashboard/projects" &&
|
||||
// (auth?.rol === "admin" || user?.canCreateProjects);
|
||||
// (auth?.rol === "owner" || user?.canCreateProjects);
|
||||
|
||||
return (
|
||||
<SidebarProvider
|
||||
@@ -783,7 +783,7 @@ export default function Page({ children }: Props) {
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
{!isCloud && auth?.rol === "admin" && (
|
||||
{!isCloud && auth?.role === "owner" && (
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild>
|
||||
<UpdateServerButton />
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { Languages } from "@/lib/languages";
|
||||
import { api } from "@/utils/api";
|
||||
import useLocale from "@/utils/hooks/use-locale";
|
||||
@@ -36,11 +37,11 @@ export const UserNav = () => {
|
||||
authId: data?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!data?.id && data?.rol === "user",
|
||||
enabled: !!data?.id && data?.role === "member",
|
||||
},
|
||||
);
|
||||
const { locale, setLocale } = useLocale();
|
||||
const { mutateAsync } = api.auth.logout.useMutation();
|
||||
// const { mutateAsync } = api.auth.logout.useMutation();
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
@@ -50,12 +51,15 @@ export const UserNav = () => {
|
||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<Avatar className="h-8 w-8 rounded-lg">
|
||||
<AvatarImage src={data?.image || ""} alt={data?.image || ""} />
|
||||
<AvatarImage
|
||||
src={data?.user?.image || ""}
|
||||
alt={data?.user?.image || ""}
|
||||
/>
|
||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||
<span className="truncate font-semibold">Account</span>
|
||||
<span className="truncate text-xs">{data?.email}</span>
|
||||
<span className="truncate text-xs">{data?.user?.email}</span>
|
||||
</div>
|
||||
<ChevronsUpDown className="ml-auto size-4" />
|
||||
</SidebarMenuButton>
|
||||
@@ -70,7 +74,7 @@ export const UserNav = () => {
|
||||
<DropdownMenuLabel className="flex flex-col">
|
||||
My Account
|
||||
<span className="text-xs font-normal text-muted-foreground">
|
||||
{data?.email}
|
||||
{data?.user?.email}
|
||||
</span>
|
||||
</DropdownMenuLabel>
|
||||
<ModeToggle />
|
||||
@@ -95,7 +99,7 @@ export const UserNav = () => {
|
||||
>
|
||||
Monitoring
|
||||
</DropdownMenuItem>
|
||||
{(data?.rol === "admin" || user?.canAccessToTraefikFiles) && (
|
||||
{(data?.role === "owner" || user?.canAccessToTraefikFiles) && (
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
@@ -105,7 +109,7 @@ export const UserNav = () => {
|
||||
Traefik
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{(data?.rol === "admin" || user?.canAccessToDocker) && (
|
||||
{(data?.role === "owner" || user?.canAccessToDocker) && (
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
@@ -118,7 +122,7 @@ export const UserNav = () => {
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
{data?.rol === "admin" && (
|
||||
{data?.role === "owner" && (
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
@@ -139,7 +143,7 @@ export const UserNav = () => {
|
||||
>
|
||||
Profile
|
||||
</DropdownMenuItem>
|
||||
{data?.rol === "admin" && (
|
||||
{data?.role === "owner" && (
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
@@ -150,7 +154,7 @@ export const UserNav = () => {
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
{data?.rol === "admin" && (
|
||||
{data?.role === "owner" && (
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
@@ -163,7 +167,7 @@ export const UserNav = () => {
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuGroup>
|
||||
{isCloud && data?.rol === "admin" && (
|
||||
{isCloud && data?.role === "owner" && (
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
@@ -178,9 +182,12 @@ export const UserNav = () => {
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={async () => {
|
||||
await mutateAsync().then(() => {
|
||||
await authClient.signOut().then(() => {
|
||||
router.push("/");
|
||||
});
|
||||
// await mutateAsync().then(() => {
|
||||
// router.push("/");
|
||||
// });
|
||||
}}
|
||||
>
|
||||
Log out
|
||||
|
||||
127
apps/dokploy/drizzle/0066_yielding_echo.sql
Normal file
127
apps/dokploy/drizzle/0066_yielding_echo.sql
Normal file
@@ -0,0 +1,127 @@
|
||||
CREATE TABLE "user_temp" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"name" text DEFAULT '' NOT NULL,
|
||||
"token" text NOT NULL,
|
||||
"isRegistered" boolean DEFAULT false NOT NULL,
|
||||
"expirationDate" text NOT NULL,
|
||||
"createdAt" text NOT NULL,
|
||||
"canCreateProjects" boolean DEFAULT false NOT NULL,
|
||||
"canAccessToSSHKeys" boolean DEFAULT false NOT NULL,
|
||||
"canCreateServices" boolean DEFAULT false NOT NULL,
|
||||
"canDeleteProjects" boolean DEFAULT false NOT NULL,
|
||||
"canDeleteServices" boolean DEFAULT false NOT NULL,
|
||||
"canAccessToDocker" boolean DEFAULT false NOT NULL,
|
||||
"canAccessToAPI" boolean DEFAULT false NOT NULL,
|
||||
"canAccessToGitProviders" boolean DEFAULT false NOT NULL,
|
||||
"canAccessToTraefikFiles" boolean DEFAULT false NOT NULL,
|
||||
"accesedProjects" text[] DEFAULT ARRAY[]::text[] NOT NULL,
|
||||
"accesedServices" text[] DEFAULT ARRAY[]::text[] NOT NULL,
|
||||
"email" text NOT NULL,
|
||||
"email_verified" boolean NOT NULL,
|
||||
"image" text,
|
||||
"banned" boolean,
|
||||
"ban_reason" text,
|
||||
"ban_expires" timestamp,
|
||||
"updated_at" timestamp NOT NULL,
|
||||
"serverIp" text,
|
||||
"certificateType" "certificateType" DEFAULT 'none' NOT NULL,
|
||||
"host" text,
|
||||
"letsEncryptEmail" text,
|
||||
"sshPrivateKey" text,
|
||||
"enableDockerCleanup" boolean DEFAULT false NOT NULL,
|
||||
"enableLogRotation" boolean DEFAULT false NOT NULL,
|
||||
"enablePaidFeatures" boolean DEFAULT false NOT NULL,
|
||||
"metricsConfig" jsonb DEFAULT '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}'::jsonb NOT NULL,
|
||||
"cleanupCacheApplications" boolean DEFAULT false NOT NULL,
|
||||
"cleanupCacheOnPreviews" boolean DEFAULT false NOT NULL,
|
||||
"cleanupCacheOnCompose" boolean DEFAULT false NOT NULL,
|
||||
"stripeCustomerId" text,
|
||||
"stripeSubscriptionId" text,
|
||||
"serversQuantity" integer DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT "user_temp_email_unique" UNIQUE("email")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "session_temp" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"expires_at" timestamp NOT NULL,
|
||||
"token" text NOT NULL,
|
||||
"created_at" timestamp NOT NULL,
|
||||
"updated_at" timestamp NOT NULL,
|
||||
"ip_address" text,
|
||||
"user_agent" text,
|
||||
"user_id" text NOT NULL,
|
||||
"impersonated_by" text,
|
||||
"active_organization_id" text,
|
||||
CONSTRAINT "session_temp_token_unique" UNIQUE("token")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "account" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"account_id" text NOT NULL,
|
||||
"provider_id" text NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"access_token" text,
|
||||
"refresh_token" text,
|
||||
"id_token" text,
|
||||
"access_token_expires_at" timestamp,
|
||||
"refresh_token_expires_at" timestamp,
|
||||
"scope" text,
|
||||
"password" text,
|
||||
"is2FAEnabled" boolean DEFAULT false NOT NULL,
|
||||
"created_at" timestamp NOT NULL,
|
||||
"updated_at" timestamp NOT NULL,
|
||||
"resetPasswordToken" text,
|
||||
"resetPasswordExpiresAt" text,
|
||||
"confirmationToken" text,
|
||||
"confirmationExpiresAt" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "invitation" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"organization_id" text NOT NULL,
|
||||
"email" text NOT NULL,
|
||||
"role" text,
|
||||
"status" text NOT NULL,
|
||||
"expires_at" timestamp NOT NULL,
|
||||
"inviter_id" text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "member" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"organization_id" text NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"role" text NOT NULL,
|
||||
"created_at" timestamp NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "organization" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"slug" text,
|
||||
"logo" text,
|
||||
"created_at" timestamp NOT NULL,
|
||||
"metadata" text,
|
||||
"owner_id" text NOT NULL,
|
||||
CONSTRAINT "organization_slug_unique" UNIQUE("slug")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "verification" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"identifier" text NOT NULL,
|
||||
"value" text NOT NULL,
|
||||
"expires_at" timestamp NOT NULL,
|
||||
"created_at" timestamp,
|
||||
"updated_at" timestamp
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "certificate" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "notification" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "ssh-key" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "git_provider" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "session_temp" ADD CONSTRAINT "session_temp_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_user_temp_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "member" ADD CONSTRAINT "member_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "organization" ADD CONSTRAINT "organization_owner_id_user_temp_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;
|
||||
211
apps/dokploy/drizzle/0067_migrate-data.sql
Normal file
211
apps/dokploy/drizzle/0067_migrate-data.sql
Normal file
@@ -0,0 +1,211 @@
|
||||
-- Custom SQL migration file, put your code below! --
|
||||
|
||||
WITH inserted_users AS (
|
||||
-- Insertar usuarios desde admins
|
||||
INSERT INTO user_temp (
|
||||
id,
|
||||
email,
|
||||
token,
|
||||
"email_verified",
|
||||
"updated_at",
|
||||
"serverIp",
|
||||
image,
|
||||
"certificateType",
|
||||
host,
|
||||
"letsEncryptEmail",
|
||||
"sshPrivateKey",
|
||||
"enableDockerCleanup",
|
||||
"enableLogRotation",
|
||||
"enablePaidFeatures",
|
||||
"metricsConfig",
|
||||
"cleanupCacheApplications",
|
||||
"cleanupCacheOnPreviews",
|
||||
"cleanupCacheOnCompose",
|
||||
"stripeCustomerId",
|
||||
"stripeSubscriptionId",
|
||||
"serversQuantity",
|
||||
"expirationDate",
|
||||
"createdAt"
|
||||
)
|
||||
SELECT
|
||||
a."adminId",
|
||||
auth.email,
|
||||
COALESCE(auth.token, ''),
|
||||
true,
|
||||
CURRENT_TIMESTAMP,
|
||||
a."serverIp",
|
||||
auth.image,
|
||||
a."certificateType",
|
||||
a.host,
|
||||
a."letsEncryptEmail",
|
||||
a."sshPrivateKey",
|
||||
a."enableDockerCleanup",
|
||||
a."enableLogRotation",
|
||||
a."enablePaidFeatures",
|
||||
a."metricsConfig",
|
||||
a."cleanupCacheApplications",
|
||||
a."cleanupCacheOnPreviews",
|
||||
a."cleanupCacheOnCompose",
|
||||
a."stripeCustomerId",
|
||||
a."stripeSubscriptionId",
|
||||
a."serversQuantity",
|
||||
NOW() + INTERVAL '1 year',
|
||||
NOW()
|
||||
FROM admin a
|
||||
JOIN auth ON auth.id = a."authId"
|
||||
RETURNING *
|
||||
),
|
||||
inserted_accounts AS (
|
||||
-- Insertar cuentas para los admins
|
||||
INSERT INTO account (
|
||||
id,
|
||||
"account_id",
|
||||
"provider_id",
|
||||
"user_id",
|
||||
password,
|
||||
"is2FAEnabled",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
gen_random_uuid(),
|
||||
'credential',
|
||||
a."adminId",
|
||||
auth.password,
|
||||
COALESCE(auth."is2FAEnabled", false),
|
||||
NOW(),
|
||||
NOW()
|
||||
FROM admin a
|
||||
JOIN auth ON auth.id = a."authId"
|
||||
RETURNING *
|
||||
),
|
||||
inserted_orgs AS (
|
||||
-- Crear organizaciones para cada admin
|
||||
INSERT INTO organization (
|
||||
id,
|
||||
name,
|
||||
slug,
|
||||
"owner_id",
|
||||
"created_at"
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
'My Organization',
|
||||
-- Generamos un slug único usando una función de hash
|
||||
encode(sha256((a."adminId" || CURRENT_TIMESTAMP)::bytea), 'hex'),
|
||||
a."adminId",
|
||||
NOW()
|
||||
FROM admin a
|
||||
RETURNING *
|
||||
),
|
||||
inserted_members AS (
|
||||
-- Insertar usuarios miembros
|
||||
INSERT INTO user_temp (
|
||||
id,
|
||||
email,
|
||||
token,
|
||||
"email_verified",
|
||||
"updated_at",
|
||||
image,
|
||||
"createdAt",
|
||||
"canAccessToAPI",
|
||||
"canAccessToDocker",
|
||||
"canAccessToGitProviders",
|
||||
"canAccessToSSHKeys",
|
||||
"canAccessToTraefikFiles",
|
||||
"canCreateProjects",
|
||||
"canCreateServices",
|
||||
"canDeleteProjects",
|
||||
"canDeleteServices",
|
||||
"accesedProjects",
|
||||
"accesedServices",
|
||||
"expirationDate"
|
||||
)
|
||||
SELECT
|
||||
u."userId",
|
||||
auth.email,
|
||||
COALESCE(u.token, ''),
|
||||
true,
|
||||
CURRENT_TIMESTAMP,
|
||||
auth.image,
|
||||
NOW(),
|
||||
COALESCE(u."canAccessToAPI", false),
|
||||
COALESCE(u."canAccessToDocker", false),
|
||||
COALESCE(u."canAccessToGitProviders", false),
|
||||
COALESCE(u."canAccessToSSHKeys", false),
|
||||
COALESCE(u."canAccessToTraefikFiles", false),
|
||||
COALESCE(u."canCreateProjects", false),
|
||||
COALESCE(u."canCreateServices", false),
|
||||
COALESCE(u."canDeleteProjects", false),
|
||||
COALESCE(u."canDeleteServices", false),
|
||||
COALESCE(u."accesedProjects", '{}'),
|
||||
COALESCE(u."accesedServices", '{}'),
|
||||
NOW() + INTERVAL '1 year'
|
||||
FROM "user" u
|
||||
JOIN admin a ON u."adminId" = a."adminId"
|
||||
JOIN auth ON auth.id = u."authId"
|
||||
RETURNING *
|
||||
),
|
||||
inserted_member_accounts AS (
|
||||
-- Insertar cuentas para los usuarios miembros
|
||||
INSERT INTO account (
|
||||
id,
|
||||
"account_id",
|
||||
"provider_id",
|
||||
"user_id",
|
||||
password,
|
||||
"is2FAEnabled",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
gen_random_uuid(),
|
||||
'credential',
|
||||
u."userId",
|
||||
auth.password,
|
||||
COALESCE(auth."is2FAEnabled", false),
|
||||
NOW(),
|
||||
NOW()
|
||||
FROM "user" u
|
||||
JOIN admin a ON u."adminId" = a."adminId"
|
||||
JOIN auth ON auth.id = u."authId"
|
||||
RETURNING *
|
||||
),
|
||||
inserted_admin_members AS (
|
||||
-- Insertar miembros en las organizaciones (admins como owners)
|
||||
INSERT INTO member (
|
||||
id,
|
||||
"organization_id",
|
||||
"user_id",
|
||||
role,
|
||||
"created_at"
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
o.id,
|
||||
a."adminId",
|
||||
'owner',
|
||||
NOW()
|
||||
FROM admin a
|
||||
JOIN inserted_orgs o ON o."owner_id" = a."adminId"
|
||||
RETURNING *
|
||||
)
|
||||
-- Insertar miembros regulares en las organizaciones
|
||||
INSERT INTO member (
|
||||
id,
|
||||
"organization_id",
|
||||
"user_id",
|
||||
role,
|
||||
"created_at"
|
||||
)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
o.id,
|
||||
u."userId",
|
||||
'member',
|
||||
NOW()
|
||||
FROM "user" u
|
||||
JOIN admin a ON u."adminId" = a."adminId"
|
||||
JOIN inserted_orgs o ON o."owner_id" = a."adminId";
|
||||
32
apps/dokploy/drizzle/0068_sour_professor_monster.sql
Normal file
32
apps/dokploy/drizzle/0068_sour_professor_monster.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
ALTER TABLE "project" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "destination" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "certificate" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "registry" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "notification" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "ssh-key" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "git_provider" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "server" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
|
||||
ALTER TABLE "project" DROP CONSTRAINT "project_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "destination" DROP CONSTRAINT "destination_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "certificate" DROP CONSTRAINT "certificate_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "registry" DROP CONSTRAINT "registry_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "notification" DROP CONSTRAINT "notification_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "ssh-key" DROP CONSTRAINT "ssh-key_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "git_provider" DROP CONSTRAINT "git_provider_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "server" DROP CONSTRAINT "server_adminId_admin_adminId_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "project" ADD CONSTRAINT "project_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "destination" ADD CONSTRAINT "destination_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "certificate" ADD CONSTRAINT "certificate_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "registry" ADD CONSTRAINT "registry_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "notification" ADD CONSTRAINT "notification_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "ssh-key" ADD CONSTRAINT "ssh-key_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "server" ADD CONSTRAINT "server_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;
|
||||
2
apps/dokploy/drizzle/0069_broad_ken_ellis.sql
Normal file
2
apps/dokploy/drizzle/0069_broad_ken_ellis.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "user_temp" ALTER COLUMN "token" SET DEFAULT '';--> statement-breakpoint
|
||||
ALTER TABLE "user_temp" ADD COLUMN "created_at" timestamp DEFAULT now();
|
||||
5272
apps/dokploy/drizzle/meta/0066_snapshot.json
Normal file
5272
apps/dokploy/drizzle/meta/0066_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
5272
apps/dokploy/drizzle/meta/0067_snapshot.json
Normal file
5272
apps/dokploy/drizzle/meta/0067_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
5272
apps/dokploy/drizzle/meta/0068_snapshot.json
Normal file
5272
apps/dokploy/drizzle/meta/0068_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
5280
apps/dokploy/drizzle/meta/0069_snapshot.json
Normal file
5280
apps/dokploy/drizzle/meta/0069_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -463,6 +463,34 @@
|
||||
"when": 1739087857244,
|
||||
"tag": "0065_daily_zaladane",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 66,
|
||||
"version": "7",
|
||||
"when": 1739426913392,
|
||||
"tag": "0066_yielding_echo",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 67,
|
||||
"version": "7",
|
||||
"when": 1739427057545,
|
||||
"tag": "0067_migrate-data",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 68,
|
||||
"version": "7",
|
||||
"when": 1739428942964,
|
||||
"tag": "0068_sour_professor_monster",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 69,
|
||||
"version": "7",
|
||||
"when": 1739664410814,
|
||||
"tag": "0069_broad_ken_ellis",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
7
apps/dokploy/lib/auth.ts
Normal file
7
apps/dokploy/lib/auth.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
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
|
||||
plugins: [organizationClient()],
|
||||
});
|
||||
126
apps/dokploy/migrate.ts
Normal file
126
apps/dokploy/migrate.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import { migrate } from "drizzle-orm/postgres-js/migrator";
|
||||
import { nanoid } from "nanoid";
|
||||
import postgres from "postgres";
|
||||
import * as schema from "./server/db/schema";
|
||||
|
||||
const connectionString = process.env.DATABASE_URL!;
|
||||
|
||||
const sql = postgres(connectionString, { max: 1 });
|
||||
const db = drizzle(sql, {
|
||||
schema,
|
||||
});
|
||||
|
||||
await db
|
||||
.transaction(async (db) => {
|
||||
const admins = await db.query.admins.findMany({
|
||||
with: {
|
||||
auth: true,
|
||||
users: {
|
||||
with: {
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
for (const admin of admins) {
|
||||
const user = await db
|
||||
.insert(schema.users_temp)
|
||||
.values({
|
||||
id: admin.adminId,
|
||||
email: admin.auth.email,
|
||||
token: admin.auth.token || "",
|
||||
emailVerified: true,
|
||||
updatedAt: new Date(),
|
||||
role: "admin",
|
||||
serverIp: admin.serverIp,
|
||||
image: admin.auth.image,
|
||||
certificateType: admin.certificateType,
|
||||
host: admin.host,
|
||||
letsEncryptEmail: admin.letsEncryptEmail,
|
||||
sshPrivateKey: admin.sshPrivateKey,
|
||||
enableDockerCleanup: admin.enableDockerCleanup,
|
||||
enableLogRotation: admin.enableLogRotation,
|
||||
enablePaidFeatures: admin.enablePaidFeatures,
|
||||
metricsConfig: admin.metricsConfig,
|
||||
cleanupCacheApplications: admin.cleanupCacheApplications,
|
||||
cleanupCacheOnPreviews: admin.cleanupCacheOnPreviews,
|
||||
cleanupCacheOnCompose: admin.cleanupCacheOnCompose,
|
||||
stripeCustomerId: admin.stripeCustomerId,
|
||||
stripeSubscriptionId: admin.stripeSubscriptionId,
|
||||
serversQuantity: admin.serversQuantity,
|
||||
})
|
||||
.returning()
|
||||
.then((user) => user[0]);
|
||||
|
||||
await db.insert(schema.account).values({
|
||||
providerId: "credential",
|
||||
userId: user?.id || "",
|
||||
password: admin.auth.password,
|
||||
is2FAEnabled: admin.auth.is2FAEnabled || false,
|
||||
createdAt: new Date(admin.auth.createdAt) || new Date(),
|
||||
updatedAt: new Date(admin.auth.createdAt) || new Date(),
|
||||
});
|
||||
|
||||
const organization = await db
|
||||
.insert(schema.organization)
|
||||
.values({
|
||||
name: "My Organization",
|
||||
slug: nanoid(),
|
||||
ownerId: user?.id || "",
|
||||
createdAt: new Date(admin.createdAt) || new Date(),
|
||||
})
|
||||
.returning()
|
||||
.then((organization) => organization[0]);
|
||||
|
||||
for (const member of admin.users) {
|
||||
const userTemp = await db
|
||||
.insert(schema.users_temp)
|
||||
.values({
|
||||
id: member.userId,
|
||||
email: member.auth.email,
|
||||
token: member.token || "",
|
||||
emailVerified: true,
|
||||
updatedAt: new Date(admin.createdAt) || new Date(),
|
||||
role: "user",
|
||||
image: member.auth.image,
|
||||
createdAt: admin.createdAt,
|
||||
canAccessToAPI: member.canAccessToAPI || false,
|
||||
canAccessToDocker: member.canAccessToDocker || false,
|
||||
canAccessToGitProviders: member.canAccessToGitProviders || false,
|
||||
canAccessToSSHKeys: member.canAccessToSSHKeys || false,
|
||||
canAccessToTraefikFiles: member.canAccessToTraefikFiles || false,
|
||||
canCreateProjects: member.canCreateProjects || false,
|
||||
canCreateServices: member.canCreateServices || false,
|
||||
canDeleteProjects: member.canDeleteProjects || false,
|
||||
canDeleteServices: member.canDeleteServices || false,
|
||||
accessedProjects: member.accessedProjects || [],
|
||||
accessedServices: member.accessedServices || [],
|
||||
})
|
||||
.returning()
|
||||
.then((userTemp) => userTemp[0]);
|
||||
|
||||
await db.insert(schema.account).values({
|
||||
providerId: "credential",
|
||||
userId: member?.userId || "",
|
||||
password: member.auth.password,
|
||||
is2FAEnabled: member.auth.is2FAEnabled || false,
|
||||
createdAt: new Date(member.auth.createdAt) || new Date(),
|
||||
updatedAt: new Date(member.auth.createdAt) || new Date(),
|
||||
});
|
||||
|
||||
await db.insert(schema.member).values({
|
||||
organizationId: organization?.id || "",
|
||||
userId: userTemp?.id || "",
|
||||
role: "admin",
|
||||
createdAt: new Date(member.createdAt) || new Date(),
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Migration finished");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dokploy",
|
||||
"version": "v0.18.3",
|
||||
"version": "v0.18.2",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
@@ -16,6 +16,7 @@
|
||||
"studio": "drizzle-kit studio --config ./server/db/drizzle.config.ts",
|
||||
"migration:generate": "drizzle-kit generate --config ./server/db/drizzle.config.ts",
|
||||
"migration:run": "tsx -r dotenv/config migration.ts",
|
||||
"manual-migration:run": "tsx -r dotenv/config migrate.ts",
|
||||
"migration:up": "drizzle-kit up --config ./server/db/drizzle.config.ts",
|
||||
"migration:drop": "drizzle-kit drop --config ./server/db/drizzle.config.ts",
|
||||
"db:push": "drizzle-kit push --config ./server/db/drizzle.config.ts",
|
||||
@@ -35,6 +36,7 @@
|
||||
"test": "vitest --config __test__/vitest.config.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"better-auth": "1.1.16",
|
||||
"bl": "6.0.11",
|
||||
"rotating-file-stream": "3.2.3",
|
||||
"qrcode": "^1.5.3",
|
||||
|
||||
7
apps/dokploy/pages/api/auth/[...all].ts
Normal file
7
apps/dokploy/pages/api/auth/[...all].ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { auth } from "@dokploy/server/index";
|
||||
import { toNodeHandler } from "better-auth/node";
|
||||
|
||||
// Disallow body parsing, we will parse it manually
|
||||
export const config = { api: { bodyParser: false } };
|
||||
|
||||
export default toNodeHandler(auth.handler);
|
||||
@@ -42,7 +42,7 @@ export default async function handler(
|
||||
const auth = await findAuthById(value as string);
|
||||
|
||||
let adminId = "";
|
||||
if (auth.rol === "admin") {
|
||||
if (auth.role === "owner") {
|
||||
const admin = await findAdminByAuthId(auth.id);
|
||||
adminId = admin.adminId;
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buffer } from "node:stream/consumers";
|
||||
import { db } from "@/server/db";
|
||||
import { admins, server } from "@/server/db/schema";
|
||||
import { findAdminById } from "@dokploy/server";
|
||||
import { admins, server, users_temp } from "@/server/db/schema";
|
||||
import { findAdminById, findUserById } from "@dokploy/server";
|
||||
import { asc, eq } from "drizzle-orm";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import Stripe from "stripe";
|
||||
@@ -64,33 +64,35 @@ export default async function handler(
|
||||
session.subscription as string,
|
||||
);
|
||||
await db
|
||||
.update(admins)
|
||||
.update(users_temp)
|
||||
.set({
|
||||
stripeCustomerId: session.customer as string,
|
||||
stripeSubscriptionId: session.subscription as string,
|
||||
serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
|
||||
})
|
||||
.where(eq(admins.adminId, adminId))
|
||||
.where(eq(users_temp.id, adminId))
|
||||
.returning();
|
||||
|
||||
const admin = await findAdminById(adminId);
|
||||
const admin = await findUserById(adminId);
|
||||
if (!admin) {
|
||||
return res.status(400).send("Webhook Error: Admin not found");
|
||||
}
|
||||
const newServersQuantity = admin.serversQuantity;
|
||||
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
||||
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
|
||||
break;
|
||||
}
|
||||
case "customer.subscription.created": {
|
||||
const newSubscription = event.data.object as Stripe.Subscription;
|
||||
|
||||
await db
|
||||
.update(admins)
|
||||
.update(users_temp)
|
||||
.set({
|
||||
stripeSubscriptionId: newSubscription.id,
|
||||
stripeCustomerId: newSubscription.customer as string,
|
||||
})
|
||||
.where(eq(admins.stripeCustomerId, newSubscription.customer as string))
|
||||
.where(
|
||||
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
|
||||
)
|
||||
.returning();
|
||||
|
||||
break;
|
||||
@@ -100,14 +102,16 @@ export default async function handler(
|
||||
const newSubscription = event.data.object as Stripe.Subscription;
|
||||
|
||||
await db
|
||||
.update(admins)
|
||||
.update(users_temp)
|
||||
.set({
|
||||
stripeSubscriptionId: null,
|
||||
serversQuantity: 0,
|
||||
})
|
||||
.where(eq(admins.stripeCustomerId, newSubscription.customer as string));
|
||||
.where(
|
||||
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
|
||||
);
|
||||
|
||||
const admin = await findAdminByStripeCustomerId(
|
||||
const admin = await findUserByStripeCustomerId(
|
||||
newSubscription.customer as string,
|
||||
);
|
||||
|
||||
@@ -115,13 +119,13 @@ export default async function handler(
|
||||
return res.status(400).send("Webhook Error: Admin not found");
|
||||
}
|
||||
|
||||
await disableServers(admin.adminId);
|
||||
await disableServers(admin.id);
|
||||
break;
|
||||
}
|
||||
case "customer.subscription.updated": {
|
||||
const newSubscription = event.data.object as Stripe.Subscription;
|
||||
|
||||
const admin = await findAdminByStripeCustomerId(
|
||||
const admin = await findUserByStripeCustomerId(
|
||||
newSubscription.customer as string,
|
||||
);
|
||||
|
||||
@@ -131,23 +135,23 @@ export default async function handler(
|
||||
|
||||
if (newSubscription.status === "active") {
|
||||
await db
|
||||
.update(admins)
|
||||
.update(users_temp)
|
||||
.set({
|
||||
serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
|
||||
})
|
||||
.where(
|
||||
eq(admins.stripeCustomerId, newSubscription.customer as string),
|
||||
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
|
||||
);
|
||||
|
||||
const newServersQuantity = admin.serversQuantity;
|
||||
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
||||
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
|
||||
} else {
|
||||
await disableServers(admin.adminId);
|
||||
await disableServers(admin.id);
|
||||
await db
|
||||
.update(admins)
|
||||
.update(users_temp)
|
||||
.set({ serversQuantity: 0 })
|
||||
.where(
|
||||
eq(admins.stripeCustomerId, newSubscription.customer as string),
|
||||
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -174,7 +178,7 @@ export default async function handler(
|
||||
})
|
||||
.where(eq(admins.stripeCustomerId, suscription.customer as string));
|
||||
|
||||
const admin = await findAdminByStripeCustomerId(
|
||||
const admin = await findUserByStripeCustomerId(
|
||||
suscription.customer as string,
|
||||
);
|
||||
|
||||
@@ -182,7 +186,7 @@ export default async function handler(
|
||||
return res.status(400).send("Webhook Error: Admin not found");
|
||||
}
|
||||
const newServersQuantity = admin.serversQuantity;
|
||||
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
||||
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
|
||||
break;
|
||||
}
|
||||
case "invoice.payment_failed": {
|
||||
@@ -193,7 +197,7 @@ export default async function handler(
|
||||
);
|
||||
|
||||
if (subscription.status !== "active") {
|
||||
const admin = await findAdminByStripeCustomerId(
|
||||
const admin = await findUserByStripeCustomerId(
|
||||
newInvoice.customer as string,
|
||||
);
|
||||
|
||||
@@ -207,7 +211,7 @@ export default async function handler(
|
||||
})
|
||||
.where(eq(admins.stripeCustomerId, newInvoice.customer as string));
|
||||
|
||||
await disableServers(admin.adminId);
|
||||
await disableServers(admin.id);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -216,20 +220,20 @@ export default async function handler(
|
||||
case "customer.deleted": {
|
||||
const customer = event.data.object as Stripe.Customer;
|
||||
|
||||
const admin = await findAdminByStripeCustomerId(customer.id);
|
||||
const admin = await findUserByStripeCustomerId(customer.id);
|
||||
if (!admin) {
|
||||
return res.status(400).send("Webhook Error: Admin not found");
|
||||
}
|
||||
|
||||
await disableServers(admin.adminId);
|
||||
await disableServers(admin.id);
|
||||
await db
|
||||
.update(admins)
|
||||
.update(users_temp)
|
||||
.set({
|
||||
stripeCustomerId: null,
|
||||
stripeSubscriptionId: null,
|
||||
serversQuantity: 0,
|
||||
})
|
||||
.where(eq(admins.stripeCustomerId, customer.id));
|
||||
.where(eq(users_temp.stripeCustomerId, customer.id));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -240,20 +244,20 @@ export default async function handler(
|
||||
return res.status(200).json({ received: true });
|
||||
}
|
||||
|
||||
const disableServers = async (adminId: string) => {
|
||||
const disableServers = async (userId: string) => {
|
||||
await db
|
||||
.update(server)
|
||||
.set({
|
||||
serverStatus: "inactive",
|
||||
})
|
||||
.where(eq(server.adminId, adminId));
|
||||
.where(eq(server.userId, userId));
|
||||
};
|
||||
|
||||
const findAdminByStripeCustomerId = async (stripeCustomerId: string) => {
|
||||
const admin = db.query.admins.findFirst({
|
||||
where: eq(admins.stripeCustomerId, stripeCustomerId),
|
||||
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
|
||||
const user = db.query.users_temp.findFirst({
|
||||
where: eq(users_temp.stripeCustomerId, stripeCustomerId),
|
||||
});
|
||||
return admin;
|
||||
return user;
|
||||
};
|
||||
|
||||
const activateServer = async (serverId: string) => {
|
||||
@@ -270,19 +274,19 @@ const deactivateServer = async (serverId: string) => {
|
||||
.where(eq(server.serverId, serverId));
|
||||
};
|
||||
|
||||
export const findServersByAdminIdSorted = async (adminId: string) => {
|
||||
export const findServersByUserIdSorted = async (userId: string) => {
|
||||
const servers = await db.query.server.findMany({
|
||||
where: eq(server.adminId, adminId),
|
||||
where: eq(server.userId, userId),
|
||||
orderBy: asc(server.createdAt),
|
||||
});
|
||||
|
||||
return servers;
|
||||
};
|
||||
export const updateServersBasedOnQuantity = async (
|
||||
adminId: string,
|
||||
userId: string,
|
||||
newServersQuantity: number,
|
||||
) => {
|
||||
const servers = await findServersByAdminIdSorted(adminId);
|
||||
const servers = await findServersByUserIdSorted(userId);
|
||||
|
||||
if (servers.length > newServersQuantity) {
|
||||
for (const [index, server] of servers.entries()) {
|
||||
|
||||
@@ -53,7 +53,7 @@ export async function getServerSideProps(
|
||||
await helpers.project.all.prefetch();
|
||||
const auth = await helpers.auth.get.fetch();
|
||||
|
||||
if (auth.rol === "user") {
|
||||
if (auth.role === "member") {
|
||||
const user = await helpers.user.byAuthId.fetch({
|
||||
authId: auth.id,
|
||||
});
|
||||
|
||||
@@ -70,9 +70,9 @@ import type {
|
||||
} from "next";
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
import { useMemo, useState, type ReactElement } from "react";
|
||||
import superjson from "superjson";
|
||||
import { type ReactElement, useMemo, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import superjson from "superjson";
|
||||
|
||||
export type Services = {
|
||||
appName: string;
|
||||
@@ -206,7 +206,7 @@ const Project = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
const { data, isLoading, refetch } = api.project.one.useQuery({ projectId });
|
||||
@@ -335,7 +335,7 @@ const Project = (
|
||||
</CardTitle>
|
||||
<CardDescription>{data?.description}</CardDescription>
|
||||
</CardHeader>
|
||||
{(auth?.rol === "admin" || user?.canCreateServices) && (
|
||||
{(auth?.role === "owner" || user?.canCreateServices) && (
|
||||
<div className="flex flex-row gap-4 flex-wrap">
|
||||
<ProjectEnvironment projectId={projectId}>
|
||||
<Button variant="outline">Project Environment</Button>
|
||||
|
||||
@@ -93,7 +93,7 @@ const Service = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -186,7 +186,7 @@ const Service = (
|
||||
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdateApplication applicationId={applicationId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={applicationId} type="application" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -87,7 +87,7 @@ const Service = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -181,7 +181,7 @@ const Service = (
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdateCompose composeId={composeId} />
|
||||
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={composeId} type="compose" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ const Mariadb = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||
@@ -154,7 +154,7 @@ const Mariadb = (
|
||||
</div>
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdateMariadb mariadbId={mariadbId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={mariadbId} type="mariadb" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ const Mongo = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -156,7 +156,7 @@ const Mongo = (
|
||||
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdateMongo mongoId={mongoId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={mongoId} type="mongo" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -67,7 +67,7 @@ const MySql = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -156,7 +156,7 @@ const MySql = (
|
||||
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdateMysql mysqlId={mysqlId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={mysqlId} type="mysql" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -66,7 +66,7 @@ const Postgresql = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
||||
@@ -154,7 +154,7 @@ const Postgresql = (
|
||||
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdatePostgres postgresId={postgresId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={postgresId} type="postgres" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -67,7 +67,7 @@ const Redis = (
|
||||
authId: auth?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!auth?.id && auth?.rol === "user",
|
||||
enabled: !!auth?.id && auth?.role === "member",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -155,7 +155,7 @@ const Redis = (
|
||||
|
||||
<div className="flex flex-row gap-2 justify-end">
|
||||
<UpdateRedis redisId={redisId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
{(auth?.role === "owner" || user?.canDeleteServices) && (
|
||||
<DeleteService id={redisId} type="redis" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,7 @@ export async function getServerSideProps(
|
||||
}
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function getServerSideProps(
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -34,7 +34,7 @@ export async function getServerSideProps(
|
||||
};
|
||||
}
|
||||
const { user, session } = await validateRequest(ctx.req, ctx.res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function getServerSideProps(
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -51,7 +51,7 @@ export async function getServerSideProps(
|
||||
await helpers.settings.isCloud.prefetch();
|
||||
const auth = await helpers.auth.get.fetch();
|
||||
|
||||
if (auth.rol === "user") {
|
||||
if (auth.role === "member") {
|
||||
const user = await helpers.user.byAuthId.fetch({
|
||||
authId: auth.id,
|
||||
});
|
||||
|
||||
@@ -190,7 +190,7 @@ export async function getServerSideProps(
|
||||
},
|
||||
};
|
||||
}
|
||||
if (user.rol === "user") {
|
||||
if (user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function getServerSideProps(
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -19,7 +19,7 @@ const Page = () => {
|
||||
authId: data?.id || "",
|
||||
},
|
||||
{
|
||||
enabled: !!data?.id && data?.rol === "user",
|
||||
enabled: !!data?.id && data?.role === "user",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -28,7 +28,7 @@ const Page = () => {
|
||||
<div className="w-full">
|
||||
<div className="h-full rounded-xl max-w-5xl mx-auto flex flex-col gap-4">
|
||||
<ProfileForm />
|
||||
{(user?.canAccessToAPI || data?.rol === "admin") && <GenerateToken />}
|
||||
{(user?.canAccessToAPI || data?.role === "owner") && <GenerateToken />}
|
||||
|
||||
{isCloud && <RemoveSelfAccount />}
|
||||
</div>
|
||||
@@ -62,7 +62,7 @@ export async function getServerSideProps(
|
||||
|
||||
await helpers.settings.isCloud.prefetch();
|
||||
await helpers.auth.get.prefetch();
|
||||
if (user?.rol === "user") {
|
||||
if (user?.role === "user") {
|
||||
await helpers.user.byAuthId.prefetch({
|
||||
authId: user.authId,
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function getServerSideProps(
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -107,7 +107,7 @@ export async function getServerSideProps(
|
||||
},
|
||||
};
|
||||
}
|
||||
if (user.rol === "user") {
|
||||
if (user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -36,7 +36,7 @@ export async function getServerSideProps(
|
||||
},
|
||||
};
|
||||
}
|
||||
if (user.rol === "user") {
|
||||
if (user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -51,7 +51,7 @@ export async function getServerSideProps(
|
||||
const auth = await helpers.auth.get.fetch();
|
||||
await helpers.settings.isCloud.prefetch();
|
||||
|
||||
if (auth.rol === "user") {
|
||||
if (auth.role === "member") {
|
||||
const user = await helpers.user.byAuthId.fetch({
|
||||
authId: auth.id,
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function getServerSideProps(
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
if (!user || user.rol === "user") {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -53,7 +53,7 @@ export async function getServerSideProps(
|
||||
await helpers.project.all.prefetch();
|
||||
const auth = await helpers.auth.get.fetch();
|
||||
|
||||
if (auth.rol === "user") {
|
||||
if (auth.role === "member") {
|
||||
const user = await helpers.user.byAuthId.fetch({
|
||||
authId: auth.id,
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ export async function getServerSideProps(
|
||||
await helpers.project.all.prefetch();
|
||||
const auth = await helpers.auth.get.fetch();
|
||||
|
||||
if (auth.rol === "user") {
|
||||
if (auth.role === "member") {
|
||||
const user = await helpers.user.byAuthId.fetch({
|
||||
authId: auth.id,
|
||||
});
|
||||
|
||||
@@ -13,10 +13,14 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { api } from "@/utils/api";
|
||||
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
|
||||
import { IS_CLOUD, auth, isAdminPresent } from "@dokploy/server";
|
||||
import { validateRequest } from "@dokploy/server/lib/auth";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Session, getSessionCookie } from "better-auth";
|
||||
import { betterFetch } from "better-auth/react";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
@@ -56,17 +60,18 @@ interface Props {
|
||||
IS_CLOUD: boolean;
|
||||
}
|
||||
export default function Home({ IS_CLOUD }: Props) {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isError, setIsError] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [temp, setTemp] = useState<AuthResponse>({
|
||||
is2FAEnabled: false,
|
||||
authId: "",
|
||||
});
|
||||
const { mutateAsync, isLoading, error, isError } =
|
||||
api.auth.login.useMutation();
|
||||
const router = useRouter();
|
||||
const form = useForm<Login>({
|
||||
defaultValues: {
|
||||
email: "",
|
||||
password: "",
|
||||
email: "siumauricio@hotmail.com",
|
||||
password: "Password123",
|
||||
},
|
||||
resolver: zodResolver(loginSchema),
|
||||
});
|
||||
@@ -76,25 +81,49 @@ export default function Home({ IS_CLOUD }: Props) {
|
||||
}, [form, form.reset, form.formState.isSubmitSuccessful]);
|
||||
|
||||
const onSubmit = async (values: Login) => {
|
||||
await mutateAsync({
|
||||
email: values.email.toLowerCase(),
|
||||
setIsLoading(true);
|
||||
const { data, error } = await authClient.signIn.email({
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
})
|
||||
.then((data) => {
|
||||
if (data.is2FAEnabled) {
|
||||
setTemp(data);
|
||||
} else {
|
||||
toast.success("Successfully signed in", {
|
||||
duration: 2000,
|
||||
});
|
||||
router.push("/dashboard/projects");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Signin failed", {
|
||||
duration: 2000,
|
||||
});
|
||||
});
|
||||
|
||||
if (!error) {
|
||||
// if (data) {
|
||||
// setTemp(data);
|
||||
// } else {
|
||||
toast.success("Successfully signed in", {
|
||||
duration: 2000,
|
||||
});
|
||||
router.push("/dashboard/projects");
|
||||
// }
|
||||
} else {
|
||||
setIsError(true);
|
||||
setError(error.message ?? "Error to signup");
|
||||
toast.error("Error to sign up", {
|
||||
description: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
// await mutateAsync({
|
||||
// email: values.email.toLowerCase(),
|
||||
// password: values.password,
|
||||
// })
|
||||
// .then((data) => {
|
||||
// if (data.is2FAEnabled) {
|
||||
// setTemp(data);
|
||||
// } else {
|
||||
// toast.success("Successfully signed in", {
|
||||
// duration: 2000,
|
||||
// });
|
||||
// router.push("/dashboard/projects");
|
||||
// }
|
||||
// })
|
||||
// .catch(() => {
|
||||
// toast.error("Signin failed", {
|
||||
// duration: 2000,
|
||||
// });
|
||||
// });
|
||||
};
|
||||
return (
|
||||
<>
|
||||
@@ -111,7 +140,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
||||
</div>
|
||||
{isError && (
|
||||
<AlertBlock type="error" className="my-2">
|
||||
<span>{error?.message}</span>
|
||||
<span>{error}</span>
|
||||
</AlertBlock>
|
||||
)}
|
||||
<CardContent className="p-0">
|
||||
@@ -203,8 +232,7 @@ Home.getLayout = (page: ReactElement) => {
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
if (IS_CLOUD) {
|
||||
try {
|
||||
const { user } = await validateRequest(context.req, context.res);
|
||||
|
||||
const { user } = await validateRequest(context.req);
|
||||
if (user) {
|
||||
return {
|
||||
redirect: {
|
||||
@@ -232,7 +260,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
};
|
||||
}
|
||||
|
||||
const { user } = await validateRequest(context.req, context.res);
|
||||
const { user } = await validateRequest(context.req);
|
||||
|
||||
if (user) {
|
||||
return {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { authClient } from "@/lib/auth";
|
||||
import { api } from "@/utils/api";
|
||||
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -31,6 +32,9 @@ import { z } from "zod";
|
||||
|
||||
const registerSchema = z
|
||||
.object({
|
||||
name: z.string().min(1, {
|
||||
message: "Name is required",
|
||||
}),
|
||||
email: z
|
||||
.string()
|
||||
.min(1, {
|
||||
@@ -79,9 +83,10 @@ const Register = ({ isCloud }: Props) => {
|
||||
|
||||
const form = useForm<Register>({
|
||||
defaultValues: {
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
name: "Mauricio Siu",
|
||||
email: "user5@yopmail.com",
|
||||
password: "Password1234",
|
||||
confirmPassword: "Password1234",
|
||||
},
|
||||
resolver: zodResolver(registerSchema),
|
||||
});
|
||||
@@ -91,19 +96,33 @@ const Register = ({ isCloud }: Props) => {
|
||||
}, [form, form.reset, form.formState.isSubmitSuccessful]);
|
||||
|
||||
const onSubmit = async (values: Register) => {
|
||||
await mutateAsync({
|
||||
email: values.email.toLowerCase(),
|
||||
const { data, error } = await authClient.signUp.email({
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
})
|
||||
.then(() => {
|
||||
toast.success("User registered successfuly", {
|
||||
duration: 2000,
|
||||
});
|
||||
if (!isCloud) {
|
||||
router.push("/");
|
||||
}
|
||||
})
|
||||
.catch((e) => e);
|
||||
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);
|
||||
};
|
||||
return (
|
||||
<div className="">
|
||||
@@ -147,6 +166,19 @@ const Register = ({ isCloud }: Props) => {
|
||||
className="grid gap-4"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="name" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="email"
|
||||
|
||||
@@ -58,7 +58,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
},
|
||||
transformer: superjson,
|
||||
});
|
||||
if (user.rol === "user") {
|
||||
if (user.role === "member") {
|
||||
const result = await helpers.user.byAuthId.fetch({
|
||||
authId: user.id,
|
||||
});
|
||||
|
||||
@@ -6,19 +6,17 @@ import {
|
||||
apiRemoveUser,
|
||||
apiUpdateAdmin,
|
||||
apiUpdateWebServerMonitoring,
|
||||
users,
|
||||
} from "@/server/db/schema";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
createInvitation,
|
||||
findAdminById,
|
||||
findUserByAuthId,
|
||||
findUserById,
|
||||
getUserByToken,
|
||||
removeUserByAuthId,
|
||||
removeUserById,
|
||||
setupWebMonitoring,
|
||||
updateAdmin,
|
||||
updateAdminById,
|
||||
updateUser,
|
||||
} from "@dokploy/server";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
@@ -32,7 +30,7 @@ import {
|
||||
|
||||
export const adminRouter = createTRPCRouter({
|
||||
one: adminProcedure.query(async ({ ctx }) => {
|
||||
const { sshPrivateKey, ...rest } = await findAdminById(ctx.user.adminId);
|
||||
const { sshPrivateKey, ...rest } = await findUserById(ctx.user.id);
|
||||
return {
|
||||
haveSSH: !!sshPrivateKey,
|
||||
...rest,
|
||||
@@ -41,21 +39,21 @@ export const adminRouter = createTRPCRouter({
|
||||
update: adminProcedure
|
||||
.input(apiUpdateAdmin)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
if (ctx.user.rol === "member") {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to update this admin",
|
||||
});
|
||||
}
|
||||
const { authId } = await findAdminById(ctx.user.adminId);
|
||||
const { id } = await findUserById(ctx.user.id);
|
||||
// @ts-ignore
|
||||
return updateAdmin(authId, input);
|
||||
return updateAdmin(id, input);
|
||||
}),
|
||||
createUserInvitation: adminProcedure
|
||||
.input(apiCreateUserInvitation)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
await createInvitation(input, ctx.user.adminId);
|
||||
await createInvitation(input, ctx.user.id);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -69,15 +67,16 @@ export const adminRouter = createTRPCRouter({
|
||||
.input(apiRemoveUser)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const user = await findUserByAuthId(input.authId);
|
||||
const user = await findUserById(input.id);
|
||||
|
||||
if (user.adminId !== ctx.user.adminId) {
|
||||
if (user.id !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to delete this user",
|
||||
});
|
||||
}
|
||||
return await removeUserByAuthId(input.authId);
|
||||
|
||||
return await removeUserById(input.id);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -95,20 +94,23 @@ export const adminRouter = createTRPCRouter({
|
||||
.input(apiAssignPermissions)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const user = await findUserById(input.userId);
|
||||
const user = await findUserById(input.id);
|
||||
|
||||
if (user.adminId !== ctx.user.adminId) {
|
||||
if (user.id !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to assign permissions",
|
||||
});
|
||||
}
|
||||
await db
|
||||
.update(users)
|
||||
.set({
|
||||
...input,
|
||||
})
|
||||
.where(eq(users.userId, input.userId));
|
||||
await updateUser(user.id, {
|
||||
...input,
|
||||
});
|
||||
// await db
|
||||
// .update(users)
|
||||
// .set({
|
||||
// ...input,
|
||||
// })
|
||||
// .where(eq(users.userId, input.userId));
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
@@ -124,15 +126,15 @@ export const adminRouter = createTRPCRouter({
|
||||
message: "Feature disabled on cloud",
|
||||
});
|
||||
}
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
if (admin.adminId !== ctx.user.adminId) {
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
if (user.id !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to setup this server",
|
||||
});
|
||||
}
|
||||
|
||||
await updateAdminById(admin.adminId, {
|
||||
await updateUser(user.id, {
|
||||
metricsConfig: {
|
||||
server: {
|
||||
type: "Dokploy",
|
||||
@@ -156,18 +158,19 @@ export const adminRouter = createTRPCRouter({
|
||||
},
|
||||
},
|
||||
});
|
||||
const currentServer = await setupWebMonitoring(admin.adminId);
|
||||
|
||||
const currentServer = await setupWebMonitoring(user.id);
|
||||
return currentServer;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}),
|
||||
getMetricsToken: protectedProcedure.query(async ({ ctx }) => {
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
return {
|
||||
serverIp: admin.serverIp,
|
||||
enabledFeatures: admin.enablePaidFeatures,
|
||||
metricsConfig: admin?.metricsConfig,
|
||||
serverIp: user.serverIp,
|
||||
enabledFeatures: user.enablePaidFeatures,
|
||||
metricsConfig: user?.metricsConfig,
|
||||
};
|
||||
}),
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiCreateApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -72,7 +72,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
}
|
||||
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
@@ -80,8 +80,8 @@ export const applicationRouter = createTRPCRouter({
|
||||
}
|
||||
const newApplication = await createApplication(input);
|
||||
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newApplication.applicationId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newApplication.applicationId);
|
||||
}
|
||||
return newApplication;
|
||||
} catch (error: unknown) {
|
||||
@@ -98,15 +98,11 @@ export const applicationRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOneApplication)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(
|
||||
ctx.user.authId,
|
||||
input.applicationId,
|
||||
"access",
|
||||
);
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.applicationId, "access");
|
||||
}
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -119,7 +115,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiReloadApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to reload this application",
|
||||
@@ -144,16 +140,12 @@ export const applicationRouter = createTRPCRouter({
|
||||
delete: protectedProcedure
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(
|
||||
ctx.user.authId,
|
||||
input.applicationId,
|
||||
"delete",
|
||||
);
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.applicationId, "delete");
|
||||
}
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this application",
|
||||
@@ -194,7 +186,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const service = await findApplicationById(input.applicationId);
|
||||
if (service.project.adminId !== ctx.user.adminId) {
|
||||
if (service.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this application",
|
||||
@@ -214,7 +206,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const service = await findApplicationById(input.applicationId);
|
||||
if (service.project.adminId !== ctx.user.adminId) {
|
||||
if (service.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to start this application",
|
||||
@@ -235,7 +227,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to redeploy this application",
|
||||
@@ -268,7 +260,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveEnvironmentVariables)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this environment",
|
||||
@@ -284,7 +276,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveBuildType)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this build type",
|
||||
@@ -305,7 +297,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveGithubProvider)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this github provider",
|
||||
@@ -327,7 +319,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveGitlabProvider)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this gitlab provider",
|
||||
@@ -351,7 +343,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveBitbucketProvider)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this bitbucket provider",
|
||||
@@ -373,7 +365,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveDockerProvider)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this docker provider",
|
||||
@@ -394,7 +386,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiSaveGitProvider)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this git provider",
|
||||
@@ -415,7 +407,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to mark this application as running",
|
||||
@@ -427,7 +419,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiUpdateApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this application",
|
||||
@@ -451,7 +443,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to refresh this application",
|
||||
@@ -466,7 +458,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this application",
|
||||
@@ -500,7 +492,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to clean this application",
|
||||
@@ -513,7 +505,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to read this application",
|
||||
@@ -548,7 +540,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
|
||||
const app = await findApplicationById(input.applicationId as string);
|
||||
|
||||
if (app.project.adminId !== ctx.user.adminId) {
|
||||
if (app.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this application",
|
||||
@@ -590,7 +582,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this application",
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
apiVerify2FA,
|
||||
apiVerifyLogin2FA,
|
||||
auth,
|
||||
member,
|
||||
} from "@/server/db/schema";
|
||||
import { WEBSITE_URL } from "@/server/utils/stripe";
|
||||
import {
|
||||
@@ -16,22 +17,23 @@ import {
|
||||
createUser,
|
||||
findAuthByEmail,
|
||||
findAuthById,
|
||||
findUserById,
|
||||
generate2FASecret,
|
||||
getUserByToken,
|
||||
lucia,
|
||||
luciaToken,
|
||||
removeAdminByAuthId,
|
||||
removeUserByAuthId,
|
||||
sendDiscordNotification,
|
||||
sendEmailNotification,
|
||||
updateAuthById,
|
||||
updateUser,
|
||||
validateRequest,
|
||||
verify2FA,
|
||||
} from "@dokploy/server";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import { isBefore } from "date-fns";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { db } from "../../db";
|
||||
@@ -169,8 +171,17 @@ export const authRouter = createTRPCRouter({
|
||||
}),
|
||||
|
||||
get: protectedProcedure.query(async ({ ctx }) => {
|
||||
const auth = await findAuthById(ctx.user.authId);
|
||||
return auth;
|
||||
const memberResult = await db.query.member.findFirst({
|
||||
where: and(
|
||||
eq(member.userId, ctx.user.id),
|
||||
eq(member.organizationId, ctx.session?.activeOrganizationId || ""),
|
||||
),
|
||||
with: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
|
||||
return memberResult;
|
||||
}),
|
||||
|
||||
logout: protectedProcedure.mutation(async ({ ctx }) => {
|
||||
@@ -243,7 +254,7 @@ export const authRouter = createTRPCRouter({
|
||||
await lucia.invalidateSession(session.id);
|
||||
res.setHeader("Set-Cookie", lucia.createBlankSessionCookie().serialize());
|
||||
|
||||
if (ctx.user.rol === "admin") {
|
||||
if (ctx.user.rol === "owner") {
|
||||
await removeAdminByAuthId(ctx.user.authId);
|
||||
} else {
|
||||
await removeUserByAuthId(ctx.user.authId);
|
||||
@@ -253,19 +264,18 @@ export const authRouter = createTRPCRouter({
|
||||
}),
|
||||
|
||||
generateToken: protectedProcedure.mutation(async ({ ctx, input }) => {
|
||||
const auth = await findAuthById(ctx.user.authId);
|
||||
const auth = await findUserById(ctx.user.id);
|
||||
console.log(auth);
|
||||
|
||||
if (auth.token) {
|
||||
await luciaToken.invalidateSession(auth.token);
|
||||
}
|
||||
const session = await luciaToken.createSession(auth?.id || "", {
|
||||
expiresIn: 60 * 60 * 24 * 30,
|
||||
});
|
||||
|
||||
await updateAuthById(auth.id, {
|
||||
token: session.id,
|
||||
});
|
||||
|
||||
// const session = await luciaToken.createSession(auth?.id || "", {
|
||||
// expiresIn: 60 * 60 * 24 * 30,
|
||||
// });
|
||||
// await updateUser(auth.id, {
|
||||
// token: session.id,
|
||||
// });
|
||||
return auth;
|
||||
}),
|
||||
verifyToken: protectedProcedure.mutation(async () => {
|
||||
@@ -277,7 +287,7 @@ export const authRouter = createTRPCRouter({
|
||||
}),
|
||||
|
||||
generate2FASecret: protectedProcedure.query(async ({ ctx }) => {
|
||||
return await generate2FASecret(ctx.user.authId);
|
||||
return await generate2FASecret(ctx.user.id);
|
||||
}),
|
||||
verify2FASetup: protectedProcedure
|
||||
.input(apiVerify2FA)
|
||||
|
||||
@@ -23,7 +23,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
.input(apiCreateBitbucket)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createBitbucket(input, ctx.user.adminId);
|
||||
return await createBitbucket(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -38,7 +38,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -61,7 +61,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
if (IS_CLOUD) {
|
||||
// TODO: mAyBe a rEfaCtoR 🤫
|
||||
result = result.filter(
|
||||
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
|
||||
(provider) => provider.gitProvider.userId === ctx.user.ownerId,
|
||||
);
|
||||
}
|
||||
return result;
|
||||
@@ -73,7 +73,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -91,7 +91,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -108,7 +108,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -132,7 +132,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -142,7 +142,7 @@ export const bitbucketRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateBitbucket(input.bitbucketId, {
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -25,14 +25,14 @@ export const certificateRouter = createTRPCRouter({
|
||||
message: "Please set a server to create a certificate",
|
||||
});
|
||||
}
|
||||
return await createCertificate(input, ctx.user.adminId);
|
||||
return await createCertificate(input, ctx.user.ownerId);
|
||||
}),
|
||||
|
||||
one: adminProcedure
|
||||
.input(apiFindCertificate)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const certificates = await findCertificateById(input.certificateId);
|
||||
if (IS_CLOUD && certificates.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && certificates.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this certificate",
|
||||
@@ -44,7 +44,7 @@ export const certificateRouter = createTRPCRouter({
|
||||
.input(apiFindCertificate)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const certificates = await findCertificateById(input.certificateId);
|
||||
if (IS_CLOUD && certificates.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && certificates.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to delete this certificate",
|
||||
@@ -56,7 +56,7 @@ export const certificateRouter = createTRPCRouter({
|
||||
all: adminProcedure.query(async ({ ctx }) => {
|
||||
return await db.query.certificates.findMany({
|
||||
// TODO: Remove this line when the cloud version is ready
|
||||
...(IS_CLOUD && { where: eq(certificates.adminId, ctx.user.adminId) }),
|
||||
...(IS_CLOUD && { where: eq(certificates.userId, ctx.user.ownerId) }),
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
findDomainsByComposeId,
|
||||
findProjectById,
|
||||
findServerById,
|
||||
findUserById,
|
||||
loadServices,
|
||||
randomizeComposeFile,
|
||||
randomizeIsolatedDeploymentComposeFile,
|
||||
@@ -60,8 +61,8 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiCreateCompose)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -71,7 +72,7 @@ export const composeRouter = createTRPCRouter({
|
||||
});
|
||||
}
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
@@ -79,8 +80,8 @@ export const composeRouter = createTRPCRouter({
|
||||
}
|
||||
const newService = await createCompose(input);
|
||||
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newService.composeId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newService.composeId);
|
||||
}
|
||||
|
||||
return newService;
|
||||
@@ -92,12 +93,12 @@ export const composeRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindCompose)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.composeId, "access");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.composeId, "access");
|
||||
}
|
||||
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
@@ -110,7 +111,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiUpdateCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this compose",
|
||||
@@ -121,12 +122,12 @@ export const composeRouter = createTRPCRouter({
|
||||
delete: protectedProcedure
|
||||
.input(apiDeleteCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.composeId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.composeId, "delete");
|
||||
}
|
||||
const composeResult = await findComposeById(input.composeId);
|
||||
|
||||
if (composeResult.project.adminId !== ctx.user.adminId) {
|
||||
if (composeResult.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this compose",
|
||||
@@ -157,7 +158,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to clean this compose",
|
||||
@@ -170,7 +171,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFetchServices)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to load this compose",
|
||||
@@ -184,7 +185,7 @@ export const composeRouter = createTRPCRouter({
|
||||
try {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to fetch this compose",
|
||||
@@ -209,7 +210,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiRandomizeCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to randomize this compose",
|
||||
@@ -221,7 +222,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiRandomizeCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to randomize this compose",
|
||||
@@ -236,7 +237,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to get this compose",
|
||||
@@ -254,7 +255,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this compose",
|
||||
@@ -287,7 +288,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to redeploy this compose",
|
||||
@@ -319,7 +320,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this compose",
|
||||
@@ -333,7 +334,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this compose",
|
||||
@@ -348,7 +349,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to get this compose",
|
||||
@@ -361,7 +362,7 @@ export const composeRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to refresh this compose",
|
||||
@@ -375,8 +376,8 @@ export const composeRouter = createTRPCRouter({
|
||||
deployTemplate: protectedProcedure
|
||||
.input(apiCreateComposeByTemplate)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -390,7 +391,7 @@ export const composeRouter = createTRPCRouter({
|
||||
|
||||
const generate = await loadTemplateModule(input.id as TemplatesKeys);
|
||||
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const admin = await findUserById(ctx.user.ownerId);
|
||||
let serverIp = admin.serverIp || "127.0.0.1";
|
||||
|
||||
const project = await findProjectById(input.projectId);
|
||||
@@ -418,8 +419,8 @@ export const composeRouter = createTRPCRouter({
|
||||
isolatedDeployment: true,
|
||||
});
|
||||
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, compose.composeId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, compose.composeId);
|
||||
}
|
||||
|
||||
if (mounts && mounts?.length > 0) {
|
||||
|
||||
@@ -19,7 +19,7 @@ export const deploymentRouter = createTRPCRouter({
|
||||
.input(apiFindAllByApplication)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -32,7 +32,7 @@ export const deploymentRouter = createTRPCRouter({
|
||||
.input(apiFindAllByCompose)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
@@ -44,7 +44,7 @@ export const deploymentRouter = createTRPCRouter({
|
||||
.input(apiFindAllByServer)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this server",
|
||||
|
||||
@@ -28,7 +28,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
.input(apiCreateDestination)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createDestintation(input, ctx.user.adminId);
|
||||
return await createDestintation(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -84,7 +84,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
.input(apiFindOneDestination)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const destination = await findDestinationById(input.destinationId);
|
||||
if (destination.adminId !== ctx.user.adminId) {
|
||||
if (destination.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this destination",
|
||||
@@ -94,7 +94,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
}),
|
||||
all: protectedProcedure.query(async ({ ctx }) => {
|
||||
return await db.query.destinations.findMany({
|
||||
where: eq(destinations.adminId, ctx.user.adminId),
|
||||
where: eq(destinations.userId, ctx.user.ownerId),
|
||||
});
|
||||
}),
|
||||
remove: adminProcedure
|
||||
@@ -103,7 +103,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
try {
|
||||
const destination = await findDestinationById(input.destinationId);
|
||||
|
||||
if (destination.adminId !== ctx.user.adminId) {
|
||||
if (destination.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to delete this destination",
|
||||
@@ -111,7 +111,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
}
|
||||
return await removeDestinationById(
|
||||
input.destinationId,
|
||||
ctx.user.adminId,
|
||||
ctx.user.ownerId,
|
||||
);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
@@ -122,7 +122,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const destination = await findDestinationById(input.destinationId);
|
||||
if (destination.adminId !== ctx.user.adminId) {
|
||||
if (destination.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to update this destination",
|
||||
@@ -130,7 +130,7 @@ export const destinationRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateDestinationById(input.destinationId, {
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
|
||||
@@ -30,7 +30,7 @@ export const domainRouter = createTRPCRouter({
|
||||
try {
|
||||
if (input.domainType === "compose" && input.composeId) {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
@@ -38,7 +38,7 @@ export const domainRouter = createTRPCRouter({
|
||||
}
|
||||
} else if (input.domainType === "application" && input.applicationId) {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -58,7 +58,7 @@ export const domainRouter = createTRPCRouter({
|
||||
.input(apiFindOneApplication)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -70,7 +70,7 @@ export const domainRouter = createTRPCRouter({
|
||||
.input(apiFindCompose)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const compose = await findComposeById(input.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
@@ -83,7 +83,7 @@ export const domainRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
return generateTraefikMeDomain(
|
||||
input.appName,
|
||||
ctx.user.adminId,
|
||||
ctx.user.ownerId,
|
||||
input.serverId,
|
||||
);
|
||||
}),
|
||||
@@ -95,7 +95,7 @@ export const domainRouter = createTRPCRouter({
|
||||
|
||||
if (currentDomain.applicationId) {
|
||||
const newApp = await findApplicationById(currentDomain.applicationId);
|
||||
if (newApp.project.adminId !== ctx.user.adminId) {
|
||||
if (newApp.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -103,7 +103,7 @@ export const domainRouter = createTRPCRouter({
|
||||
}
|
||||
} else if (currentDomain.composeId) {
|
||||
const newCompose = await findComposeById(currentDomain.composeId);
|
||||
if (newCompose.project.adminId !== ctx.user.adminId) {
|
||||
if (newCompose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
@@ -114,7 +114,7 @@ export const domainRouter = createTRPCRouter({
|
||||
currentDomain.previewDeploymentId,
|
||||
);
|
||||
if (
|
||||
newPreviewDeployment.application.project.adminId !== ctx.user.adminId
|
||||
newPreviewDeployment.application.project.userId !== ctx.user.ownerId
|
||||
) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -143,7 +143,7 @@ export const domainRouter = createTRPCRouter({
|
||||
const domain = await findDomainById(input.domainId);
|
||||
if (domain.applicationId) {
|
||||
const application = await findApplicationById(domain.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -151,7 +151,7 @@ export const domainRouter = createTRPCRouter({
|
||||
}
|
||||
} else if (domain.composeId) {
|
||||
const compose = await findComposeById(domain.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
@@ -166,7 +166,7 @@ export const domainRouter = createTRPCRouter({
|
||||
const domain = await findDomainById(input.domainId);
|
||||
if (domain.applicationId) {
|
||||
const application = await findApplicationById(domain.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -174,7 +174,7 @@ export const domainRouter = createTRPCRouter({
|
||||
}
|
||||
} else if (domain.composeId) {
|
||||
const compose = await findComposeById(domain.composeId);
|
||||
if (compose.project.adminId !== ctx.user.adminId) {
|
||||
if (compose.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
|
||||
@@ -18,7 +18,7 @@ export const gitProviderRouter = createTRPCRouter({
|
||||
github: true,
|
||||
},
|
||||
orderBy: desc(gitProvider.createdAt),
|
||||
...(IS_CLOUD && { where: eq(gitProvider.adminId, ctx.user.adminId) }),
|
||||
...(IS_CLOUD && { where: eq(gitProvider.userId, ctx.user.ownerId) }),
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
});
|
||||
}),
|
||||
@@ -28,7 +28,7 @@ export const gitProviderRouter = createTRPCRouter({
|
||||
try {
|
||||
const gitProvider = await findGitProviderById(input.gitProviderId);
|
||||
|
||||
if (IS_CLOUD && gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && gitProvider.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
|
||||
@@ -20,7 +20,7 @@ export const githubRouter = createTRPCRouter({
|
||||
.input(apiFindOneGithub)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const githubProvider = await findGithubById(input.githubId);
|
||||
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -33,7 +33,7 @@ export const githubRouter = createTRPCRouter({
|
||||
.input(apiFindOneGithub)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const githubProvider = await findGithubById(input.githubId);
|
||||
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -46,7 +46,7 @@ export const githubRouter = createTRPCRouter({
|
||||
.input(apiFindGithubBranches)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const githubProvider = await findGithubById(input.githubId || "");
|
||||
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -65,7 +65,7 @@ export const githubRouter = createTRPCRouter({
|
||||
if (IS_CLOUD) {
|
||||
// TODO: mAyBe a rEfaCtoR 🤫
|
||||
result = result.filter(
|
||||
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
|
||||
(provider) => provider.gitProvider.userId === ctx.user.ownerId,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ export const githubRouter = createTRPCRouter({
|
||||
const githubProvider = await findGithubById(input.githubId);
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
githubProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
githubProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -111,7 +111,7 @@ export const githubRouter = createTRPCRouter({
|
||||
.input(apiUpdateGithub)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const githubProvider = await findGithubById(input.githubId);
|
||||
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -120,7 +120,7 @@ export const githubRouter = createTRPCRouter({
|
||||
}
|
||||
await updateGitProvider(input.gitProviderId, {
|
||||
name: input.name,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
.input(apiCreateGitlab)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createGitlab(input, ctx.user.adminId);
|
||||
return await createGitlab(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -39,7 +39,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
.input(apiFindOneGitlab)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const gitlabProvider = await findGitlabById(input.gitlabId);
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -58,7 +58,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
if (IS_CLOUD) {
|
||||
// TODO: mAyBe a rEfaCtoR 🤫
|
||||
result = result.filter(
|
||||
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
|
||||
(provider) => provider.gitProvider.userId === ctx.user.ownerId,
|
||||
);
|
||||
}
|
||||
const filtered = result
|
||||
@@ -78,7 +78,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
.input(apiFindOneGitlab)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const gitlabProvider = await findGitlabById(input.gitlabId);
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -92,7 +92,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
.input(apiFindGitlabBranches)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const gitlabProvider = await findGitlabById(input.gitlabId || "");
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -108,7 +108,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
const gitlabProvider = await findGitlabById(input.gitlabId || "");
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
gitlabProvider.gitProvider.adminId !== ctx.user.adminId
|
||||
gitlabProvider.gitProvider.userId !== ctx.user.ownerId
|
||||
) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
@@ -130,7 +130,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
.input(apiUpdateGitlab)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const gitlabProvider = await findGitlabById(input.gitlabId);
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
|
||||
//TODO: Remove this line when the cloud version is ready
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -140,7 +140,7 @@ export const gitlabRouter = createTRPCRouter({
|
||||
if (input.name) {
|
||||
await updateGitProvider(input.gitProviderId, {
|
||||
name: input.name,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
|
||||
await updateGitlab(input.gitlabId, {
|
||||
|
||||
@@ -37,8 +37,8 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiCreateMariaDB)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -49,15 +49,15 @@ export const mariadbRouter = createTRPCRouter({
|
||||
}
|
||||
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
});
|
||||
}
|
||||
const newMariadb = await createMariadb(input);
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newMariadb.mariadbId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newMariadb.mariadbId);
|
||||
}
|
||||
|
||||
await createMount({
|
||||
@@ -79,11 +79,11 @@ export const mariadbRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOneMariaDB)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.mariadbId, "access");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.mariadbId, "access");
|
||||
}
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
if (mariadb.project.adminId !== ctx.user.adminId) {
|
||||
if (mariadb.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this Mariadb",
|
||||
@@ -96,7 +96,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiFindOneMariaDB)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const service = await findMariadbById(input.mariadbId);
|
||||
if (service.project.adminId !== ctx.user.adminId) {
|
||||
if (service.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to start this Mariadb",
|
||||
@@ -133,7 +133,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiSaveExternalPortMariaDB)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMariadbById(input.mariadbId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this external port",
|
||||
@@ -149,7 +149,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiDeployMariaDB)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
if (mariadb.project.adminId !== ctx.user.adminId) {
|
||||
if (mariadb.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this Mariadb",
|
||||
@@ -170,7 +170,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiDeployMariaDB)
|
||||
.subscription(async ({ input, ctx }) => {
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
if (mariadb.project.adminId !== ctx.user.adminId) {
|
||||
if (mariadb.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this Mariadb",
|
||||
@@ -187,7 +187,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiChangeMariaDBStatus)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMariadbById(input.mariadbId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to change this Mariadb status",
|
||||
@@ -201,12 +201,12 @@ export const mariadbRouter = createTRPCRouter({
|
||||
remove: protectedProcedure
|
||||
.input(apiFindOneMariaDB)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.mariadbId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.mariadbId, "delete");
|
||||
}
|
||||
|
||||
const mongo = await findMariadbById(input.mariadbId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this Mariadb",
|
||||
@@ -232,7 +232,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiSaveEnvironmentVariablesMariaDB)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
if (mariadb.project.adminId !== ctx.user.adminId) {
|
||||
if (mariadb.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this environment",
|
||||
@@ -255,7 +255,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.input(apiResetMariadb)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mariadb = await findMariadbById(input.mariadbId);
|
||||
if (mariadb.project.adminId !== ctx.user.adminId) {
|
||||
if (mariadb.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to reload this Mariadb",
|
||||
@@ -285,7 +285,7 @@ export const mariadbRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { mariadbId, ...rest } = input;
|
||||
const mariadb = await findMariadbById(mariadbId);
|
||||
if (mariadb.project.adminId !== ctx.user.adminId) {
|
||||
if (mariadb.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this Mariadb",
|
||||
|
||||
@@ -36,8 +36,8 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiCreateMongo)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -48,15 +48,15 @@ export const mongoRouter = createTRPCRouter({
|
||||
}
|
||||
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
});
|
||||
}
|
||||
const newMongo = await createMongo(input);
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newMongo.mongoId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newMongo.mongoId);
|
||||
}
|
||||
|
||||
await createMount({
|
||||
@@ -82,12 +82,12 @@ export const mongoRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOneMongo)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.mongoId, "access");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.mongoId, "access");
|
||||
}
|
||||
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this mongo",
|
||||
@@ -101,7 +101,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const service = await findMongoById(input.mongoId);
|
||||
|
||||
if (service.project.adminId !== ctx.user.adminId) {
|
||||
if (service.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to start this mongo",
|
||||
@@ -124,7 +124,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this mongo",
|
||||
@@ -146,7 +146,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiSaveExternalPortMongo)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this external port",
|
||||
@@ -162,7 +162,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiDeployMongo)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this mongo",
|
||||
@@ -182,7 +182,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiDeployMongo)
|
||||
.subscription(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this mongo",
|
||||
@@ -199,7 +199,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiChangeMongoStatus)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to change this mongo status",
|
||||
@@ -214,7 +214,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiResetMongo)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to reload this mongo",
|
||||
@@ -242,13 +242,13 @@ export const mongoRouter = createTRPCRouter({
|
||||
remove: protectedProcedure
|
||||
.input(apiFindOneMongo)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.mongoId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.mongoId, "delete");
|
||||
}
|
||||
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this mongo",
|
||||
@@ -274,7 +274,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.input(apiSaveEnvironmentVariablesMongo)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMongoById(input.mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this environment",
|
||||
@@ -298,7 +298,7 @@ export const mongoRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { mongoId, ...rest } = input;
|
||||
const mongo = await findMongoById(mongoId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this mongo",
|
||||
|
||||
@@ -38,8 +38,8 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiCreateMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -50,7 +50,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
}
|
||||
1;
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
@@ -58,8 +58,8 @@ export const mysqlRouter = createTRPCRouter({
|
||||
}
|
||||
|
||||
const newMysql = await createMysql(input);
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newMysql.mysqlId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newMysql.mysqlId);
|
||||
}
|
||||
|
||||
await createMount({
|
||||
@@ -85,11 +85,11 @@ export const mysqlRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOneMySql)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.mysqlId, "access");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.mysqlId, "access");
|
||||
}
|
||||
const mysql = await findMySqlById(input.mysqlId);
|
||||
if (mysql.project.adminId !== ctx.user.adminId) {
|
||||
if (mysql.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this MySQL",
|
||||
@@ -102,7 +102,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiFindOneMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const service = await findMySqlById(input.mysqlId);
|
||||
if (service.project.adminId !== ctx.user.adminId) {
|
||||
if (service.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to start this MySQL",
|
||||
@@ -124,7 +124,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiFindOneMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMySqlById(input.mysqlId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this MySQL",
|
||||
@@ -145,7 +145,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiSaveExternalPortMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMySqlById(input.mysqlId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this external port",
|
||||
@@ -161,7 +161,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiDeployMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mysql = await findMySqlById(input.mysqlId);
|
||||
if (mysql.project.adminId !== ctx.user.adminId) {
|
||||
if (mysql.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this MySQL",
|
||||
@@ -181,7 +181,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiDeployMySql)
|
||||
.subscription(async ({ input, ctx }) => {
|
||||
const mysql = await findMySqlById(input.mysqlId);
|
||||
if (mysql.project.adminId !== ctx.user.adminId) {
|
||||
if (mysql.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this MySQL",
|
||||
@@ -198,7 +198,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiChangeMySqlStatus)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findMySqlById(input.mysqlId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to change this MySQL status",
|
||||
@@ -213,7 +213,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiResetMysql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mysql = await findMySqlById(input.mysqlId);
|
||||
if (mysql.project.adminId !== ctx.user.adminId) {
|
||||
if (mysql.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to reload this MySQL",
|
||||
@@ -240,11 +240,11 @@ export const mysqlRouter = createTRPCRouter({
|
||||
remove: protectedProcedure
|
||||
.input(apiFindOneMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.mysqlId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.mysqlId, "delete");
|
||||
}
|
||||
const mongo = await findMySqlById(input.mysqlId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this MySQL",
|
||||
@@ -270,7 +270,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.input(apiSaveEnvironmentVariablesMySql)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mysql = await findMySqlById(input.mysqlId);
|
||||
if (mysql.project.adminId !== ctx.user.adminId) {
|
||||
if (mysql.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this environment",
|
||||
@@ -294,7 +294,7 @@ export const mysqlRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { mysqlId, ...rest } = input;
|
||||
const mysql = await findMySqlById(mysqlId);
|
||||
if (mysql.project.adminId !== ctx.user.adminId) {
|
||||
if (mysql.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this MySQL",
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
} from "@/server/api/trpc";
|
||||
import { db } from "@/server/db";
|
||||
import {
|
||||
admins,
|
||||
apiCreateDiscord,
|
||||
apiCreateEmail,
|
||||
apiCreateGotify,
|
||||
@@ -25,6 +24,7 @@ import {
|
||||
apiUpdateTelegram,
|
||||
notifications,
|
||||
server,
|
||||
users_temp,
|
||||
} from "@/server/db/schema";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
@@ -57,7 +57,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.input(apiCreateSlack)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createSlackNotification(input, ctx.user.adminId);
|
||||
return await createSlackNotification(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -71,7 +71,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -80,7 +80,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateSlackNotification({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
@@ -107,7 +107,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.input(apiCreateTelegram)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createTelegramNotification(input, ctx.user.adminId);
|
||||
return await createTelegramNotification(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -122,7 +122,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -131,7 +131,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateTelegramNotification({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -159,7 +159,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.input(apiCreateDiscord)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createDiscordNotification(input, ctx.user.adminId);
|
||||
return await createDiscordNotification(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -174,7 +174,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -183,7 +183,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateDiscordNotification({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -220,7 +220,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.input(apiCreateEmail)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createEmailNotification(input, ctx.user.adminId);
|
||||
return await createEmailNotification(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -234,7 +234,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -243,7 +243,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateEmailNotification({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -276,7 +276,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -295,7 +295,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.input(apiFindOneNotification)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -314,7 +314,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
gotify: true,
|
||||
},
|
||||
orderBy: desc(notifications.createdAt),
|
||||
...(IS_CLOUD && { where: eq(notifications.adminId, ctx.user.adminId) }),
|
||||
...(IS_CLOUD && { where: eq(notifications.userId, ctx.user.ownerId) }),
|
||||
// TODO: Remove this line when the cloud version is ready
|
||||
});
|
||||
}),
|
||||
@@ -332,24 +332,24 @@ export const notificationRouter = createTRPCRouter({
|
||||
)
|
||||
.mutation(async ({ input }) => {
|
||||
try {
|
||||
let adminId = "";
|
||||
let userId = "";
|
||||
let ServerName = "";
|
||||
if (input.ServerType === "Dokploy") {
|
||||
const result = await db
|
||||
.select()
|
||||
.from(admins)
|
||||
.from(users_temp)
|
||||
.where(
|
||||
sql`${admins.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
|
||||
sql`${users_temp.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
|
||||
);
|
||||
|
||||
if (!result?.[0]?.adminId) {
|
||||
if (!result?.[0]?.id) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Token not found",
|
||||
});
|
||||
}
|
||||
|
||||
adminId = result?.[0]?.adminId;
|
||||
userId = result?.[0]?.id;
|
||||
ServerName = "Dokploy";
|
||||
} else {
|
||||
const result = await db
|
||||
@@ -359,18 +359,18 @@ export const notificationRouter = createTRPCRouter({
|
||||
sql`${server.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
|
||||
);
|
||||
|
||||
if (!result?.[0]?.adminId) {
|
||||
if (!result?.[0]?.userId) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Token not found",
|
||||
});
|
||||
}
|
||||
|
||||
adminId = result?.[0]?.adminId;
|
||||
userId = result?.[0]?.userId;
|
||||
ServerName = "Remote";
|
||||
}
|
||||
|
||||
await sendServerThresholdNotifications(adminId, {
|
||||
await sendServerThresholdNotifications(userId, {
|
||||
...input,
|
||||
ServerName,
|
||||
});
|
||||
@@ -386,7 +386,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.input(apiCreateGotify)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
return await createGotifyNotification(input, ctx.user.adminId);
|
||||
return await createGotifyNotification(input, ctx.user.ownerId);
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
@@ -400,7 +400,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const notification = await findNotificationById(input.notificationId);
|
||||
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this notification",
|
||||
@@ -408,7 +408,7 @@ export const notificationRouter = createTRPCRouter({
|
||||
}
|
||||
return await updateGotifyNotification({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
|
||||
@@ -44,8 +44,8 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiCreatePostgres)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -56,15 +56,15 @@ export const postgresRouter = createTRPCRouter({
|
||||
}
|
||||
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
});
|
||||
}
|
||||
const newPostgres = await createPostgres(input);
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newPostgres.postgresId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newPostgres.postgresId);
|
||||
}
|
||||
|
||||
await createMount({
|
||||
@@ -90,12 +90,12 @@ export const postgresRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOnePostgres)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.postgresId, "access");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.postgresId, "access");
|
||||
}
|
||||
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this Postgres",
|
||||
@@ -109,7 +109,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const service = await findPostgresById(input.postgresId);
|
||||
|
||||
if (service.project.adminId !== ctx.user.adminId) {
|
||||
if (service.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to start this Postgres",
|
||||
@@ -131,7 +131,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiFindOnePostgres)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this Postgres",
|
||||
@@ -153,7 +153,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this external port",
|
||||
@@ -169,7 +169,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiDeployPostgres)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this Postgres",
|
||||
@@ -190,7 +190,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiDeployPostgres)
|
||||
.subscription(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this Postgres",
|
||||
@@ -207,7 +207,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiChangePostgresStatus)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to change this Postgres status",
|
||||
@@ -221,12 +221,12 @@ export const postgresRouter = createTRPCRouter({
|
||||
remove: protectedProcedure
|
||||
.input(apiFindOnePostgres)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.postgresId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.postgresId, "delete");
|
||||
}
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this Postgres",
|
||||
@@ -249,7 +249,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiSaveEnvironmentVariablesPostgres)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this environment",
|
||||
@@ -272,7 +272,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.input(apiResetPostgres)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const postgres = await findPostgresById(input.postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to reload this Postgres",
|
||||
@@ -302,7 +302,7 @@ export const postgresRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { postgresId, ...rest } = input;
|
||||
const postgres = await findPostgresById(postgresId);
|
||||
if (postgres.project.adminId !== ctx.user.adminId) {
|
||||
if (postgres.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this Postgres",
|
||||
|
||||
@@ -14,7 +14,7 @@ export const previewDeploymentRouter = createTRPCRouter({
|
||||
.input(apiFindAllByApplication)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -28,7 +28,7 @@ export const previewDeploymentRouter = createTRPCRouter({
|
||||
const previewDeployment = await findPreviewDeploymentById(
|
||||
input.previewDeploymentId,
|
||||
);
|
||||
if (previewDeployment.application.project.adminId !== ctx.user.adminId) {
|
||||
if (previewDeployment.application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this preview deployment",
|
||||
@@ -43,7 +43,7 @@ export const previewDeploymentRouter = createTRPCRouter({
|
||||
const previewDeployment = await findPreviewDeploymentById(
|
||||
input.previewDeploymentId,
|
||||
);
|
||||
if (previewDeployment.application.project.adminId !== ctx.user.adminId) {
|
||||
if (previewDeployment.application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this preview deployment",
|
||||
|
||||
@@ -25,9 +25,9 @@ import {
|
||||
checkProjectAccess,
|
||||
createProject,
|
||||
deleteProject,
|
||||
findAdminById,
|
||||
findProjectById,
|
||||
findUserByAuthId,
|
||||
findUserById,
|
||||
updateProjectById,
|
||||
} from "@dokploy/server";
|
||||
|
||||
@@ -36,11 +36,11 @@ export const projectRouter = createTRPCRouter({
|
||||
.input(apiCreateProject)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkProjectAccess(ctx.user.authId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkProjectAccess(ctx.user.id, "create");
|
||||
}
|
||||
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const admin = await findUserById(ctx.user.ownerId);
|
||||
|
||||
if (admin.serversQuantity === 0 && IS_CLOUD) {
|
||||
throw new TRPCError({
|
||||
@@ -49,9 +49,9 @@ export const projectRouter = createTRPCRouter({
|
||||
});
|
||||
}
|
||||
|
||||
const project = await createProject(input, ctx.user.adminId);
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewProject(ctx.user.authId, project.projectId);
|
||||
const project = await createProject(input, ctx.user.ownerId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewProject(ctx.user.id, project.projectId);
|
||||
}
|
||||
|
||||
return project;
|
||||
@@ -67,15 +67,15 @@ export const projectRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOneProject)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
const { accessedServices } = await findUserByAuthId(ctx.user.authId);
|
||||
if (ctx.user.rol === "member") {
|
||||
const { accessedServices } = await findUserByAuthId(ctx.user.id);
|
||||
|
||||
await checkProjectAccess(ctx.user.authId, "access", input.projectId);
|
||||
await checkProjectAccess(ctx.user.id, "access", input.projectId);
|
||||
|
||||
const project = await db.query.projects.findFirst({
|
||||
where: and(
|
||||
eq(projects.projectId, input.projectId),
|
||||
eq(projects.adminId, ctx.user.adminId),
|
||||
eq(projects.userId, ctx.user.ownerId),
|
||||
),
|
||||
with: {
|
||||
compose: {
|
||||
@@ -115,7 +115,7 @@ export const projectRouter = createTRPCRouter({
|
||||
}
|
||||
const project = await findProjectById(input.projectId);
|
||||
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
@@ -124,9 +124,10 @@ export const projectRouter = createTRPCRouter({
|
||||
return project;
|
||||
}),
|
||||
all: protectedProcedure.query(async ({ ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
const { accessedProjects, accessedServices } = await findUserByAuthId(
|
||||
ctx.user.authId,
|
||||
// console.log(ctx.user);
|
||||
if (ctx.user.rol === "member") {
|
||||
const { accessedProjects, accessedServices } = await findUserById(
|
||||
ctx.user.id,
|
||||
);
|
||||
|
||||
if (accessedProjects.length === 0) {
|
||||
@@ -139,7 +140,7 @@ export const projectRouter = createTRPCRouter({
|
||||
accessedProjects.map((projectId) => sql`${projectId}`),
|
||||
sql`, `,
|
||||
)})`,
|
||||
eq(projects.adminId, ctx.user.adminId),
|
||||
eq(projects.userId, ctx.user.id),
|
||||
),
|
||||
with: {
|
||||
applications: {
|
||||
@@ -193,7 +194,7 @@ export const projectRouter = createTRPCRouter({
|
||||
},
|
||||
},
|
||||
},
|
||||
where: eq(projects.adminId, ctx.user.adminId),
|
||||
where: eq(projects.userId, ctx.user.id),
|
||||
orderBy: desc(projects.createdAt),
|
||||
});
|
||||
}),
|
||||
@@ -202,11 +203,11 @@ export const projectRouter = createTRPCRouter({
|
||||
.input(apiRemoveProject)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkProjectAccess(ctx.user.authId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkProjectAccess(ctx.user.id, "delete");
|
||||
}
|
||||
const currentProject = await findProjectById(input.projectId);
|
||||
if (currentProject.adminId !== ctx.user.adminId) {
|
||||
if (currentProject.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this project",
|
||||
@@ -224,7 +225,7 @@ export const projectRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const currentProject = await findProjectById(input.projectId);
|
||||
if (currentProject.adminId !== ctx.user.adminId) {
|
||||
if (currentProject.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this project",
|
||||
|
||||
@@ -18,7 +18,7 @@ export const redirectsRouter = createTRPCRouter({
|
||||
.input(apiCreateRedirect)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -31,7 +31,7 @@ export const redirectsRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
const redirect = await findRedirectById(input.redirectId);
|
||||
const application = await findApplicationById(redirect.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -44,7 +44,7 @@ export const redirectsRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redirect = await findRedirectById(input.redirectId);
|
||||
const application = await findApplicationById(redirect.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -57,7 +57,7 @@ export const redirectsRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redirect = await findRedirectById(input.redirectId);
|
||||
const application = await findApplicationById(redirect.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
|
||||
@@ -36,8 +36,8 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiCreateRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.projectId, "create");
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -48,15 +48,15 @@ export const redisRouter = createTRPCRouter({
|
||||
}
|
||||
|
||||
const project = await findProjectById(input.projectId);
|
||||
if (project.adminId !== ctx.user.adminId) {
|
||||
if (project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this project",
|
||||
});
|
||||
}
|
||||
const newRedis = await createRedis(input);
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, newRedis.redisId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(ctx.user.id, newRedis.redisId);
|
||||
}
|
||||
|
||||
await createMount({
|
||||
@@ -75,12 +75,12 @@ export const redisRouter = createTRPCRouter({
|
||||
one: protectedProcedure
|
||||
.input(apiFindOneRedis)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.redisId, "access");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.redisId, "access");
|
||||
}
|
||||
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this Redis",
|
||||
@@ -93,7 +93,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiFindOneRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to start this Redis",
|
||||
@@ -115,7 +115,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiResetRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to reload this Redis",
|
||||
@@ -145,7 +145,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiFindOneRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to stop this Redis",
|
||||
@@ -166,7 +166,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiSaveExternalPortRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findRedisById(input.redisId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this external port",
|
||||
@@ -182,7 +182,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiDeployRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this Redis",
|
||||
@@ -202,7 +202,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiDeployRedis)
|
||||
.subscription(async ({ input, ctx }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to deploy this Redis",
|
||||
@@ -218,7 +218,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiChangeRedisStatus)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const mongo = await findRedisById(input.redisId);
|
||||
if (mongo.project.adminId !== ctx.user.adminId) {
|
||||
if (mongo.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to change this Redis status",
|
||||
@@ -232,13 +232,13 @@ export const redisRouter = createTRPCRouter({
|
||||
remove: protectedProcedure
|
||||
.input(apiFindOneRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.authId, input.redisId, "delete");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(ctx.user.id, input.redisId, "delete");
|
||||
}
|
||||
|
||||
const redis = await findRedisById(input.redisId);
|
||||
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this Redis",
|
||||
@@ -261,7 +261,7 @@ export const redisRouter = createTRPCRouter({
|
||||
.input(apiSaveEnvironmentVariablesRedis)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const redis = await findRedisById(input.redisId);
|
||||
if (redis.project.adminId !== ctx.user.adminId) {
|
||||
if (redis.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to save this environment",
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
createRegistry,
|
||||
execAsync,
|
||||
execAsyncRemote,
|
||||
findAllRegistryByAdminId,
|
||||
findAllRegistryByUserId,
|
||||
findRegistryById,
|
||||
removeRegistry,
|
||||
updateRegistry,
|
||||
@@ -22,13 +22,13 @@ export const registryRouter = createTRPCRouter({
|
||||
create: adminProcedure
|
||||
.input(apiCreateRegistry)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return await createRegistry(input, ctx.user.adminId);
|
||||
return await createRegistry(input, ctx.user.ownerId);
|
||||
}),
|
||||
remove: adminProcedure
|
||||
.input(apiRemoveRegistry)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const registry = await findRegistryById(input.registryId);
|
||||
if (registry.adminId !== ctx.user.adminId) {
|
||||
if (registry.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to delete this registry",
|
||||
@@ -41,7 +41,7 @@ export const registryRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { registryId, ...rest } = input;
|
||||
const registry = await findRegistryById(registryId);
|
||||
if (registry.adminId !== ctx.user.adminId) {
|
||||
if (registry.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to update this registry",
|
||||
@@ -61,13 +61,13 @@ export const registryRouter = createTRPCRouter({
|
||||
return true;
|
||||
}),
|
||||
all: protectedProcedure.query(async ({ ctx }) => {
|
||||
return await findAllRegistryByAdminId(ctx.user.adminId);
|
||||
return await findAllRegistryByUserId(ctx.user.ownerId);
|
||||
}),
|
||||
one: adminProcedure
|
||||
.input(apiFindOneRegistry)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const registry = await findRegistryById(input.registryId);
|
||||
if (registry.adminId !== ctx.user.adminId) {
|
||||
if (registry.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not allowed to access this registry",
|
||||
|
||||
@@ -18,7 +18,7 @@ export const securityRouter = createTRPCRouter({
|
||||
.input(apiCreateSecurity)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -31,7 +31,7 @@ export const securityRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
const security = await findSecurityById(input.securityId);
|
||||
const application = await findApplicationById(security.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -44,7 +44,7 @@ export const securityRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const security = await findSecurityById(input.securityId);
|
||||
const application = await findApplicationById(security.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
@@ -57,7 +57,7 @@ export const securityRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const security = await findSecurityById(input.securityId);
|
||||
const application = await findApplicationById(security.applicationId);
|
||||
if (application.project.adminId !== ctx.user.adminId) {
|
||||
if (application.project.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
|
||||
@@ -21,9 +21,9 @@ import {
|
||||
createServer,
|
||||
defaultCommand,
|
||||
deleteServer,
|
||||
findAdminById,
|
||||
findServerById,
|
||||
findServersByAdminId,
|
||||
findServersByUserId,
|
||||
findUserById,
|
||||
getPublicIpWithFallback,
|
||||
haveActiveServices,
|
||||
removeDeploymentsByServerId,
|
||||
@@ -42,15 +42,15 @@ export const serverRouter = createTRPCRouter({
|
||||
.input(apiCreateServer)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
try {
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const servers = await findServersByAdminId(admin.adminId);
|
||||
if (IS_CLOUD && servers.length >= admin.serversQuantity) {
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
const servers = await findServersByUserId(user.id);
|
||||
if (IS_CLOUD && servers.length >= user.serversQuantity) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "You cannot create more servers",
|
||||
});
|
||||
}
|
||||
const project = await createServer(input, ctx.user.adminId);
|
||||
const project = await createServer(input, ctx.user.ownerId);
|
||||
return project;
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -65,7 +65,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.input(apiFindOneServer)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this server",
|
||||
@@ -93,7 +93,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.leftJoin(mongo, eq(mongo.serverId, server.serverId))
|
||||
.leftJoin(mysql, eq(mysql.serverId, server.serverId))
|
||||
.leftJoin(postgres, eq(postgres.serverId, server.serverId))
|
||||
.where(eq(server.adminId, ctx.user.adminId))
|
||||
.where(eq(server.userId, ctx.user.ownerId))
|
||||
.orderBy(desc(server.createdAt))
|
||||
.groupBy(server.serverId);
|
||||
|
||||
@@ -105,10 +105,10 @@ export const serverRouter = createTRPCRouter({
|
||||
where: IS_CLOUD
|
||||
? and(
|
||||
isNotNull(server.sshKeyId),
|
||||
eq(server.adminId, ctx.user.adminId),
|
||||
eq(server.userId, ctx.user.ownerId),
|
||||
eq(server.serverStatus, "active"),
|
||||
)
|
||||
: and(isNotNull(server.sshKeyId), eq(server.adminId, ctx.user.adminId)),
|
||||
: and(isNotNull(server.sshKeyId), eq(server.userId, ctx.user.ownerId)),
|
||||
});
|
||||
return result;
|
||||
}),
|
||||
@@ -117,7 +117,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to setup this server",
|
||||
@@ -142,7 +142,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.subscription(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to setup this server",
|
||||
@@ -162,7 +162,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to validate this server",
|
||||
@@ -204,7 +204,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to validate this server",
|
||||
@@ -254,7 +254,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to setup this server",
|
||||
@@ -296,7 +296,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to delete this server",
|
||||
@@ -315,12 +315,9 @@ export const serverRouter = createTRPCRouter({
|
||||
await deleteServer(input.serverId);
|
||||
|
||||
if (IS_CLOUD) {
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const admin = await findUserById(ctx.user.ownerId);
|
||||
|
||||
await updateServersBasedOnQuantity(
|
||||
admin.adminId,
|
||||
admin.serversQuantity,
|
||||
);
|
||||
await updateServersBasedOnQuantity(admin.id, admin.serversQuantity);
|
||||
}
|
||||
|
||||
return currentServer;
|
||||
@@ -333,7 +330,7 @@ export const serverRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const server = await findServerById(input.serverId);
|
||||
if (server.adminId !== ctx.user.adminId) {
|
||||
if (server.userId !== ctx.user.ownerId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to update this server",
|
||||
|
||||
@@ -47,7 +47,6 @@ import {
|
||||
startServiceRemote,
|
||||
stopService,
|
||||
stopServiceRemote,
|
||||
updateAdmin,
|
||||
updateLetsEncryptEmail,
|
||||
updateServerById,
|
||||
updateServerTraefik,
|
||||
@@ -383,7 +382,7 @@ export const settingsRouter = createTRPCRouter({
|
||||
.input(apiServerSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
try {
|
||||
if (ctx.user.rol === "user") {
|
||||
if (ctx.user.rol === "member") {
|
||||
const canAccess = await canAccessToTraefikFiles(ctx.user.authId);
|
||||
|
||||
if (!canAccess) {
|
||||
@@ -401,7 +400,7 @@ export const settingsRouter = createTRPCRouter({
|
||||
updateTraefikFile: protectedProcedure
|
||||
.input(apiModifyTraefikConfig)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
if (ctx.user.rol === "member") {
|
||||
const canAccess = await canAccessToTraefikFiles(ctx.user.authId);
|
||||
|
||||
if (!canAccess) {
|
||||
@@ -419,7 +418,7 @@ export const settingsRouter = createTRPCRouter({
|
||||
readTraefikFile: protectedProcedure
|
||||
.input(apiReadTraefikConfig)
|
||||
.query(async ({ input, ctx }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
if (ctx.user.rol === "member") {
|
||||
const canAccess = await canAccessToTraefikFiles(ctx.user.authId);
|
||||
|
||||
if (!canAccess) {
|
||||
@@ -655,7 +654,7 @@ export const settingsRouter = createTRPCRouter({
|
||||
|
||||
return true;
|
||||
}),
|
||||
isCloud: protectedProcedure.query(async () => {
|
||||
isCloud: publicProcedure.query(async () => {
|
||||
return IS_CLOUD;
|
||||
}),
|
||||
health: publicProcedure.query(async () => {
|
||||
|
||||
@@ -24,9 +24,10 @@ export const sshRouter = createTRPCRouter({
|
||||
.input(apiCreateSshKey)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
console.log(ctx.user.ownerId);
|
||||
await createSshKey({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
userId: ctx.user.ownerId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -41,7 +42,7 @@ export const sshRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const sshKey = await findSSHKeyById(input.sshKeyId);
|
||||
if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && sshKey.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -59,7 +60,7 @@ export const sshRouter = createTRPCRouter({
|
||||
.query(async ({ input, ctx }) => {
|
||||
const sshKey = await findSSHKeyById(input.sshKeyId);
|
||||
|
||||
if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && sshKey.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
@@ -70,7 +71,7 @@ export const sshRouter = createTRPCRouter({
|
||||
}),
|
||||
all: protectedProcedure.query(async ({ ctx }) => {
|
||||
return await db.query.sshKeys.findMany({
|
||||
...(IS_CLOUD && { where: eq(sshKeys.adminId, ctx.user.adminId) }),
|
||||
...(IS_CLOUD && { where: eq(sshKeys.userId, ctx.user.ownerId) }),
|
||||
orderBy: desc(sshKeys.createdAt),
|
||||
});
|
||||
// TODO: Remove this line when the cloud version is ready
|
||||
@@ -85,7 +86,7 @@ export const sshRouter = createTRPCRouter({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const sshKey = await findSSHKeyById(input.sshKeyId);
|
||||
if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
|
||||
if (IS_CLOUD && sshKey.userId !== ctx.user.ownerId) {
|
||||
// TODO: Remove isCloud in the next versions of dokploy
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { WEBSITE_URL, getStripeItems } from "@/server/utils/stripe";
|
||||
import {
|
||||
IS_CLOUD,
|
||||
findAdminById,
|
||||
findServersByAdminId,
|
||||
updateAdmin,
|
||||
findServersByUserId,
|
||||
findUserById,
|
||||
updateUser,
|
||||
} from "@dokploy/server";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import Stripe from "stripe";
|
||||
@@ -12,8 +12,8 @@ import { adminProcedure, createTRPCRouter } from "../trpc";
|
||||
|
||||
export const stripeRouter = createTRPCRouter({
|
||||
getProducts: adminProcedure.query(async ({ ctx }) => {
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const stripeCustomerId = admin.stripeCustomerId;
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
const stripeCustomerId = user.stripeCustomerId;
|
||||
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
|
||||
apiVersion: "2024-09-30.acacia",
|
||||
@@ -56,15 +56,15 @@ export const stripeRouter = createTRPCRouter({
|
||||
});
|
||||
|
||||
const items = getStripeItems(input.serverQuantity, input.isAnnual);
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
|
||||
let stripeCustomerId = admin.stripeCustomerId;
|
||||
let stripeCustomerId = user.stripeCustomerId;
|
||||
|
||||
if (stripeCustomerId) {
|
||||
const customer = await stripe.customers.retrieve(stripeCustomerId);
|
||||
|
||||
if (customer.deleted) {
|
||||
await updateAdmin(admin.authId, {
|
||||
await updateUser(user.id, {
|
||||
stripeCustomerId: null,
|
||||
});
|
||||
stripeCustomerId = null;
|
||||
@@ -78,7 +78,7 @@ export const stripeRouter = createTRPCRouter({
|
||||
customer: stripeCustomerId,
|
||||
}),
|
||||
metadata: {
|
||||
adminId: admin.adminId,
|
||||
ownerId: user.id,
|
||||
},
|
||||
allow_promotion_codes: true,
|
||||
success_url: `${WEBSITE_URL}/dashboard/settings/servers?success=true`,
|
||||
@@ -89,15 +89,15 @@ export const stripeRouter = createTRPCRouter({
|
||||
}),
|
||||
createCustomerPortalSession: adminProcedure.mutation(
|
||||
async ({ ctx, input }) => {
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
|
||||
if (!admin.stripeCustomerId) {
|
||||
if (!user.stripeCustomerId) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Stripe Customer ID not found",
|
||||
});
|
||||
}
|
||||
const stripeCustomerId = admin.stripeCustomerId;
|
||||
const stripeCustomerId = user.stripeCustomerId;
|
||||
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
|
||||
apiVersion: "2024-09-30.acacia",
|
||||
@@ -119,13 +119,13 @@ export const stripeRouter = createTRPCRouter({
|
||||
),
|
||||
|
||||
canCreateMoreServers: adminProcedure.query(async ({ ctx }) => {
|
||||
const admin = await findAdminById(ctx.user.adminId);
|
||||
const servers = await findServersByAdminId(admin.adminId);
|
||||
const user = await findUserById(ctx.user.ownerId);
|
||||
const servers = await findServersByUserId(user.id);
|
||||
|
||||
if (!IS_CLOUD) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return servers.length < admin.serversQuantity;
|
||||
return servers.length < user.serversQuantity;
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
// import { getServerAuthSession } from "@/server/auth";
|
||||
import { db } from "@/server/db";
|
||||
import { validateBearerToken, validateRequest } from "@dokploy/server";
|
||||
import { validateBearerToken } from "@dokploy/server";
|
||||
import { validateRequest } from "@dokploy/server/lib/auth";
|
||||
import type { OpenApiMeta } from "@dokploy/trpc-openapi";
|
||||
import { TRPCError, initTRPC } from "@trpc/server";
|
||||
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
|
||||
@@ -18,7 +19,7 @@ import {
|
||||
experimental_isMultipartFormDataRequest,
|
||||
experimental_parseMultipartFormData,
|
||||
} from "@trpc/server/adapters/node-http/content-type/form-data";
|
||||
import type { Session, User } from "lucia";
|
||||
import type { Session, User } from "better-auth";
|
||||
import superjson from "superjson";
|
||||
import { ZodError } from "zod";
|
||||
/**
|
||||
@@ -30,8 +31,8 @@ import { ZodError } from "zod";
|
||||
*/
|
||||
|
||||
interface CreateContextOptions {
|
||||
user: (User & { authId: string; adminId: string }) | null;
|
||||
session: Session | null;
|
||||
user: (User & { rol: "member" | "admin" | "owner"; ownerId: string }) | null;
|
||||
session: (Session & { activeOrganizationId?: string }) | null;
|
||||
req: CreateNextContextOptions["req"];
|
||||
res: CreateNextContextOptions["res"];
|
||||
}
|
||||
@@ -65,30 +66,36 @@ const createInnerTRPCContext = (opts: CreateContextOptions) => {
|
||||
export const createTRPCContext = async (opts: CreateNextContextOptions) => {
|
||||
const { req, res } = opts;
|
||||
|
||||
let { session, user } = await validateBearerToken(req);
|
||||
// Get from the request
|
||||
const { session, user } = await validateRequest(req);
|
||||
|
||||
if (!session) {
|
||||
const cookieResult = await validateRequest(req, res);
|
||||
session = cookieResult.session;
|
||||
user = cookieResult.user;
|
||||
}
|
||||
// if (!session) {
|
||||
// const cookieResult = await validateRequest(req);
|
||||
// session = cookieResult.session;
|
||||
// user = cookieResult.user;
|
||||
// }
|
||||
|
||||
console.log("session", session);
|
||||
console.log("user", user);
|
||||
|
||||
return createInnerTRPCContext({
|
||||
req,
|
||||
res,
|
||||
session: session,
|
||||
...((user && {
|
||||
user: {
|
||||
authId: user.id,
|
||||
email: user.email,
|
||||
rol: user.rol,
|
||||
id: user.id,
|
||||
secret: user.secret,
|
||||
adminId: user.adminId,
|
||||
},
|
||||
}) || {
|
||||
user: null,
|
||||
}),
|
||||
session: session
|
||||
? {
|
||||
...session,
|
||||
activeOrganizationId: session.activeOrganizationId ?? undefined,
|
||||
}
|
||||
: null,
|
||||
user: user
|
||||
? {
|
||||
...user,
|
||||
email: user.email,
|
||||
rol: user.role as "owner" | "member" | "admin",
|
||||
id: user.id,
|
||||
ownerId: user.ownerId,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -181,7 +188,7 @@ export const uploadProcedure = async (opts: any) => {
|
||||
};
|
||||
|
||||
export const cliProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
if (!ctx.session || !ctx.user || ctx.user.rol !== "admin") {
|
||||
if (!ctx.session || !ctx.user || ctx.user.rol !== "owner") {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
return next({
|
||||
@@ -195,7 +202,7 @@ export const cliProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
});
|
||||
|
||||
export const adminProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
if (!ctx.session || !ctx.user || ctx.user.rol !== "admin") {
|
||||
if (!ctx.session || !ctx.user || ctx.user.rol !== "owner") {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
return next({
|
||||
|
||||
@@ -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();
|
||||
|
||||
96
packages/server/auth-schema.ts
Normal file
96
packages/server/auth-schema.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import {
|
||||
boolean,
|
||||
integer,
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
export const user = pgTable("user", {
|
||||
id: text("id").primaryKey(),
|
||||
name: text("name").notNull(),
|
||||
email: text("email").notNull().unique(),
|
||||
emailVerified: boolean("email_verified").notNull(),
|
||||
image: text("image"),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
updatedAt: timestamp("updated_at").notNull(),
|
||||
});
|
||||
|
||||
export const session = pgTable("session", {
|
||||
id: text("id").primaryKey(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
token: text("token").notNull().unique(),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
updatedAt: timestamp("updated_at").notNull(),
|
||||
ipAddress: text("ip_address"),
|
||||
userAgent: text("user_agent"),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id),
|
||||
activeOrganizationId: text("active_organization_id"),
|
||||
});
|
||||
|
||||
export const account = pgTable("account", {
|
||||
id: text("id").primaryKey(),
|
||||
accountId: text("account_id").notNull(),
|
||||
providerId: text("provider_id").notNull(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id),
|
||||
accessToken: text("access_token"),
|
||||
refreshToken: text("refresh_token"),
|
||||
idToken: text("id_token"),
|
||||
accessTokenExpiresAt: timestamp("access_token_expires_at"),
|
||||
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
|
||||
scope: text("scope"),
|
||||
password: text("password"),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
updatedAt: timestamp("updated_at").notNull(),
|
||||
});
|
||||
|
||||
export const verification = pgTable("verification", {
|
||||
id: text("id").primaryKey(),
|
||||
identifier: text("identifier").notNull(),
|
||||
value: text("value").notNull(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
createdAt: timestamp("created_at"),
|
||||
updatedAt: timestamp("updated_at"),
|
||||
});
|
||||
|
||||
export const organization = pgTable("organization", {
|
||||
id: text("id").primaryKey(),
|
||||
name: text("name").notNull(),
|
||||
slug: text("slug").unique(),
|
||||
logo: text("logo"),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
metadata: text("metadata"),
|
||||
ownerId: text("owner_id")
|
||||
.notNull()
|
||||
.references(() => user.userId),
|
||||
});
|
||||
|
||||
export const member = pgTable("member", {
|
||||
id: text("id").primaryKey(),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.userId),
|
||||
role: text("role").notNull(),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
});
|
||||
|
||||
export const invitation = pgTable("invitation", {
|
||||
id: text("id").primaryKey(),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id),
|
||||
email: text("email").notNull(),
|
||||
role: text("role"),
|
||||
status: text("status").notNull(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
inviterId: text("inviter_id")
|
||||
.notNull()
|
||||
.references(() => user.userId),
|
||||
});
|
||||
@@ -28,6 +28,10 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oslojs/encoding":"1.1.0",
|
||||
"@oslojs/crypto":"1.0.1",
|
||||
"drizzle-dbml-generator":"0.10.0",
|
||||
"better-auth":"1.1.16",
|
||||
"rotating-file-stream": "3.2.3",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@lucia-auth/adapter-drizzle": "1.0.7",
|
||||
|
||||
@@ -6,9 +6,9 @@ import { TimeSpan } from "lucia";
|
||||
import { Lucia } from "lucia/dist/core.js";
|
||||
import type { Session, User } from "lucia/dist/core.js";
|
||||
import { db } from "../db";
|
||||
import { type DatabaseUser, auth, sessionTable } from "../db/schema";
|
||||
import { type DatabaseUser, auth, session } from "../db/schema";
|
||||
|
||||
export const adapter = new DrizzlePostgreSQLAdapter(db, sessionTable, auth);
|
||||
export const adapter = new DrizzlePostgreSQLAdapter(db, session, auth);
|
||||
|
||||
export const lucia = new Lucia(adapter, {
|
||||
sessionCookie: {
|
||||
@@ -16,6 +16,7 @@ export const lucia = new Lucia(adapter, {
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
|
||||
sessionExpiresIn: new TimeSpan(1, "d"),
|
||||
getUserAttributes: (attributes) => {
|
||||
return {
|
||||
@@ -46,6 +47,7 @@ export async function validateRequest(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
): ReturnValidateToken {
|
||||
console.log(session);
|
||||
const sessionId = lucia.readSessionCookie(req.headers.cookie ?? "");
|
||||
|
||||
if (!sessionId) {
|
||||
@@ -69,10 +71,10 @@ export async function validateRequest(
|
||||
}
|
||||
if (result.user) {
|
||||
try {
|
||||
if (result.user?.rol === "admin") {
|
||||
if (result.user?.rol === "owner") {
|
||||
const admin = await findAdminByAuthId(result.user.id);
|
||||
result.user.adminId = admin.adminId;
|
||||
} else if (result.user?.rol === "user") {
|
||||
} else if (result.user?.rol === "member") {
|
||||
const userResult = await findUserByAuthId(result.user.id);
|
||||
result.user.adminId = userResult.adminId;
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ export const validateBearerToken = async (
|
||||
const result = await luciaToken.validateSession(sessionId);
|
||||
|
||||
if (result.user) {
|
||||
if (result.user?.rol === "admin") {
|
||||
if (result.user?.rol === "owner") {
|
||||
const admin = await findAdminByAuthId(result.user.id);
|
||||
result.user.adminId = admin.adminId;
|
||||
} else if (result.user?.rol === "user") {
|
||||
} else if (result.user?.rol === "member") {
|
||||
const userResult = await findUserByAuthId(result.user.id);
|
||||
result.user.adminId = userResult.adminId;
|
||||
}
|
||||
@@ -73,10 +73,10 @@ export const validateBearerTokenAPI = async (
|
||||
const result = await luciaToken.validateSession(sessionId);
|
||||
|
||||
if (result.user) {
|
||||
if (result.user?.rol === "admin") {
|
||||
if (result.user?.rol === "owner") {
|
||||
const admin = await findAdminByAuthId(result.user.id);
|
||||
result.user.adminId = admin.adminId;
|
||||
} else if (result.user?.rol === "user") {
|
||||
} else if (result.user?.rol === "member") {
|
||||
const userResult = await findUserByAuthId(result.user.id);
|
||||
result.user.adminId = userResult.adminId;
|
||||
}
|
||||
|
||||
114
packages/server/src/db/schema/account.ts
Normal file
114
packages/server/src/db/schema/account.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import { nanoid } from "nanoid";
|
||||
import { users_temp } from "./user";
|
||||
|
||||
export const account = pgTable("account", {
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
accountId: text("account_id")
|
||||
.notNull()
|
||||
.$defaultFn(() => nanoid()),
|
||||
providerId: text("provider_id").notNull(),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => users_temp.id),
|
||||
accessToken: text("access_token"),
|
||||
refreshToken: text("refresh_token"),
|
||||
idToken: text("id_token"),
|
||||
accessTokenExpiresAt: timestamp("access_token_expires_at"),
|
||||
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
|
||||
scope: text("scope"),
|
||||
password: text("password"),
|
||||
is2FAEnabled: boolean("is2FAEnabled").notNull().default(false),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
updatedAt: timestamp("updated_at").notNull(),
|
||||
resetPasswordToken: text("resetPasswordToken"),
|
||||
resetPasswordExpiresAt: text("resetPasswordExpiresAt"),
|
||||
confirmationToken: text("confirmationToken"),
|
||||
confirmationExpiresAt: text("confirmationExpiresAt"),
|
||||
});
|
||||
|
||||
export const accountRelations = relations(account, ({ one }) => ({
|
||||
user: one(users_temp, {
|
||||
fields: [account.userId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const verification = pgTable("verification", {
|
||||
id: text("id").primaryKey(),
|
||||
identifier: text("identifier").notNull(),
|
||||
value: text("value").notNull(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
createdAt: timestamp("created_at"),
|
||||
updatedAt: timestamp("updated_at"),
|
||||
});
|
||||
|
||||
export const organization = pgTable("organization", {
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
name: text("name").notNull(),
|
||||
slug: text("slug").unique(),
|
||||
logo: text("logo"),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
metadata: text("metadata"),
|
||||
ownerId: text("owner_id")
|
||||
.notNull()
|
||||
.references(() => users_temp.id),
|
||||
});
|
||||
|
||||
export const organizationRelations = relations(organization, ({ one }) => ({
|
||||
owner: one(users_temp, {
|
||||
fields: [organization.ownerId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const member = pgTable("member", {
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => users_temp.id),
|
||||
role: text("role").notNull().$type<"owner" | "member" | "admin">(),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
});
|
||||
|
||||
export const memberRelations = relations(member, ({ one }) => ({
|
||||
organization: one(organization, {
|
||||
fields: [member.organizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
user: one(users_temp, {
|
||||
fields: [member.userId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const invitation = pgTable("invitation", {
|
||||
id: text("id").primaryKey(),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id),
|
||||
email: text("email").notNull(),
|
||||
role: text("role").$type<"owner" | "member" | "admin">(),
|
||||
status: text("status").notNull(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
inviterId: text("inviter_id")
|
||||
.notNull()
|
||||
.references(() => users_temp.id),
|
||||
});
|
||||
|
||||
export const invitationRelations = relations(invitation, ({ one }) => ({
|
||||
organization: one(organization, {
|
||||
fields: [invitation.organizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
}));
|
||||
@@ -4,7 +4,7 @@ import { boolean, pgEnum, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
// import { admins } from "./admin";
|
||||
import { users } from "./user";
|
||||
|
||||
const randomImages = [
|
||||
@@ -55,7 +55,7 @@ export const auth = pgTable("auth", {
|
||||
});
|
||||
|
||||
export const authRelations = relations(auth, ({ many }) => ({
|
||||
admins: many(admins),
|
||||
// admins: many(admins),
|
||||
users: many(users),
|
||||
}));
|
||||
const createSchema = createInsertSchema(auth, {
|
||||
|
||||
@@ -61,5 +61,5 @@ export const apiUpdateBitbucket = createSchema.extend({
|
||||
name: z.string().min(1),
|
||||
bitbucketUsername: z.string().optional(),
|
||||
bitbucketWorkspaceName: z.string().optional(),
|
||||
adminId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
});
|
||||
|
||||
@@ -5,6 +5,8 @@ import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
import { server } from "./server";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
import { generateAppName } from "./utils";
|
||||
|
||||
export const certificates = pgTable("certificate", {
|
||||
@@ -20,9 +22,12 @@ export const certificates = pgTable("certificate", {
|
||||
.$defaultFn(() => generateAppName("certificate"))
|
||||
.unique(),
|
||||
autoRenew: boolean("autoRenew"),
|
||||
adminId: text("adminId").references(() => admins.adminId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// userId: text("userId").references(() => user.userId, {
|
||||
// onDelete: "cascade",
|
||||
// }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
serverId: text("serverId").references(() => server.serverId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
@@ -35,9 +40,9 @@ export const certificatesRelations = relations(
|
||||
fields: [certificates.serverId],
|
||||
references: [server.serverId],
|
||||
}),
|
||||
admin: one(admins, {
|
||||
fields: [certificates.adminId],
|
||||
references: [admins.adminId],
|
||||
user: one(users_temp, {
|
||||
fields: [certificates.userId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
7
packages/server/src/db/schema/dbml.ts
Normal file
7
packages/server/src/db/schema/dbml.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { pgGenerate } from "drizzle-dbml-generator"; // Using Postgres for this example
|
||||
import * as schema from "./index";
|
||||
|
||||
const out = "./schema.dbml";
|
||||
const relational = true;
|
||||
|
||||
pgGenerate({ schema, out, relational });
|
||||
@@ -5,6 +5,8 @@ import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
import { backups } from "./backups";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
|
||||
export const destinations = pgTable("destination", {
|
||||
destinationId: text("destinationId")
|
||||
@@ -19,19 +21,22 @@ export const destinations = pgTable("destination", {
|
||||
region: text("region").notNull(),
|
||||
// maybe it can be null
|
||||
endpoint: text("endpoint").notNull(),
|
||||
adminId: text("adminId")
|
||||
// userId: text("userId")
|
||||
// .notNull()
|
||||
// .references(() => user.userId, { onDelete: "cascade" }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const destinationsRelations = relations(
|
||||
destinations,
|
||||
({ many, one }) => ({
|
||||
backups: many(backups),
|
||||
admin: one(admins, {
|
||||
fields: [destinations.adminId],
|
||||
references: [admins.adminId],
|
||||
}),
|
||||
// user: one(user, {
|
||||
// fields: [destinations.userId],
|
||||
// references: [user.id],
|
||||
// }),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import { admins } from "./admin";
|
||||
import { bitbucket } from "./bitbucket";
|
||||
import { github } from "./github";
|
||||
import { gitlab } from "./gitlab";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
|
||||
export const gitProviderType = pgEnum("gitProviderType", [
|
||||
"github",
|
||||
@@ -24,9 +26,12 @@ export const gitProvider = pgTable("git_provider", {
|
||||
createdAt: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
adminId: text("adminId").references(() => admins.adminId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// userId: text("userId").references(() => user.userId, {
|
||||
// onDelete: "cascade",
|
||||
// }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
|
||||
@@ -42,9 +47,9 @@ export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
|
||||
fields: [gitProvider.gitProviderId],
|
||||
references: [bitbucket.gitProviderId],
|
||||
}),
|
||||
admin: one(admins, {
|
||||
fields: [gitProvider.adminId],
|
||||
references: [admins.adminId],
|
||||
user: one(users_temp, {
|
||||
fields: [gitProvider.userId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
@@ -30,3 +30,4 @@ export * from "./gitlab";
|
||||
export * from "./server";
|
||||
export * from "./utils";
|
||||
export * from "./preview-deployments";
|
||||
export * from "./account";
|
||||
|
||||
@@ -3,7 +3,8 @@ import { boolean, integer, pgEnum, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
|
||||
export const notificationType = pgEnum("notificationType", [
|
||||
"slack",
|
||||
@@ -44,9 +45,12 @@ export const notifications = pgTable("notification", {
|
||||
gotifyId: text("gotifyId").references(() => gotify.gotifyId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
adminId: text("adminId").references(() => admins.adminId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// userId: text("userId").references(() => user.userId, {
|
||||
// onDelete: "cascade",
|
||||
// }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const slack = pgTable("slack", {
|
||||
@@ -121,9 +125,9 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({
|
||||
fields: [notifications.gotifyId],
|
||||
references: [gotify.gotifyId],
|
||||
}),
|
||||
admin: one(admins, {
|
||||
fields: [notifications.adminId],
|
||||
references: [admins.adminId],
|
||||
user: one(users_temp, {
|
||||
fields: [notifications.userId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -148,7 +152,7 @@ export const apiCreateSlack = notificationsSchema
|
||||
export const apiUpdateSlack = apiCreateSlack.partial().extend({
|
||||
notificationId: z.string().min(1),
|
||||
slackId: z.string(),
|
||||
adminId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiTestSlackConnection = apiCreateSlack.pick({
|
||||
@@ -175,7 +179,7 @@ export const apiCreateTelegram = notificationsSchema
|
||||
export const apiUpdateTelegram = apiCreateTelegram.partial().extend({
|
||||
notificationId: z.string().min(1),
|
||||
telegramId: z.string().min(1),
|
||||
adminId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiTestTelegramConnection = apiCreateTelegram.pick({
|
||||
@@ -202,7 +206,7 @@ export const apiCreateDiscord = notificationsSchema
|
||||
export const apiUpdateDiscord = apiCreateDiscord.partial().extend({
|
||||
notificationId: z.string().min(1),
|
||||
discordId: z.string().min(1),
|
||||
adminId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiTestDiscordConnection = apiCreateDiscord
|
||||
@@ -236,7 +240,7 @@ export const apiCreateEmail = notificationsSchema
|
||||
export const apiUpdateEmail = apiCreateEmail.partial().extend({
|
||||
notificationId: z.string().min(1),
|
||||
emailId: z.string().min(1),
|
||||
adminId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiTestEmailConnection = apiCreateEmail.pick({
|
||||
@@ -268,7 +272,7 @@ export const apiCreateGotify = notificationsSchema
|
||||
export const apiUpdateGotify = apiCreateGotify.partial().extend({
|
||||
notificationId: z.string().min(1),
|
||||
gotifyId: z.string().min(1),
|
||||
adminId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiTestGotifyConnection = apiCreateGotify
|
||||
|
||||
@@ -5,6 +5,7 @@ import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
// import { admins } from "./admin";
|
||||
import { applications } from "./application";
|
||||
import { compose } from "./compose";
|
||||
import { mariadb } from "./mariadb";
|
||||
@@ -12,6 +13,7 @@ import { mongo } from "./mongo";
|
||||
import { mysql } from "./mysql";
|
||||
import { postgres } from "./postgres";
|
||||
import { redis } from "./redis";
|
||||
import { users, users_temp } from "./user";
|
||||
|
||||
export const projects = pgTable("project", {
|
||||
projectId: text("projectId")
|
||||
@@ -23,9 +25,12 @@ export const projects = pgTable("project", {
|
||||
createdAt: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
adminId: text("adminId")
|
||||
// userId: text("userId")
|
||||
// .notNull()
|
||||
// .references(() => user.userId, { onDelete: "cascade" }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
env: text("env").notNull().default(""),
|
||||
});
|
||||
|
||||
@@ -37,10 +42,10 @@ export const projectRelations = relations(projects, ({ many, one }) => ({
|
||||
mongo: many(mongo),
|
||||
redis: many(redis),
|
||||
compose: many(compose),
|
||||
admin: one(admins, {
|
||||
fields: [projects.adminId],
|
||||
references: [admins.adminId],
|
||||
}),
|
||||
// user: one(user, {
|
||||
// fields: [projects.userId],
|
||||
// references: [user.id],
|
||||
// }),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(projects, {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
import { applications } from "./application";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
/**
|
||||
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
||||
* database instance for multiple projects.
|
||||
@@ -27,16 +29,19 @@ export const registry = pgTable("registry", {
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
registryType: registryType("selfHosted").notNull().default("cloud"),
|
||||
adminId: text("adminId")
|
||||
// userId: text("userId")
|
||||
// .notNull()
|
||||
// .references(() => user.userId, { onDelete: "cascade" }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const registryRelations = relations(registry, ({ one, many }) => ({
|
||||
admin: one(admins, {
|
||||
fields: [registry.adminId],
|
||||
references: [admins.adminId],
|
||||
}),
|
||||
// user: one(user, {
|
||||
// fields: [registry.userId],
|
||||
// references: [user.id],
|
||||
// }),
|
||||
applications: many(applications),
|
||||
}));
|
||||
|
||||
@@ -45,7 +50,7 @@ const createSchema = createInsertSchema(registry, {
|
||||
username: z.string().min(1),
|
||||
password: z.string().min(1),
|
||||
registryUrl: z.string(),
|
||||
adminId: z.string().min(1),
|
||||
userId: z.string().min(1),
|
||||
registryId: z.string().min(1),
|
||||
registryType: z.enum(["cloud"]),
|
||||
imagePrefix: z.string().nullable().optional(),
|
||||
|
||||
872
packages/server/src/db/schema/schema.dbml
Normal file
872
packages/server/src/db/schema/schema.dbml
Normal file
@@ -0,0 +1,872 @@
|
||||
enum applicationStatus {
|
||||
idle
|
||||
running
|
||||
done
|
||||
error
|
||||
}
|
||||
|
||||
enum buildType {
|
||||
dockerfile
|
||||
heroku_buildpacks
|
||||
paketo_buildpacks
|
||||
nixpacks
|
||||
static
|
||||
}
|
||||
|
||||
enum certificateType {
|
||||
letsencrypt
|
||||
none
|
||||
}
|
||||
|
||||
enum composeType {
|
||||
"docker-compose"
|
||||
stack
|
||||
}
|
||||
|
||||
enum databaseType {
|
||||
postgres
|
||||
mariadb
|
||||
mysql
|
||||
mongo
|
||||
}
|
||||
|
||||
enum deploymentStatus {
|
||||
running
|
||||
done
|
||||
error
|
||||
}
|
||||
|
||||
enum domainType {
|
||||
compose
|
||||
application
|
||||
preview
|
||||
}
|
||||
|
||||
enum gitProviderType {
|
||||
github
|
||||
gitlab
|
||||
bitbucket
|
||||
}
|
||||
|
||||
enum mountType {
|
||||
bind
|
||||
volume
|
||||
file
|
||||
}
|
||||
|
||||
enum notificationType {
|
||||
slack
|
||||
telegram
|
||||
discord
|
||||
email
|
||||
gotify
|
||||
}
|
||||
|
||||
enum protocolType {
|
||||
tcp
|
||||
udp
|
||||
}
|
||||
|
||||
enum RegistryType {
|
||||
selfHosted
|
||||
cloud
|
||||
}
|
||||
|
||||
enum Roles {
|
||||
admin
|
||||
user
|
||||
}
|
||||
|
||||
enum serverStatus {
|
||||
active
|
||||
inactive
|
||||
}
|
||||
|
||||
enum serviceType {
|
||||
application
|
||||
postgres
|
||||
mysql
|
||||
mariadb
|
||||
mongo
|
||||
redis
|
||||
compose
|
||||
}
|
||||
|
||||
enum sourceType {
|
||||
docker
|
||||
git
|
||||
github
|
||||
gitlab
|
||||
bitbucket
|
||||
drop
|
||||
}
|
||||
|
||||
enum sourceTypeCompose {
|
||||
git
|
||||
github
|
||||
gitlab
|
||||
bitbucket
|
||||
raw
|
||||
}
|
||||
|
||||
table account {
|
||||
id text [pk, not null]
|
||||
account_id text [not null]
|
||||
provider_id text [not null]
|
||||
user_id text [not null]
|
||||
access_token text
|
||||
refresh_token text
|
||||
id_token text
|
||||
access_token_expires_at timestamp
|
||||
refresh_token_expires_at timestamp
|
||||
scope text
|
||||
password text
|
||||
is2FAEnabled boolean [not null, default: false]
|
||||
created_at timestamp [not null]
|
||||
updated_at timestamp [not null]
|
||||
resetPasswordToken text
|
||||
resetPasswordExpiresAt text
|
||||
confirmationToken text
|
||||
confirmationExpiresAt text
|
||||
}
|
||||
|
||||
table admin {
|
||||
}
|
||||
|
||||
table application {
|
||||
applicationId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null, unique]
|
||||
description text
|
||||
env text
|
||||
previewEnv text
|
||||
previewBuildArgs text
|
||||
previewWildcard text
|
||||
previewPort integer [default: 3000]
|
||||
previewHttps boolean [not null, default: false]
|
||||
previewPath text [default: '/']
|
||||
certificateType certificateType [not null, default: 'none']
|
||||
previewLimit integer [default: 3]
|
||||
isPreviewDeploymentsActive boolean [default: false]
|
||||
buildArgs text
|
||||
memoryReservation text
|
||||
memoryLimit text
|
||||
cpuReservation text
|
||||
cpuLimit text
|
||||
title text
|
||||
enabled boolean
|
||||
subtitle text
|
||||
command text
|
||||
refreshToken text
|
||||
sourceType sourceType [not null, default: 'github']
|
||||
repository text
|
||||
owner text
|
||||
branch text
|
||||
buildPath text [default: '/']
|
||||
autoDeploy boolean
|
||||
gitlabProjectId integer
|
||||
gitlabRepository text
|
||||
gitlabOwner text
|
||||
gitlabBranch text
|
||||
gitlabBuildPath text [default: '/']
|
||||
gitlabPathNamespace text
|
||||
bitbucketRepository text
|
||||
bitbucketOwner text
|
||||
bitbucketBranch text
|
||||
bitbucketBuildPath text [default: '/']
|
||||
username text
|
||||
password text
|
||||
dockerImage text
|
||||
registryUrl text
|
||||
customGitUrl text
|
||||
customGitBranch text
|
||||
customGitBuildPath text
|
||||
customGitSSHKeyId text
|
||||
dockerfile text
|
||||
dockerContextPath text
|
||||
dockerBuildStage text
|
||||
dropBuildPath text
|
||||
healthCheckSwarm json
|
||||
restartPolicySwarm json
|
||||
placementSwarm json
|
||||
updateConfigSwarm json
|
||||
rollbackConfigSwarm json
|
||||
modeSwarm json
|
||||
labelsSwarm json
|
||||
networkSwarm json
|
||||
replicas integer [not null, default: 1]
|
||||
applicationStatus applicationStatus [not null, default: 'idle']
|
||||
buildType buildType [not null, default: 'nixpacks']
|
||||
herokuVersion text [default: '24']
|
||||
publishDirectory text
|
||||
createdAt text [not null]
|
||||
registryId text
|
||||
projectId text [not null]
|
||||
githubId text
|
||||
gitlabId text
|
||||
bitbucketId text
|
||||
serverId text
|
||||
}
|
||||
|
||||
table auth {
|
||||
id text [pk, not null]
|
||||
email text [not null, unique]
|
||||
password text [not null]
|
||||
rol Roles [not null]
|
||||
image text
|
||||
secret text
|
||||
token text
|
||||
is2FAEnabled boolean [not null, default: false]
|
||||
createdAt text [not null]
|
||||
resetPasswordToken text
|
||||
resetPasswordExpiresAt text
|
||||
confirmationToken text
|
||||
confirmationExpiresAt text
|
||||
}
|
||||
|
||||
table backup {
|
||||
backupId text [pk, not null]
|
||||
schedule text [not null]
|
||||
enabled boolean
|
||||
database text [not null]
|
||||
prefix text [not null]
|
||||
destinationId text [not null]
|
||||
databaseType databaseType [not null]
|
||||
postgresId text
|
||||
mariadbId text
|
||||
mysqlId text
|
||||
mongoId text
|
||||
}
|
||||
|
||||
table bitbucket {
|
||||
bitbucketId text [pk, not null]
|
||||
bitbucketUsername text
|
||||
appPassword text
|
||||
bitbucketWorkspaceName text
|
||||
gitProviderId text [not null]
|
||||
}
|
||||
|
||||
table certificate {
|
||||
certificateId text [pk, not null]
|
||||
name text [not null]
|
||||
certificateData text [not null]
|
||||
privateKey text [not null]
|
||||
certificatePath text [not null, unique]
|
||||
autoRenew boolean
|
||||
userId text
|
||||
serverId text
|
||||
}
|
||||
|
||||
table compose {
|
||||
composeId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null]
|
||||
description text
|
||||
env text
|
||||
composeFile text [not null, default: '']
|
||||
refreshToken text
|
||||
sourceType sourceTypeCompose [not null, default: 'github']
|
||||
composeType composeType [not null, default: 'docker-compose']
|
||||
repository text
|
||||
owner text
|
||||
branch text
|
||||
autoDeploy boolean
|
||||
gitlabProjectId integer
|
||||
gitlabRepository text
|
||||
gitlabOwner text
|
||||
gitlabBranch text
|
||||
gitlabPathNamespace text
|
||||
bitbucketRepository text
|
||||
bitbucketOwner text
|
||||
bitbucketBranch text
|
||||
customGitUrl text
|
||||
customGitBranch text
|
||||
customGitSSHKeyId text
|
||||
command text [not null, default: '']
|
||||
composePath text [not null, default: './docker-compose.yml']
|
||||
suffix text [not null, default: '']
|
||||
randomize boolean [not null, default: false]
|
||||
isolatedDeployment boolean [not null, default: false]
|
||||
composeStatus applicationStatus [not null, default: 'idle']
|
||||
projectId text [not null]
|
||||
createdAt text [not null]
|
||||
githubId text
|
||||
gitlabId text
|
||||
bitbucketId text
|
||||
serverId text
|
||||
}
|
||||
|
||||
table deployment {
|
||||
deploymentId text [pk, not null]
|
||||
title text [not null]
|
||||
description text
|
||||
status deploymentStatus [default: 'running']
|
||||
logPath text [not null]
|
||||
applicationId text
|
||||
composeId text
|
||||
serverId text
|
||||
isPreviewDeployment boolean [default: false]
|
||||
previewDeploymentId text
|
||||
createdAt text [not null]
|
||||
errorMessage text
|
||||
}
|
||||
|
||||
table destination {
|
||||
destinationId text [pk, not null]
|
||||
name text [not null]
|
||||
provider text
|
||||
accessKey text [not null]
|
||||
secretAccessKey text [not null]
|
||||
bucket text [not null]
|
||||
region text [not null]
|
||||
endpoint text [not null]
|
||||
userId text [not null]
|
||||
}
|
||||
|
||||
table discord {
|
||||
discordId text [pk, not null]
|
||||
webhookUrl text [not null]
|
||||
decoration boolean
|
||||
}
|
||||
|
||||
table domain {
|
||||
domainId text [pk, not null]
|
||||
host text [not null]
|
||||
https boolean [not null, default: false]
|
||||
port integer [default: 3000]
|
||||
path text [default: '/']
|
||||
serviceName text
|
||||
domainType domainType [default: 'application']
|
||||
uniqueConfigKey serial [not null, increment]
|
||||
createdAt text [not null]
|
||||
composeId text
|
||||
applicationId text
|
||||
previewDeploymentId text
|
||||
certificateType certificateType [not null, default: 'none']
|
||||
}
|
||||
|
||||
table email {
|
||||
emailId text [pk, not null]
|
||||
smtpServer text [not null]
|
||||
smtpPort integer [not null]
|
||||
username text [not null]
|
||||
password text [not null]
|
||||
fromAddress text [not null]
|
||||
toAddress text[] [not null]
|
||||
}
|
||||
|
||||
table git_provider {
|
||||
gitProviderId text [pk, not null]
|
||||
name text [not null]
|
||||
providerType gitProviderType [not null, default: 'github']
|
||||
createdAt text [not null]
|
||||
userId text
|
||||
}
|
||||
|
||||
table github {
|
||||
githubId text [pk, not null]
|
||||
githubAppName text
|
||||
githubAppId integer
|
||||
githubClientId text
|
||||
githubClientSecret text
|
||||
githubInstallationId text
|
||||
githubPrivateKey text
|
||||
githubWebhookSecret text
|
||||
gitProviderId text [not null]
|
||||
}
|
||||
|
||||
table gitlab {
|
||||
gitlabId text [pk, not null]
|
||||
gitlabUrl text [not null, default: 'https://gitlab.com']
|
||||
application_id text
|
||||
redirect_uri text
|
||||
secret text
|
||||
access_token text
|
||||
refresh_token text
|
||||
group_name text
|
||||
expires_at integer
|
||||
gitProviderId text [not null]
|
||||
}
|
||||
|
||||
table gotify {
|
||||
gotifyId text [pk, not null]
|
||||
serverUrl text [not null]
|
||||
appToken text [not null]
|
||||
priority integer [not null, default: 5]
|
||||
decoration boolean
|
||||
}
|
||||
|
||||
table invitation {
|
||||
id text [pk, not null]
|
||||
organization_id text [not null]
|
||||
email text [not null]
|
||||
role text
|
||||
status text [not null]
|
||||
expires_at timestamp [not null]
|
||||
inviter_id text [not null]
|
||||
}
|
||||
|
||||
table mariadb {
|
||||
mariadbId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null, unique]
|
||||
description text
|
||||
databaseName text [not null]
|
||||
databaseUser text [not null]
|
||||
databasePassword text [not null]
|
||||
rootPassword text [not null]
|
||||
dockerImage text [not null]
|
||||
command text
|
||||
env text
|
||||
memoryReservation text
|
||||
memoryLimit text
|
||||
cpuReservation text
|
||||
cpuLimit text
|
||||
externalPort integer
|
||||
applicationStatus applicationStatus [not null, default: 'idle']
|
||||
createdAt text [not null]
|
||||
projectId text [not null]
|
||||
serverId text
|
||||
}
|
||||
|
||||
table member {
|
||||
id text [pk, not null]
|
||||
organization_id text [not null]
|
||||
user_id text [not null]
|
||||
role text [not null]
|
||||
created_at timestamp [not null]
|
||||
}
|
||||
|
||||
table mongo {
|
||||
mongoId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null, unique]
|
||||
description text
|
||||
databaseUser text [not null]
|
||||
databasePassword text [not null]
|
||||
dockerImage text [not null]
|
||||
command text
|
||||
env text
|
||||
memoryReservation text
|
||||
memoryLimit text
|
||||
cpuReservation text
|
||||
cpuLimit text
|
||||
externalPort integer
|
||||
applicationStatus applicationStatus [not null, default: 'idle']
|
||||
createdAt text [not null]
|
||||
projectId text [not null]
|
||||
serverId text
|
||||
replicaSets boolean [default: false]
|
||||
}
|
||||
|
||||
table mount {
|
||||
mountId text [pk, not null]
|
||||
type mountType [not null]
|
||||
hostPath text
|
||||
volumeName text
|
||||
filePath text
|
||||
content text
|
||||
serviceType serviceType [not null, default: 'application']
|
||||
mountPath text [not null]
|
||||
applicationId text
|
||||
postgresId text
|
||||
mariadbId text
|
||||
mongoId text
|
||||
mysqlId text
|
||||
redisId text
|
||||
composeId text
|
||||
}
|
||||
|
||||
table mysql {
|
||||
mysqlId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null, unique]
|
||||
description text
|
||||
databaseName text [not null]
|
||||
databaseUser text [not null]
|
||||
databasePassword text [not null]
|
||||
rootPassword text [not null]
|
||||
dockerImage text [not null]
|
||||
command text
|
||||
env text
|
||||
memoryReservation text
|
||||
memoryLimit text
|
||||
cpuReservation text
|
||||
cpuLimit text
|
||||
externalPort integer
|
||||
applicationStatus applicationStatus [not null, default: 'idle']
|
||||
createdAt text [not null]
|
||||
projectId text [not null]
|
||||
serverId text
|
||||
}
|
||||
|
||||
table notification {
|
||||
notificationId text [pk, not null]
|
||||
name text [not null]
|
||||
appDeploy boolean [not null, default: false]
|
||||
appBuildError boolean [not null, default: false]
|
||||
databaseBackup boolean [not null, default: false]
|
||||
dokployRestart boolean [not null, default: false]
|
||||
dockerCleanup boolean [not null, default: false]
|
||||
serverThreshold boolean [not null, default: false]
|
||||
notificationType notificationType [not null]
|
||||
createdAt text [not null]
|
||||
slackId text
|
||||
telegramId text
|
||||
discordId text
|
||||
emailId text
|
||||
gotifyId text
|
||||
userId text
|
||||
}
|
||||
|
||||
table organization {
|
||||
id text [pk, not null]
|
||||
name text [not null]
|
||||
slug text [unique]
|
||||
logo text
|
||||
created_at timestamp [not null]
|
||||
metadata text
|
||||
owner_id text [not null]
|
||||
}
|
||||
|
||||
table port {
|
||||
portId text [pk, not null]
|
||||
publishedPort integer [not null]
|
||||
targetPort integer [not null]
|
||||
protocol protocolType [not null]
|
||||
applicationId text [not null]
|
||||
}
|
||||
|
||||
table postgres {
|
||||
postgresId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null, unique]
|
||||
databaseName text [not null]
|
||||
databaseUser text [not null]
|
||||
databasePassword text [not null]
|
||||
description text
|
||||
dockerImage text [not null]
|
||||
command text
|
||||
env text
|
||||
memoryReservation text
|
||||
externalPort integer
|
||||
memoryLimit text
|
||||
cpuReservation text
|
||||
cpuLimit text
|
||||
applicationStatus applicationStatus [not null, default: 'idle']
|
||||
createdAt text [not null]
|
||||
projectId text [not null]
|
||||
serverId text
|
||||
}
|
||||
|
||||
table preview_deployments {
|
||||
previewDeploymentId text [pk, not null]
|
||||
branch text [not null]
|
||||
pullRequestId text [not null]
|
||||
pullRequestNumber text [not null]
|
||||
pullRequestURL text [not null]
|
||||
pullRequestTitle text [not null]
|
||||
pullRequestCommentId text [not null]
|
||||
previewStatus applicationStatus [not null, default: 'idle']
|
||||
appName text [not null, unique]
|
||||
applicationId text [not null]
|
||||
domainId text
|
||||
createdAt text [not null]
|
||||
expiresAt text
|
||||
}
|
||||
|
||||
table project {
|
||||
projectId text [pk, not null]
|
||||
name text [not null]
|
||||
description text
|
||||
createdAt text [not null]
|
||||
userId text [not null]
|
||||
env text [not null, default: '']
|
||||
}
|
||||
|
||||
table redirect {
|
||||
redirectId text [pk, not null]
|
||||
regex text [not null]
|
||||
replacement text [not null]
|
||||
permanent boolean [not null, default: false]
|
||||
uniqueConfigKey serial [not null, increment]
|
||||
createdAt text [not null]
|
||||
applicationId text [not null]
|
||||
}
|
||||
|
||||
table redis {
|
||||
redisId text [pk, not null]
|
||||
name text [not null]
|
||||
appName text [not null, unique]
|
||||
description text
|
||||
password text [not null]
|
||||
dockerImage text [not null]
|
||||
command text
|
||||
env text
|
||||
memoryReservation text
|
||||
memoryLimit text
|
||||
cpuReservation text
|
||||
cpuLimit text
|
||||
externalPort integer
|
||||
createdAt text [not null]
|
||||
applicationStatus applicationStatus [not null, default: 'idle']
|
||||
projectId text [not null]
|
||||
serverId text
|
||||
}
|
||||
|
||||
table registry {
|
||||
registryId text [pk, not null]
|
||||
registryName text [not null]
|
||||
imagePrefix text
|
||||
username text [not null]
|
||||
password text [not null]
|
||||
registryUrl text [not null, default: '']
|
||||
createdAt text [not null]
|
||||
selfHosted RegistryType [not null, default: 'cloud']
|
||||
userId text [not null]
|
||||
}
|
||||
|
||||
table security {
|
||||
securityId text [pk, not null]
|
||||
username text [not null]
|
||||
password text [not null]
|
||||
createdAt text [not null]
|
||||
applicationId text [not null]
|
||||
|
||||
indexes {
|
||||
(username, applicationId) [name: 'security_username_applicationId_unique', unique]
|
||||
}
|
||||
}
|
||||
|
||||
table server {
|
||||
serverId text [pk, not null]
|
||||
name text [not null]
|
||||
description text
|
||||
ipAddress text [not null]
|
||||
port integer [not null]
|
||||
username text [not null, default: 'root']
|
||||
appName text [not null]
|
||||
enableDockerCleanup boolean [not null, default: false]
|
||||
createdAt text [not null]
|
||||
userId text [not null]
|
||||
serverStatus serverStatus [not null, default: 'active']
|
||||
command text [not null, default: '']
|
||||
sshKeyId text
|
||||
metricsConfig jsonb [not null, default: `{"server":{"type":"Remote","refreshRate":60,"port":4500,"token":"","urlCallback":"","cronJob":"","retentionDays":2,"thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}`]
|
||||
}
|
||||
|
||||
table session {
|
||||
id text [pk, not null]
|
||||
expires_at timestamp [not null]
|
||||
token text [not null, unique]
|
||||
created_at timestamp [not null]
|
||||
updated_at timestamp [not null]
|
||||
ip_address text
|
||||
user_agent text
|
||||
user_id text [not null]
|
||||
impersonated_by text
|
||||
active_organization_id text
|
||||
}
|
||||
|
||||
table slack {
|
||||
slackId text [pk, not null]
|
||||
webhookUrl text [not null]
|
||||
channel text
|
||||
}
|
||||
|
||||
table "ssh-key" {
|
||||
sshKeyId text [pk, not null]
|
||||
privateKey text [not null, default: '']
|
||||
publicKey text [not null]
|
||||
name text [not null]
|
||||
description text
|
||||
createdAt text [not null]
|
||||
lastUsedAt text
|
||||
userId text
|
||||
}
|
||||
|
||||
table telegram {
|
||||
telegramId text [pk, not null]
|
||||
botToken text [not null]
|
||||
chatId text [not null]
|
||||
}
|
||||
|
||||
table user {
|
||||
id text [pk, not null]
|
||||
name text [not null, default: '']
|
||||
token text [not null]
|
||||
isRegistered boolean [not null, default: false]
|
||||
expirationDate text [not null]
|
||||
createdAt text [not null]
|
||||
canCreateProjects boolean [not null, default: false]
|
||||
canAccessToSSHKeys boolean [not null, default: false]
|
||||
canCreateServices boolean [not null, default: false]
|
||||
canDeleteProjects boolean [not null, default: false]
|
||||
canDeleteServices boolean [not null, default: false]
|
||||
canAccessToDocker boolean [not null, default: false]
|
||||
canAccessToAPI boolean [not null, default: false]
|
||||
canAccessToGitProviders boolean [not null, default: false]
|
||||
canAccessToTraefikFiles boolean [not null, default: false]
|
||||
accesedProjects text[] [not null, default: `ARRAY[]::text[]`]
|
||||
accesedServices text[] [not null, default: `ARRAY[]::text[]`]
|
||||
email text [not null, unique]
|
||||
email_verified boolean [not null]
|
||||
image text
|
||||
role text
|
||||
banned boolean
|
||||
ban_reason text
|
||||
ban_expires timestamp
|
||||
updated_at timestamp [not null]
|
||||
serverIp text
|
||||
certificateType certificateType [not null, default: 'none']
|
||||
host text
|
||||
letsEncryptEmail text
|
||||
sshPrivateKey text
|
||||
enableDockerCleanup boolean [not null, default: false]
|
||||
enableLogRotation boolean [not null, default: false]
|
||||
enablePaidFeatures boolean [not null, default: false]
|
||||
metricsConfig jsonb [not null, default: `{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}`]
|
||||
cleanupCacheApplications boolean [not null, default: false]
|
||||
cleanupCacheOnPreviews boolean [not null, default: false]
|
||||
cleanupCacheOnCompose boolean [not null, default: false]
|
||||
stripeCustomerId text
|
||||
stripeSubscriptionId text
|
||||
serversQuantity integer [not null, default: 0]
|
||||
}
|
||||
|
||||
table verification {
|
||||
id text [pk, not null]
|
||||
identifier text [not null]
|
||||
value text [not null]
|
||||
expires_at timestamp [not null]
|
||||
created_at timestamp
|
||||
updated_at timestamp
|
||||
}
|
||||
|
||||
ref: mount.applicationId > application.applicationId
|
||||
|
||||
ref: mount.postgresId > postgres.postgresId
|
||||
|
||||
ref: mount.mariadbId > mariadb.mariadbId
|
||||
|
||||
ref: mount.mongoId > mongo.mongoId
|
||||
|
||||
ref: mount.mysqlId > mysql.mysqlId
|
||||
|
||||
ref: mount.redisId > redis.redisId
|
||||
|
||||
ref: mount.composeId > compose.composeId
|
||||
|
||||
ref: application.projectId > project.projectId
|
||||
|
||||
ref: application.customGitSSHKeyId > "ssh-key".sshKeyId
|
||||
|
||||
ref: application.registryId > registry.registryId
|
||||
|
||||
ref: application.githubId - github.githubId
|
||||
|
||||
ref: application.gitlabId - gitlab.gitlabId
|
||||
|
||||
ref: application.bitbucketId - bitbucket.bitbucketId
|
||||
|
||||
ref: application.serverId > server.serverId
|
||||
|
||||
ref: backup.destinationId > destination.destinationId
|
||||
|
||||
ref: backup.postgresId > postgres.postgresId
|
||||
|
||||
ref: backup.mariadbId > mariadb.mariadbId
|
||||
|
||||
ref: backup.mysqlId > mysql.mysqlId
|
||||
|
||||
ref: backup.mongoId > mongo.mongoId
|
||||
|
||||
ref: git_provider.gitProviderId - bitbucket.gitProviderId
|
||||
|
||||
ref: certificate.serverId > server.serverId
|
||||
|
||||
ref: certificate.userId - user.id
|
||||
|
||||
ref: compose.projectId > project.projectId
|
||||
|
||||
ref: compose.customGitSSHKeyId > "ssh-key".sshKeyId
|
||||
|
||||
ref: compose.githubId - github.githubId
|
||||
|
||||
ref: compose.gitlabId - gitlab.gitlabId
|
||||
|
||||
ref: compose.bitbucketId - bitbucket.bitbucketId
|
||||
|
||||
ref: compose.serverId > server.serverId
|
||||
|
||||
ref: deployment.applicationId > application.applicationId
|
||||
|
||||
ref: deployment.composeId > compose.composeId
|
||||
|
||||
ref: deployment.serverId > server.serverId
|
||||
|
||||
ref: deployment.previewDeploymentId > preview_deployments.previewDeploymentId
|
||||
|
||||
ref: destination.userId - user.id
|
||||
|
||||
ref: domain.applicationId > application.applicationId
|
||||
|
||||
ref: domain.composeId > compose.composeId
|
||||
|
||||
ref: preview_deployments.domainId - domain.domainId
|
||||
|
||||
ref: github.gitProviderId - git_provider.gitProviderId
|
||||
|
||||
ref: gitlab.gitProviderId - git_provider.gitProviderId
|
||||
|
||||
ref: git_provider.userId - user.id
|
||||
|
||||
ref: mariadb.projectId > project.projectId
|
||||
|
||||
ref: mariadb.serverId > server.serverId
|
||||
|
||||
ref: mongo.projectId > project.projectId
|
||||
|
||||
ref: mongo.serverId > server.serverId
|
||||
|
||||
ref: mysql.projectId > project.projectId
|
||||
|
||||
ref: mysql.serverId > server.serverId
|
||||
|
||||
ref: notification.slackId - slack.slackId
|
||||
|
||||
ref: notification.telegramId - telegram.telegramId
|
||||
|
||||
ref: notification.discordId - discord.discordId
|
||||
|
||||
ref: notification.emailId - email.emailId
|
||||
|
||||
ref: notification.gotifyId - gotify.gotifyId
|
||||
|
||||
ref: notification.userId - user.id
|
||||
|
||||
ref: port.applicationId > application.applicationId
|
||||
|
||||
ref: postgres.projectId > project.projectId
|
||||
|
||||
ref: postgres.serverId > server.serverId
|
||||
|
||||
ref: preview_deployments.applicationId > application.applicationId
|
||||
|
||||
ref: project.userId - user.id
|
||||
|
||||
ref: redirect.applicationId > application.applicationId
|
||||
|
||||
ref: redis.projectId > project.projectId
|
||||
|
||||
ref: redis.serverId > server.serverId
|
||||
|
||||
ref: registry.userId - user.id
|
||||
|
||||
ref: security.applicationId > application.applicationId
|
||||
|
||||
ref: server.userId - user.id
|
||||
|
||||
ref: server.sshKeyId > "ssh-key".sshKeyId
|
||||
|
||||
ref: "ssh-key".userId - user.id
|
||||
@@ -22,6 +22,8 @@ import { mysql } from "./mysql";
|
||||
import { postgres } from "./postgres";
|
||||
import { redis } from "./redis";
|
||||
import { sshKeys } from "./ssh-key";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
import { generateAppName } from "./utils";
|
||||
|
||||
export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]);
|
||||
@@ -40,12 +42,14 @@ export const server = pgTable("server", {
|
||||
.notNull()
|
||||
.$defaultFn(() => generateAppName("server")),
|
||||
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
|
||||
createdAt: text("createdAt")
|
||||
createdAt: text("createdAt").notNull(),
|
||||
// .$defaultFn(() => new Date().toISOString()),
|
||||
// userId: text("userId")
|
||||
// .notNull()
|
||||
// .references(() => user.userId, { onDelete: "cascade" }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
adminId: text("adminId")
|
||||
.notNull()
|
||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
serverStatus: serverStatus("serverStatus").notNull().default("active"),
|
||||
command: text("command").notNull().default(""),
|
||||
sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, {
|
||||
@@ -100,10 +104,10 @@ export const server = pgTable("server", {
|
||||
});
|
||||
|
||||
export const serverRelations = relations(server, ({ one, many }) => ({
|
||||
admin: one(admins, {
|
||||
fields: [server.adminId],
|
||||
references: [admins.adminId],
|
||||
}),
|
||||
// user: one(user, {
|
||||
// fields: [server.userId],
|
||||
// references: [user.id],
|
||||
// }),
|
||||
deployments: many(deployments),
|
||||
sshKey: one(sshKeys, {
|
||||
fields: [server.sshKeyId],
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import { auth } from "./auth";
|
||||
import { users_temp } from "./user";
|
||||
|
||||
// OLD TABLE
|
||||
export const session = pgTable("session_temp", {
|
||||
id: text("id").primaryKey(),
|
||||
expiresAt: timestamp("expires_at").notNull(),
|
||||
token: text("token").notNull().unique(),
|
||||
createdAt: timestamp("created_at").notNull(),
|
||||
updatedAt: timestamp("updated_at").notNull(),
|
||||
ipAddress: text("ip_address"),
|
||||
userAgent: text("user_agent"),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => users_temp.id),
|
||||
impersonatedBy: text("impersonated_by"),
|
||||
activeOrganizationId: text("active_organization_id"),
|
||||
});
|
||||
|
||||
export const sessionTable = pgTable("session", {
|
||||
id: text("id").primaryKey(),
|
||||
|
||||
@@ -7,6 +7,8 @@ import { admins } from "./admin";
|
||||
import { applications } from "./application";
|
||||
import { compose } from "./compose";
|
||||
import { server } from "./server";
|
||||
import { users_temp } from "./user";
|
||||
// import { user } from "./user";
|
||||
|
||||
export const sshKeys = pgTable("ssh-key", {
|
||||
sshKeyId: text("sshKeyId")
|
||||
@@ -21,18 +23,21 @@ export const sshKeys = pgTable("ssh-key", {
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
lastUsedAt: text("lastUsedAt"),
|
||||
adminId: text("adminId").references(() => admins.adminId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// userId: text("userId").references(() => user.userId, {
|
||||
// onDelete: "cascade",
|
||||
// }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users_temp.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const sshKeysRelations = relations(sshKeys, ({ many, one }) => ({
|
||||
applications: many(applications),
|
||||
compose: many(compose),
|
||||
servers: many(server),
|
||||
admin: one(admins, {
|
||||
fields: [sshKeys.adminId],
|
||||
references: [admins.adminId],
|
||||
user: one(users_temp, {
|
||||
fields: [sshKeys.userId],
|
||||
references: [users_temp.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -48,7 +53,7 @@ export const apiCreateSshKey = createSchema
|
||||
description: true,
|
||||
privateKey: true,
|
||||
publicKey: true,
|
||||
adminId: true,
|
||||
userId: true,
|
||||
})
|
||||
.merge(sshKeyCreate.pick({ privateKey: true }));
|
||||
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import {
|
||||
boolean,
|
||||
integer,
|
||||
jsonb,
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { account, organization } from "./account";
|
||||
import { admins } from "./admin";
|
||||
import { auth } from "./auth";
|
||||
import { certificateType } from "./shared";
|
||||
/**
|
||||
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
||||
* database instance for multiple projects.
|
||||
@@ -12,6 +21,8 @@ import { auth } from "./auth";
|
||||
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
|
||||
*/
|
||||
|
||||
// OLD TABLE
|
||||
|
||||
export const users = pgTable("user", {
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
@@ -56,23 +67,146 @@ export const users = pgTable("user", {
|
||||
.references(() => auth.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users, ({ one }) => ({
|
||||
auth: one(auth, {
|
||||
fields: [users.authId],
|
||||
references: [auth.id],
|
||||
}),
|
||||
admin: one(admins, {
|
||||
fields: [users.adminId],
|
||||
references: [admins.adminId],
|
||||
// TEMP
|
||||
export const users_temp = pgTable("user_temp", {
|
||||
id: text("id")
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
name: text("name").notNull().default(""),
|
||||
token: text("token").notNull().default(""),
|
||||
isRegistered: boolean("isRegistered").notNull().default(false),
|
||||
expirationDate: text("expirationDate")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
createdAt2: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
canCreateProjects: boolean("canCreateProjects").notNull().default(false),
|
||||
canAccessToSSHKeys: boolean("canAccessToSSHKeys").notNull().default(false),
|
||||
canCreateServices: boolean("canCreateServices").notNull().default(false),
|
||||
canDeleteProjects: boolean("canDeleteProjects").notNull().default(false),
|
||||
canDeleteServices: boolean("canDeleteServices").notNull().default(false),
|
||||
canAccessToDocker: boolean("canAccessToDocker").notNull().default(false),
|
||||
canAccessToAPI: boolean("canAccessToAPI").notNull().default(false),
|
||||
canAccessToGitProviders: boolean("canAccessToGitProviders")
|
||||
.notNull()
|
||||
.default(false),
|
||||
canAccessToTraefikFiles: boolean("canAccessToTraefikFiles")
|
||||
.notNull()
|
||||
.default(false),
|
||||
accessedProjects: text("accesedProjects")
|
||||
.array()
|
||||
.notNull()
|
||||
.default(sql`ARRAY[]::text[]`),
|
||||
accessedServices: text("accesedServices")
|
||||
.array()
|
||||
.notNull()
|
||||
.default(sql`ARRAY[]::text[]`),
|
||||
// authId: text("authId")
|
||||
// .notNull()
|
||||
// .references(() => auth.id, { onDelete: "cascade" }),
|
||||
// Auth
|
||||
email: text("email").notNull().unique(),
|
||||
emailVerified: boolean("email_verified").notNull(),
|
||||
image: text("image"),
|
||||
banned: boolean("banned"),
|
||||
banReason: text("ban_reason"),
|
||||
banExpires: timestamp("ban_expires"),
|
||||
updatedAt: timestamp("updated_at").notNull(),
|
||||
// Admin
|
||||
serverIp: text("serverIp"),
|
||||
certificateType: certificateType("certificateType").notNull().default("none"),
|
||||
host: text("host"),
|
||||
letsEncryptEmail: text("letsEncryptEmail"),
|
||||
sshPrivateKey: text("sshPrivateKey"),
|
||||
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
|
||||
enableLogRotation: boolean("enableLogRotation").notNull().default(false),
|
||||
// Metrics
|
||||
enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false),
|
||||
metricsConfig: jsonb("metricsConfig")
|
||||
.$type<{
|
||||
server: {
|
||||
type: "Dokploy" | "Remote";
|
||||
refreshRate: number;
|
||||
port: number;
|
||||
token: string;
|
||||
urlCallback: string;
|
||||
retentionDays: number;
|
||||
cronJob: string;
|
||||
thresholds: {
|
||||
cpu: number;
|
||||
memory: number;
|
||||
};
|
||||
};
|
||||
containers: {
|
||||
refreshRate: number;
|
||||
services: {
|
||||
include: string[];
|
||||
exclude: string[];
|
||||
};
|
||||
};
|
||||
}>()
|
||||
.notNull()
|
||||
.default({
|
||||
server: {
|
||||
type: "Dokploy",
|
||||
refreshRate: 60,
|
||||
port: 4500,
|
||||
token: "",
|
||||
retentionDays: 2,
|
||||
cronJob: "",
|
||||
urlCallback: "",
|
||||
thresholds: {
|
||||
cpu: 0,
|
||||
memory: 0,
|
||||
},
|
||||
},
|
||||
containers: {
|
||||
refreshRate: 60,
|
||||
services: {
|
||||
include: [],
|
||||
exclude: [],
|
||||
},
|
||||
},
|
||||
}),
|
||||
cleanupCacheApplications: boolean("cleanupCacheApplications")
|
||||
.notNull()
|
||||
.default(false),
|
||||
cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews")
|
||||
.notNull()
|
||||
.default(false),
|
||||
cleanupCacheOnCompose: boolean("cleanupCacheOnCompose")
|
||||
.notNull()
|
||||
.default(false),
|
||||
stripeCustomerId: text("stripeCustomerId"),
|
||||
stripeSubscriptionId: text("stripeSubscriptionId"),
|
||||
serversQuantity: integer("serversQuantity").notNull().default(0),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users_temp, ({ one, many }) => ({
|
||||
// auth: one(auth, {
|
||||
// fields: [users.authId],
|
||||
// references: [auth.id],
|
||||
// }),
|
||||
account: one(account, {
|
||||
fields: [users_temp.id],
|
||||
references: [account.userId],
|
||||
}),
|
||||
organizations: many(organization),
|
||||
// admin: one(admins, {
|
||||
// fields: [users.adminId],
|
||||
// references: [admins.adminId],
|
||||
// }),
|
||||
}));
|
||||
|
||||
const createSchema = createInsertSchema(users, {
|
||||
userId: z.string().min(1),
|
||||
authId: z.string().min(1),
|
||||
const createSchema = createInsertSchema(users_temp, {
|
||||
id: z.string().min(1),
|
||||
// authId: z.string().min(1),
|
||||
token: z.string().min(1),
|
||||
isRegistered: z.boolean().optional(),
|
||||
adminId: z.string(),
|
||||
// adminId: z.string(),
|
||||
accessedProjects: z.array(z.string()).optional(),
|
||||
accessedServices: z.array(z.string()).optional(),
|
||||
canCreateProjects: z.boolean().optional(),
|
||||
@@ -89,7 +223,7 @@ export const apiCreateUserInvitation = createSchema.pick({}).extend({
|
||||
|
||||
export const apiRemoveUser = createSchema
|
||||
.pick({
|
||||
authId: true,
|
||||
id: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
@@ -101,7 +235,7 @@ export const apiFindOneToken = createSchema
|
||||
|
||||
export const apiAssignPermissions = createSchema
|
||||
.pick({
|
||||
userId: true,
|
||||
id: true,
|
||||
canCreateProjects: true,
|
||||
canCreateServices: true,
|
||||
canDeleteProjects: true,
|
||||
@@ -118,12 +252,12 @@ export const apiAssignPermissions = createSchema
|
||||
|
||||
export const apiFindOneUser = createSchema
|
||||
.pick({
|
||||
userId: true,
|
||||
id: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
export const apiFindOneUserByAuth = createSchema
|
||||
.pick({
|
||||
authId: true,
|
||||
// authId: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
@@ -118,3 +118,5 @@ export * from "./monitoring/utils";
|
||||
export * from "./db/validations/domain";
|
||||
export * from "./db/validations/index";
|
||||
export * from "./utils/gpu-setup";
|
||||
|
||||
export * from "./lib/auth";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user