Compare commits

..

35 Commits

Author SHA1 Message Date
Mauricio Siu
56af89468a Merge pull request #1313 from nktnet1/superset-networks
docs(template): note on networking for superset
2025-02-16 21:34:40 -06:00
Mauricio Siu
b1502f5f82 Merge pull request #1329 from drudge/templates/registry
feat(template): add docker registry template
2025-02-16 21:33:54 -06:00
Mauricio Siu
c78b8cfead Update package.json 2025-02-16 21:30:57 -06:00
Nicholas Penree
48c4ec55f9 fix(template): switch outline to png for dark mode 2025-02-16 15:52:15 -05:00
Nicholas Penree
2ebb02dc20 feat(template): add docker registry template 2025-02-15 22:46:37 -05:00
Mauricio Siu
9ca3ab3845 Merge pull request #1327 from Krobys/canary
feat(template): Add Appwrite template
2025-02-15 16:00:19 -06:00
Krobys
0baf9d8962 feat(template): add Appwrite 2025-02-15 21:46:18 +00:00
Mauricio Siu
71c609df0e Merge pull request #1326 from Dokploy/1304-preview-deployments-dont-work-when-enabling-auth-or-redirects
fix: inherit security & redirects from application
2025-02-15 15:24:36 -06:00
Mauricio Siu
450302b2c2 fix: inherit security & redirects from application 2025-02-15 15:23:33 -06:00
Mauricio Siu
71a007a4b3 Merge pull request #1325 from Dokploy/1257-main-server-error-error-http-code-409-unexpected---rpc-error
fix: handle race condition to catch recreation base containers
2025-02-15 14:26:52 -06:00
Mauricio Siu
871931b460 fix: handle race condition to catch recreation base containers 2025-02-15 14:23:54 -06:00
Mauricio Siu
3a7bb5016c Merge pull request #1324 from Dokploy/1320-missing-path-option-when-adding-a-template-in-dokploy
refactor: add missing path option
2025-02-15 14:09:33 -06:00
Mauricio Siu
23b59076b8 refactor: add missing path option 2025-02-15 13:35:25 -06:00
Mauricio Siu
2ddfc83f36 Merge pull request #1322 from drudge/ui/compose-monitoring-status
style(monitoring): use status badges for compose monitoring
2025-02-15 13:30:07 -06:00
Mauricio Siu
ba54124a56 Merge pull request #1321 from drudge/templates/outline
feat(template): add outline
2025-02-15 13:29:18 -06:00
Mauricio Siu
64bdf07dbd Merge pull request #1319 from mafrasil/feat-add-convex-tpl
feat(template): add convex.dev
2025-02-15 13:19:15 -06:00
Mauricio Siu
8366219266 refactor: format 2025-02-15 13:18:54 -06:00
Mauricio Siu
f38fb96eaf Merge branch 'canary' into feat-add-convex-tpl 2025-02-15 13:17:16 -06:00
Nicholas Penree
3b1ade804f style(monitoring): use status badges for compose monitoring 2025-02-15 14:16:30 -05:00
Mauricio Siu
fd69b45e5e refactor: update envs 2025-02-15 13:15:32 -06:00
Mauricio Siu
12034e460e Merge pull request #1316 from mezotv/patch-2
feat(template): update plausible
2025-02-15 13:08:23 -06:00
Mauricio Siu
2b5a1d90b0 Merge pull request #1309 from jeffersoncbd/canary
feat: Add Trilium app template
2025-02-15 13:07:38 -06:00
Mauricio Siu
e7195c8acf Update apps/dokploy/templates/trilium/docker-compose.yml 2025-02-15 13:07:33 -06:00
Nicholas Penree
9ace0f38cd chore(lint): fix lint 2025-02-15 02:22:51 -05:00
Nicholas Penree
796e50ed5f feat(template): add outline 2025-02-15 02:22:37 -05:00
mafrasil
ed54df9bd2 feat(template): add convex.dev 2025-02-14 09:23:41 +04:00
Dominik Koch
bf6c2698d4 fix: update plausible version 2025-02-13 21:52:01 +01:00
Dominik Koch
bbdda014d8 feat(template): update plausible 2025-02-13 21:46:06 +01:00
Khiet Tam Nguyen
d9c83b7010 docs(template): note on networking for superset 2025-02-13 20:36:03 +11:00
Mauricio Siu
209029214e Merge pull request #1307 from vytenisstaugaitis/canary
chore: update wordpress version to v6.7.1
2025-02-12 22:16:14 -06:00
Jefferson Carlos
9de3bf3c32 Add files via upload 2025-02-13 00:33:11 -03:00
Jefferson Carlos
2c65fc22b0 Update templates.ts 2025-02-13 00:32:45 -03:00
Jefferson Carlos
6688b14753 Create docker-compose.yml 2025-02-13 00:22:18 -03:00
Jefferson Carlos
6ea2a82bb0 Create index.ts for Trilium app 2025-02-13 00:21:23 -03:00
vytenisstaugaitis
e01347673e chore: update wordpress version to v6.7.1 2025-02-12 22:31:52 +02:00
157 changed files with 2417 additions and 24396 deletions

View File

@@ -1,3 +1,5 @@
import { badgeStateColor } from "@/components/dashboard/application/logs/show";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -96,7 +98,10 @@ export const ComposeFreeMonitoring = ({
key={container.containerId}
value={container.name}
>
{container.name} ({container.containerId}) {container.state}
{container.name} ({container.containerId}){" "}
<Badge variant={badgeStateColor(container.state)}>
{container.state}
</Badge>
</SelectItem>
))}
<SelectLabel>Containers ({data?.length})</SelectLabel>

View File

@@ -1,3 +1,5 @@
import { badgeStateColor } from "@/components/dashboard/application/logs/show";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -102,7 +104,9 @@ export const ComposePaidMonitoring = ({
value={container.name}
>
{container.name} ({container.containerId}){" "}
{container.state}
<Badge variant={badgeStateColor(container.state)}>
{container.state}
</Badge>
</SelectItem>
))}
<SelectLabel>Containers ({data?.length})</SelectLabel>

View File

@@ -21,7 +21,6 @@ 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";
@@ -98,18 +97,6 @@ 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}>

View File

@@ -57,7 +57,7 @@ export const ShowProjects = () => {
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
const { mutateAsync } = api.project.remove.useMutation();
@@ -91,7 +91,7 @@ export const ShowProjects = () => {
</CardDescription>
</CardHeader>
{(auth?.role === "owner" || user?.canCreateProjects) && (
{(auth?.rol === "admin" || user?.canCreateProjects) && (
<div className="">
<HandleProject />
</div>
@@ -293,7 +293,7 @@ export const ShowProjects = () => {
<div
onClick={(e) => e.stopPropagation()}
>
{(auth?.role === "owner" ||
{(auth?.rol === "admin" ||
user?.canDeleteProjects) && (
<AlertDialog>
<AlertDialogTrigger className="w-full">

View File

@@ -18,7 +18,6 @@ import {
CommandList,
CommandSeparator,
} from "@/components/ui/command";
import { authClient } from "@/lib/auth";
import {
type Services,
extractServices,
@@ -36,10 +35,8 @@ export const SearchCommand = () => {
const router = useRouter();
const [open, setOpen] = React.useState(false);
const [search, setSearch] = React.useState("");
const { data: session } = authClient.getSession();
const { data } = api.project.all.useQuery(undefined, {
enabled: !!session,
});
const { data } = api.project.all.useQuery();
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
React.useEffect(() => {

View File

@@ -15,7 +15,7 @@ export const ShowWelcomeDokploy = () => {
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
if (!isCloud || data?.role !== "admin") {
if (!isCloud || data?.rol !== "admin") {
return null;
}
@@ -24,14 +24,14 @@ export const ShowWelcomeDokploy = () => {
!isLoading &&
isCloud &&
!localStorage.getItem("hasSeenCloudWelcomeModal") &&
data?.role === "owner"
data?.rol === "admin"
) {
setOpen(true);
}
}, [isCloud, isLoading]);
const handleClose = (isOpen: boolean) => {
if (data?.role === "owner") {
if (data?.rol === "admin") {
setOpen(isOpen);
if (!isOpen) {
localStorage.setItem("hasSeenCloudWelcomeModal", "true"); // Establece el flag al cerrar el modal

View File

@@ -51,7 +51,7 @@ export const GenerateToken = () => {
<Label>Token</Label>
<ToggleVisibilityInput
placeholder="Token"
value={data?.user?.token || ""}
value={data?.token || ""}
disabled
/>
</div>

View File

@@ -73,9 +73,9 @@ export const ProfileForm = () => {
const form = useForm<Profile>({
defaultValues: {
email: data?.user?.email || "",
email: data?.email || "",
password: "",
image: data?.user?.image || "",
image: data?.image || "",
currentPassword: "",
},
resolver: zodResolver(profileSchema),
@@ -84,14 +84,14 @@ export const ProfileForm = () => {
useEffect(() => {
if (data) {
form.reset({
email: data?.user?.email || "",
email: data?.email || "",
password: "",
image: data?.user?.image || "",
image: data?.image || "",
currentPassword: "",
});
if (data.user.email) {
generateSHA256Hash(data.user.email).then((hash) => {
if (data.email) {
generateSHA256Hash(data.email).then((hash) => {
setGravatarHash(hash);
});
}

View File

@@ -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?.role === "owner" || user?.canAccessToTraefikFiles) &&
(auth?.rol === "admin" || 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?.role === "owner" || user?.canAccessToDocker) && !isCloud),
!!((auth?.rol === "admin" || 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?.role === "owner" || user?.canAccessToDocker) && !isCloud),
!!((auth?.rol === "admin" || 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?.role === "owner" || user?.canAccessToDocker) && !isCloud),
!!((auth?.rol === "admin" || 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?.role === "owner" && !isCloud),
!!(auth?.rol === "admin" && !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?.role === "owner"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
},
{
isSingle: true,
@@ -274,7 +274,7 @@ const MENU: Menu = {
icon: Users,
url: "/dashboard/settings/users",
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
},
{
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?.role === "owner" || user?.canAccessToSSHKeys),
!!(auth?.rol === "admin" || 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?.role === "owner" || user?.canAccessToGitProviders),
!!(auth?.rol === "admin" || 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?.role === "owner"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
},
{
isSingle: true,
@@ -308,7 +308,7 @@ const MENU: Menu = {
url: "/dashboard/settings/destinations",
icon: Database,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
},
{
@@ -317,7 +317,7 @@ const MENU: Menu = {
url: "/dashboard/settings/certificates",
icon: ShieldCheck,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
},
{
isSingle: true,
@@ -326,7 +326,7 @@ const MENU: Menu = {
icon: Boxes,
// Only enabled for admins in non-cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!(auth?.role === "owner" && !isCloud),
!!(auth?.rol === "admin" && !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?.role === "owner"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
},
{
isSingle: true,
@@ -343,7 +343,7 @@ const MENU: Menu = {
icon: CreditCard,
// Only enabled for admins in cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!(auth?.role === "owner" && isCloud),
!!(auth?.rol === "admin" && isCloud),
},
],
@@ -537,7 +537,7 @@ export default function Page({ children }: Props) {
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
@@ -557,7 +557,7 @@ export default function Page({ children }: Props) {
// const showProjectsButton =
// currentPath === "/dashboard/projects" &&
// (auth?.rol === "owner" || user?.canCreateProjects);
// (auth?.rol === "admin" || user?.canCreateProjects);
return (
<SidebarProvider
@@ -783,7 +783,7 @@ export default function Page({ children }: Props) {
</SidebarMenuButton>
</SidebarMenuItem>
))}
{!isCloud && auth?.role === "owner" && (
{!isCloud && auth?.rol === "admin" && (
<SidebarMenuItem>
<SidebarMenuButton asChild>
<UpdateServerButton />

View File

@@ -15,7 +15,6 @@ 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";
@@ -37,11 +36,11 @@ export const UserNav = () => {
authId: data?.id || "",
},
{
enabled: !!data?.id && data?.role === "member",
enabled: !!data?.id && data?.rol === "user",
},
);
const { locale, setLocale } = useLocale();
// const { mutateAsync } = api.auth.logout.useMutation();
const { mutateAsync } = api.auth.logout.useMutation();
return (
<DropdownMenu>
@@ -51,15 +50,12 @@ 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?.user?.image || ""}
alt={data?.user?.image || ""}
/>
<AvatarImage src={data?.image || ""} alt={data?.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?.user?.email}</span>
<span className="truncate text-xs">{data?.email}</span>
</div>
<ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton>
@@ -74,7 +70,7 @@ export const UserNav = () => {
<DropdownMenuLabel className="flex flex-col">
My Account
<span className="text-xs font-normal text-muted-foreground">
{data?.user?.email}
{data?.email}
</span>
</DropdownMenuLabel>
<ModeToggle />
@@ -99,7 +95,7 @@ export const UserNav = () => {
>
Monitoring
</DropdownMenuItem>
{(data?.role === "owner" || user?.canAccessToTraefikFiles) && (
{(data?.rol === "admin" || user?.canAccessToTraefikFiles) && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -109,7 +105,7 @@ export const UserNav = () => {
Traefik
</DropdownMenuItem>
)}
{(data?.role === "owner" || user?.canAccessToDocker) && (
{(data?.rol === "admin" || user?.canAccessToDocker) && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -122,7 +118,7 @@ export const UserNav = () => {
</DropdownMenuItem>
)}
{data?.role === "owner" && (
{data?.rol === "admin" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -143,7 +139,7 @@ export const UserNav = () => {
>
Profile
</DropdownMenuItem>
{data?.role === "owner" && (
{data?.rol === "admin" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -154,7 +150,7 @@ export const UserNav = () => {
</DropdownMenuItem>
)}
{data?.role === "owner" && (
{data?.rol === "admin" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -167,7 +163,7 @@ export const UserNav = () => {
</>
)}
</DropdownMenuGroup>
{isCloud && data?.role === "owner" && (
{isCloud && data?.rol === "admin" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -182,12 +178,9 @@ export const UserNav = () => {
<DropdownMenuItem
className="cursor-pointer"
onClick={async () => {
await authClient.signOut().then(() => {
await mutateAsync().then(() => {
router.push("/");
});
// await mutateAsync().then(() => {
// router.push("/");
// });
}}
>
Log out

View File

@@ -1,127 +0,0 @@
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;

View File

@@ -1,211 +0,0 @@
-- 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";

View File

@@ -1,32 +0,0 @@
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;

View File

@@ -1,2 +0,0 @@
ALTER TABLE "user_temp" ALTER COLUMN "token" SET DEFAULT '';--> statement-breakpoint
ALTER TABLE "user_temp" ADD COLUMN "created_at" timestamp DEFAULT now();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -463,34 +463,6 @@
"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
}
]
}

View File

@@ -1,7 +0,0 @@
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()],
});

View File

@@ -1,126 +0,0 @@
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);
});

View File

@@ -1,6 +1,6 @@
{
"name": "dokploy",
"version": "v0.18.2",
"version": "v0.18.4",
"private": true,
"license": "Apache-2.0",
"type": "module",
@@ -16,7 +16,6 @@
"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",
@@ -36,7 +35,6 @@
"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",

View File

@@ -1,7 +0,0 @@
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);

View File

@@ -42,7 +42,7 @@ export default async function handler(
const auth = await findAuthById(value as string);
let adminId = "";
if (auth.role === "owner") {
if (auth.rol === "admin") {
const admin = await findAdminByAuthId(auth.id);
adminId = admin.adminId;
} else {

View File

@@ -1,7 +1,7 @@
import { buffer } from "node:stream/consumers";
import { db } from "@/server/db";
import { admins, server, users_temp } from "@/server/db/schema";
import { findAdminById, findUserById } from "@dokploy/server";
import { admins, server } from "@/server/db/schema";
import { findAdminById } from "@dokploy/server";
import { asc, eq } from "drizzle-orm";
import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
@@ -64,35 +64,33 @@ export default async function handler(
session.subscription as string,
);
await db
.update(users_temp)
.update(admins)
.set({
stripeCustomerId: session.customer as string,
stripeSubscriptionId: session.subscription as string,
serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(eq(users_temp.id, adminId))
.where(eq(admins.adminId, adminId))
.returning();
const admin = await findUserById(adminId);
const admin = await findAdminById(adminId);
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
break;
}
case "customer.subscription.created": {
const newSubscription = event.data.object as Stripe.Subscription;
await db
.update(users_temp)
.update(admins)
.set({
stripeSubscriptionId: newSubscription.id,
stripeCustomerId: newSubscription.customer as string,
})
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
)
.where(eq(admins.stripeCustomerId, newSubscription.customer as string))
.returning();
break;
@@ -102,16 +100,14 @@ export default async function handler(
const newSubscription = event.data.object as Stripe.Subscription;
await db
.update(users_temp)
.update(admins)
.set({
stripeSubscriptionId: null,
serversQuantity: 0,
})
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
);
.where(eq(admins.stripeCustomerId, newSubscription.customer as string));
const admin = await findUserByStripeCustomerId(
const admin = await findAdminByStripeCustomerId(
newSubscription.customer as string,
);
@@ -119,13 +115,13 @@ export default async function handler(
return res.status(400).send("Webhook Error: Admin not found");
}
await disableServers(admin.id);
await disableServers(admin.adminId);
break;
}
case "customer.subscription.updated": {
const newSubscription = event.data.object as Stripe.Subscription;
const admin = await findUserByStripeCustomerId(
const admin = await findAdminByStripeCustomerId(
newSubscription.customer as string,
);
@@ -135,23 +131,23 @@ export default async function handler(
if (newSubscription.status === "active") {
await db
.update(users_temp)
.update(admins)
.set({
serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
eq(admins.stripeCustomerId, newSubscription.customer as string),
);
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
} else {
await disableServers(admin.id);
await disableServers(admin.adminId);
await db
.update(users_temp)
.update(admins)
.set({ serversQuantity: 0 })
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
eq(admins.stripeCustomerId, newSubscription.customer as string),
);
}
@@ -178,7 +174,7 @@ export default async function handler(
})
.where(eq(admins.stripeCustomerId, suscription.customer as string));
const admin = await findUserByStripeCustomerId(
const admin = await findAdminByStripeCustomerId(
suscription.customer as string,
);
@@ -186,7 +182,7 @@ export default async function handler(
return res.status(400).send("Webhook Error: Admin not found");
}
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
break;
}
case "invoice.payment_failed": {
@@ -197,7 +193,7 @@ export default async function handler(
);
if (subscription.status !== "active") {
const admin = await findUserByStripeCustomerId(
const admin = await findAdminByStripeCustomerId(
newInvoice.customer as string,
);
@@ -211,7 +207,7 @@ export default async function handler(
})
.where(eq(admins.stripeCustomerId, newInvoice.customer as string));
await disableServers(admin.id);
await disableServers(admin.adminId);
}
break;
@@ -220,20 +216,20 @@ export default async function handler(
case "customer.deleted": {
const customer = event.data.object as Stripe.Customer;
const admin = await findUserByStripeCustomerId(customer.id);
const admin = await findAdminByStripeCustomerId(customer.id);
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
await disableServers(admin.id);
await disableServers(admin.adminId);
await db
.update(users_temp)
.update(admins)
.set({
stripeCustomerId: null,
stripeSubscriptionId: null,
serversQuantity: 0,
})
.where(eq(users_temp.stripeCustomerId, customer.id));
.where(eq(admins.stripeCustomerId, customer.id));
break;
}
@@ -244,20 +240,20 @@ export default async function handler(
return res.status(200).json({ received: true });
}
const disableServers = async (userId: string) => {
const disableServers = async (adminId: string) => {
await db
.update(server)
.set({
serverStatus: "inactive",
})
.where(eq(server.userId, userId));
.where(eq(server.adminId, adminId));
};
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
const user = db.query.users_temp.findFirst({
where: eq(users_temp.stripeCustomerId, stripeCustomerId),
const findAdminByStripeCustomerId = async (stripeCustomerId: string) => {
const admin = db.query.admins.findFirst({
where: eq(admins.stripeCustomerId, stripeCustomerId),
});
return user;
return admin;
};
const activateServer = async (serverId: string) => {
@@ -274,19 +270,19 @@ const deactivateServer = async (serverId: string) => {
.where(eq(server.serverId, serverId));
};
export const findServersByUserIdSorted = async (userId: string) => {
export const findServersByAdminIdSorted = async (adminId: string) => {
const servers = await db.query.server.findMany({
where: eq(server.userId, userId),
where: eq(server.adminId, adminId),
orderBy: asc(server.createdAt),
});
return servers;
};
export const updateServersBasedOnQuantity = async (
userId: string,
adminId: string,
newServersQuantity: number,
) => {
const servers = await findServersByUserIdSorted(userId);
const servers = await findServersByAdminIdSorted(adminId);
if (servers.length > newServersQuantity) {
for (const [index, server] of servers.entries()) {

View File

@@ -53,7 +53,7 @@ export async function getServerSideProps(
await helpers.project.all.prefetch();
const auth = await helpers.auth.get.fetch();
if (auth.role === "member") {
if (auth.rol === "user") {
const user = await helpers.user.byAuthId.fetch({
authId: auth.id,
});

View File

@@ -206,7 +206,7 @@ const Project = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
const { data, isLoading, refetch } = api.project.one.useQuery({ projectId });
@@ -335,7 +335,7 @@ const Project = (
</CardTitle>
<CardDescription>{data?.description}</CardDescription>
</CardHeader>
{(auth?.role === "owner" || user?.canCreateServices) && (
{(auth?.rol === "admin" || user?.canCreateServices) && (
<div className="flex flex-row gap-4 flex-wrap">
<ProjectEnvironment projectId={projectId}>
<Button variant="outline">Project Environment</Button>

View File

@@ -93,7 +93,7 @@ const Service = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
@@ -186,7 +186,7 @@ const Service = (
<div className="flex flex-row gap-2 justify-end">
<UpdateApplication applicationId={applicationId} />
{(auth?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={applicationId} type="application" />
)}
</div>

View File

@@ -87,7 +87,7 @@ const Service = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
@@ -181,7 +181,7 @@ const Service = (
<div className="flex flex-row gap-2 justify-end">
<UpdateCompose composeId={composeId} />
{(auth?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={composeId} type="compose" />
)}
</div>

View File

@@ -68,7 +68,7 @@ const Mariadb = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
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?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={mariadbId} type="mariadb" />
)}
</div>

View File

@@ -68,7 +68,7 @@ const Mongo = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
@@ -156,7 +156,7 @@ const Mongo = (
<div className="flex flex-row gap-2 justify-end">
<UpdateMongo mongoId={mongoId} />
{(auth?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={mongoId} type="mongo" />
)}
</div>

View File

@@ -67,7 +67,7 @@ const MySql = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
@@ -156,7 +156,7 @@ const MySql = (
<div className="flex flex-row gap-2 justify-end">
<UpdateMysql mysqlId={mysqlId} />
{(auth?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={mysqlId} type="mysql" />
)}
</div>

View File

@@ -66,7 +66,7 @@ const Postgresql = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
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?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={postgresId} type="postgres" />
)}
</div>

View File

@@ -67,7 +67,7 @@ const Redis = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.role === "member",
enabled: !!auth?.id && auth?.rol === "user",
},
);
@@ -155,7 +155,7 @@ const Redis = (
<div className="flex flex-row gap-2 justify-end">
<UpdateRedis redisId={redisId} />
{(auth?.role === "owner" || user?.canDeleteServices) && (
{(auth?.rol === "admin" || user?.canDeleteServices) && (
<DeleteService id={redisId} type="redis" />
)}
</div>

View File

@@ -30,7 +30,7 @@ export async function getServerSideProps(
}
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -25,7 +25,7 @@ export async function getServerSideProps(
) {
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -34,7 +34,7 @@ export async function getServerSideProps(
};
}
const { user, session } = await validateRequest(ctx.req, ctx.res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -26,7 +26,7 @@ export async function getServerSideProps(
) {
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -51,7 +51,7 @@ export async function getServerSideProps(
await helpers.settings.isCloud.prefetch();
const auth = await helpers.auth.get.fetch();
if (auth.role === "member") {
if (auth.rol === "user") {
const user = await helpers.user.byAuthId.fetch({
authId: auth.id,
});

View File

@@ -190,7 +190,7 @@ export async function getServerSideProps(
},
};
}
if (user.role === "member") {
if (user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -26,7 +26,7 @@ export async function getServerSideProps(
) {
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -19,7 +19,7 @@ const Page = () => {
authId: data?.id || "",
},
{
enabled: !!data?.id && data?.role === "user",
enabled: !!data?.id && data?.rol === "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?.role === "owner") && <GenerateToken />}
{(user?.canAccessToAPI || data?.rol === "admin") && <GenerateToken />}
{isCloud && <RemoveSelfAccount />}
</div>
@@ -62,7 +62,7 @@ export async function getServerSideProps(
await helpers.settings.isCloud.prefetch();
await helpers.auth.get.prefetch();
if (user?.role === "user") {
if (user?.rol === "user") {
await helpers.user.byAuthId.prefetch({
authId: user.authId,
});

View File

@@ -26,7 +26,7 @@ export async function getServerSideProps(
) {
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -107,7 +107,7 @@ export async function getServerSideProps(
},
};
}
if (user.role === "member") {
if (user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -36,7 +36,7 @@ export async function getServerSideProps(
},
};
}
if (user.role === "member") {
if (user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -51,7 +51,7 @@ export async function getServerSideProps(
const auth = await helpers.auth.get.fetch();
await helpers.settings.isCloud.prefetch();
if (auth.role === "member") {
if (auth.rol === "user") {
const user = await helpers.user.byAuthId.fetch({
authId: auth.id,
});

View File

@@ -26,7 +26,7 @@ export async function getServerSideProps(
) {
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
if (!user || user.role === "member") {
if (!user || user.rol === "user") {
return {
redirect: {
permanent: true,

View File

@@ -53,7 +53,7 @@ export async function getServerSideProps(
await helpers.project.all.prefetch();
const auth = await helpers.auth.get.fetch();
if (auth.role === "member") {
if (auth.rol === "user") {
const user = await helpers.user.byAuthId.fetch({
authId: auth.id,
});

View File

@@ -53,7 +53,7 @@ export async function getServerSideProps(
await helpers.project.all.prefetch();
const auth = await helpers.auth.get.fetch();
if (auth.role === "member") {
if (auth.rol === "user") {
const user = await helpers.user.byAuthId.fetch({
authId: auth.id,
});

View File

@@ -13,14 +13,10 @@ 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, auth, isAdminPresent } from "@dokploy/server";
import { validateRequest } from "@dokploy/server/lib/auth";
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
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";
@@ -60,18 +56,17 @@ 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: "siumauricio@hotmail.com",
password: "Password123",
email: "",
password: "",
},
resolver: zodResolver(loginSchema),
});
@@ -81,49 +76,25 @@ export default function Home({ IS_CLOUD }: Props) {
}, [form, form.reset, form.formState.isSubmitSuccessful]);
const onSubmit = async (values: Login) => {
setIsLoading(true);
const { data, error } = await authClient.signIn.email({
email: values.email,
await mutateAsync({
email: values.email.toLowerCase(),
password: values.password,
});
if (!error) {
// if (data) {
// setTemp(data);
// } else {
toast.success("Successfully signed in", {
duration: 2000,
})
.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,
});
});
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 (
<>
@@ -140,7 +111,7 @@ export default function Home({ IS_CLOUD }: Props) {
</div>
{isError && (
<AlertBlock type="error" className="my-2">
<span>{error}</span>
<span>{error?.message}</span>
</AlertBlock>
)}
<CardContent className="p-0">
@@ -232,7 +203,8 @@ Home.getLayout = (page: ReactElement) => {
export async function getServerSideProps(context: GetServerSidePropsContext) {
if (IS_CLOUD) {
try {
const { user } = await validateRequest(context.req);
const { user } = await validateRequest(context.req, context.res);
if (user) {
return {
redirect: {
@@ -260,7 +232,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
};
}
const { user } = await validateRequest(context.req);
const { user } = await validateRequest(context.req, context.res);
if (user) {
return {

View File

@@ -17,7 +17,6 @@ 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";
@@ -32,9 +31,6 @@ import { z } from "zod";
const registerSchema = z
.object({
name: z.string().min(1, {
message: "Name is required",
}),
email: z
.string()
.min(1, {
@@ -83,10 +79,9 @@ const Register = ({ isCloud }: Props) => {
const form = useForm<Register>({
defaultValues: {
name: "Mauricio Siu",
email: "user5@yopmail.com",
password: "Password1234",
confirmPassword: "Password1234",
email: "",
password: "",
confirmPassword: "",
},
resolver: zodResolver(registerSchema),
});
@@ -96,33 +91,19 @@ const Register = ({ isCloud }: Props) => {
}, [form, form.reset, form.formState.isSubmitSuccessful]);
const onSubmit = async (values: Register) => {
const { data, error } = await authClient.signUp.email({
email: values.email,
await mutateAsync({
email: values.email.toLowerCase(),
password: values.password,
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);
})
.then(() => {
toast.success("User registered successfuly", {
duration: 2000,
});
if (!isCloud) {
router.push("/");
}
})
.catch((e) => e);
};
return (
<div className="">
@@ -166,19 +147,6 @@ 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"

View File

@@ -58,7 +58,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
},
transformer: superjson,
});
if (user.role === "member") {
if (user.rol === "user") {
const result = await helpers.user.byAuthId.fetch({
authId: user.id,
});

View File

@@ -0,0 +1,9 @@
<svg class="max-w-full" xmlns="http://www.w3.org/2000/svg" width="112" height="98" viewBox="0 0 112 98"
fill="none">
<path
d="M111.1 73.4729V97.9638H48.8706C30.7406 97.9638 14.9105 88.114 6.44112 73.4729C5.2099 71.3444 4.13229 69.1113 3.22835 66.7935C1.45387 62.2516 0.338421 57.3779 0 52.2926V45.6712C0.0734729 44.5379 0.189248 43.4135 0.340647 42.3025C0.650124 40.0227 1.11768 37.7918 1.73218 35.6232C7.54544 15.0641 26.448 0 48.8706 0C71.2932 0 90.1935 15.0641 96.0068 35.6232H69.3985C65.0302 28.9216 57.4692 24.491 48.8706 24.491C40.272 24.491 32.711 28.9216 28.3427 35.6232C27.0113 37.6604 25.9782 39.9069 25.3014 42.3025C24.7002 44.4266 24.3796 46.6664 24.3796 48.9819C24.3796 56.0019 27.3319 62.3295 32.0653 66.7935C36.4515 70.9369 42.3649 73.4729 48.8706 73.4729H111.1Z"
fill="#FD366E" />
<path
d="M111.1 42.3027V66.7937H65.6759C70.4094 62.3297 73.3616 56.0021 73.3616 48.9821C73.3616 46.6666 73.041 44.4268 72.4399 42.3027H111.1Z"
fill="#FD366E" />
</svg>

After

Width:  |  Height:  |  Size: 986 B

View File

@@ -0,0 +1,5 @@
<svg width="184" height="188" viewBox="0 0 184 188" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M108.092 130.021C126.258 128.003 143.385 118.323 152.815 102.167C148.349 142.128 104.653 167.385 68.9858 151.878C65.6992 150.453 62.8702 148.082 60.9288 145.034C52.9134 132.448 50.2786 116.433 54.0644 101.899C64.881 120.567 86.8748 132.01 108.092 130.021Z" fill="#F3B01C"/>
<path d="M53.4012 90.1735C46.0375 107.191 45.7186 127.114 54.7463 143.51C22.9759 119.608 23.3226 68.4578 54.358 44.7949C57.2286 42.6078 60.64 41.3097 64.2178 41.1121C78.9312 40.336 93.8804 46.0225 104.364 56.6193C83.0637 56.831 62.318 70.4756 53.4012 90.1735Z" fill="#8D2676"/>
<path d="M114.637 61.8552C103.89 46.8701 87.0686 36.6684 68.6387 36.358C104.264 20.1876 148.085 46.4045 152.856 85.1654C153.3 88.7635 152.717 92.4322 151.122 95.6775C144.466 109.195 132.124 119.679 117.702 123.559C128.269 103.96 126.965 80.0151 114.637 61.8552Z" fill="#EE342F"/>
</svg>

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -6,17 +6,19 @@ import {
apiRemoveUser,
apiUpdateAdmin,
apiUpdateWebServerMonitoring,
users,
} from "@/server/db/schema";
import {
IS_CLOUD,
createInvitation,
findAdminById,
findUserByAuthId,
findUserById,
getUserByToken,
removeUserById,
removeUserByAuthId,
setupWebMonitoring,
updateAdmin,
updateAdminById,
updateUser,
} from "@dokploy/server";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
@@ -30,7 +32,7 @@ import {
export const adminRouter = createTRPCRouter({
one: adminProcedure.query(async ({ ctx }) => {
const { sshPrivateKey, ...rest } = await findUserById(ctx.user.id);
const { sshPrivateKey, ...rest } = await findAdminById(ctx.user.adminId);
return {
haveSSH: !!sshPrivateKey,
...rest,
@@ -39,21 +41,21 @@ export const adminRouter = createTRPCRouter({
update: adminProcedure
.input(apiUpdateAdmin)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
if (ctx.user.rol === "user") {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to update this admin",
});
}
const { id } = await findUserById(ctx.user.id);
const { authId } = await findAdminById(ctx.user.adminId);
// @ts-ignore
return updateAdmin(id, input);
return updateAdmin(authId, input);
}),
createUserInvitation: adminProcedure
.input(apiCreateUserInvitation)
.mutation(async ({ input, ctx }) => {
try {
await createInvitation(input, ctx.user.id);
await createInvitation(input, ctx.user.adminId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -67,16 +69,15 @@ export const adminRouter = createTRPCRouter({
.input(apiRemoveUser)
.mutation(async ({ input, ctx }) => {
try {
const user = await findUserById(input.id);
const user = await findUserByAuthId(input.authId);
if (user.id !== ctx.user.ownerId) {
if (user.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this user",
});
}
return await removeUserById(input.id);
return await removeUserByAuthId(input.authId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -94,23 +95,20 @@ export const adminRouter = createTRPCRouter({
.input(apiAssignPermissions)
.mutation(async ({ input, ctx }) => {
try {
const user = await findUserById(input.id);
const user = await findUserById(input.userId);
if (user.id !== ctx.user.ownerId) {
if (user.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to assign permissions",
});
}
await updateUser(user.id, {
...input,
});
// await db
// .update(users)
// .set({
// ...input,
// })
// .where(eq(users.userId, input.userId));
await db
.update(users)
.set({
...input,
})
.where(eq(users.userId, input.userId));
} catch (error) {
throw error;
}
@@ -126,15 +124,15 @@ export const adminRouter = createTRPCRouter({
message: "Feature disabled on cloud",
});
}
const user = await findUserById(ctx.user.ownerId);
if (user.id !== ctx.user.ownerId) {
const admin = await findAdminById(ctx.user.adminId);
if (admin.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to setup this server",
});
}
await updateUser(user.id, {
await updateAdminById(admin.adminId, {
metricsConfig: {
server: {
type: "Dokploy",
@@ -158,19 +156,18 @@ export const adminRouter = createTRPCRouter({
},
},
});
const currentServer = await setupWebMonitoring(user.id);
const currentServer = await setupWebMonitoring(admin.adminId);
return currentServer;
} catch (error) {
throw error;
}
}),
getMetricsToken: protectedProcedure.query(async ({ ctx }) => {
const user = await findUserById(ctx.user.ownerId);
const admin = await findAdminById(ctx.user.adminId);
return {
serverIp: user.serverIp,
enabledFeatures: user.enablePaidFeatures,
metricsConfig: user?.metricsConfig,
serverIp: admin.serverIp,
enabledFeatures: admin.enablePaidFeatures,
metricsConfig: admin?.metricsConfig,
};
}),

View File

@@ -60,8 +60,8 @@ export const applicationRouter = createTRPCRouter({
.input(apiCreateApplication)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -72,7 +72,7 @@ export const applicationRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
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 === "member") {
await addNewService(ctx.user.id, newApplication.applicationId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newApplication.applicationId);
}
return newApplication;
} catch (error: unknown) {
@@ -98,11 +98,15 @@ export const applicationRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneApplication)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.applicationId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(
ctx.user.authId,
input.applicationId,
"access",
);
}
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
@@ -115,7 +119,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiReloadApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this application",
@@ -140,12 +144,16 @@ export const applicationRouter = createTRPCRouter({
delete: protectedProcedure
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.applicationId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(
ctx.user.authId,
input.applicationId,
"delete",
);
}
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this application",
@@ -186,7 +194,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const service = await findApplicationById(input.applicationId);
if (service.project.userId !== ctx.user.ownerId) {
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this application",
@@ -206,7 +214,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const service = await findApplicationById(input.applicationId);
if (service.project.userId !== ctx.user.ownerId) {
if (service.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this application",
@@ -227,7 +235,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to redeploy this application",
@@ -260,7 +268,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveEnvironmentVariables)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
@@ -276,7 +284,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveBuildType)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this build type",
@@ -297,7 +305,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveGithubProvider)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this github provider",
@@ -319,7 +327,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveGitlabProvider)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this gitlab provider",
@@ -343,7 +351,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveBitbucketProvider)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this bitbucket provider",
@@ -365,7 +373,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveDockerProvider)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this docker provider",
@@ -386,7 +394,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiSaveGitProvider)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this git provider",
@@ -407,7 +415,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to mark this application as running",
@@ -419,7 +427,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiUpdateApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this application",
@@ -443,7 +451,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to refresh this application",
@@ -458,7 +466,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this application",
@@ -492,7 +500,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to clean this application",
@@ -505,7 +513,7 @@ export const applicationRouter = createTRPCRouter({
.input(apiFindOneApplication)
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to read this application",
@@ -540,7 +548,7 @@ export const applicationRouter = createTRPCRouter({
const app = await findApplicationById(input.applicationId as string);
if (app.project.userId !== ctx.user.ownerId) {
if (app.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this application",
@@ -582,7 +590,7 @@ export const applicationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this application",

View File

@@ -7,7 +7,6 @@ import {
apiVerify2FA,
apiVerifyLogin2FA,
auth,
member,
} from "@/server/db/schema";
import { WEBSITE_URL } from "@/server/utils/stripe";
import {
@@ -17,23 +16,22 @@ 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 { and, eq } from "drizzle-orm";
import { eq } from "drizzle-orm";
import { nanoid } from "nanoid";
import { z } from "zod";
import { db } from "../../db";
@@ -171,17 +169,8 @@ export const authRouter = createTRPCRouter({
}),
get: protectedProcedure.query(async ({ ctx }) => {
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;
const auth = await findAuthById(ctx.user.authId);
return auth;
}),
logout: protectedProcedure.mutation(async ({ ctx }) => {
@@ -254,7 +243,7 @@ export const authRouter = createTRPCRouter({
await lucia.invalidateSession(session.id);
res.setHeader("Set-Cookie", lucia.createBlankSessionCookie().serialize());
if (ctx.user.rol === "owner") {
if (ctx.user.rol === "admin") {
await removeAdminByAuthId(ctx.user.authId);
} else {
await removeUserByAuthId(ctx.user.authId);
@@ -264,18 +253,19 @@ export const authRouter = createTRPCRouter({
}),
generateToken: protectedProcedure.mutation(async ({ ctx, input }) => {
const auth = await findUserById(ctx.user.id);
console.log(auth);
const auth = await findAuthById(ctx.user.authId);
if (auth.token) {
await luciaToken.invalidateSession(auth.token);
}
// const session = await luciaToken.createSession(auth?.id || "", {
// expiresIn: 60 * 60 * 24 * 30,
// });
// await updateUser(auth.id, {
// token: session.id,
// });
const session = await luciaToken.createSession(auth?.id || "", {
expiresIn: 60 * 60 * 24 * 30,
});
await updateAuthById(auth.id, {
token: session.id,
});
return auth;
}),
verifyToken: protectedProcedure.mutation(async () => {
@@ -287,7 +277,7 @@ export const authRouter = createTRPCRouter({
}),
generate2FASecret: protectedProcedure.query(async ({ ctx }) => {
return await generate2FASecret(ctx.user.id);
return await generate2FASecret(ctx.user.authId);
}),
verify2FASetup: protectedProcedure
.input(apiVerify2FA)

View File

@@ -23,7 +23,7 @@ export const bitbucketRouter = createTRPCRouter({
.input(apiCreateBitbucket)
.mutation(async ({ input, ctx }) => {
try {
return await createBitbucket(input, ctx.user.ownerId);
return await createBitbucket(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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.userId === ctx.user.ownerId,
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
);
}
return result;
@@ -73,7 +73,7 @@ export const bitbucketRouter = createTRPCRouter({
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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.userId !== ctx.user.ownerId
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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.userId !== ctx.user.ownerId
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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.userId !== ctx.user.ownerId
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
}),
});

View File

@@ -25,14 +25,14 @@ export const certificateRouter = createTRPCRouter({
message: "Please set a server to create a certificate",
});
}
return await createCertificate(input, ctx.user.ownerId);
return await createCertificate(input, ctx.user.adminId);
}),
one: adminProcedure
.input(apiFindCertificate)
.query(async ({ input, ctx }) => {
const certificates = await findCertificateById(input.certificateId);
if (IS_CLOUD && certificates.userId !== ctx.user.ownerId) {
if (IS_CLOUD && certificates.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && certificates.adminId !== ctx.user.adminId) {
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.userId, ctx.user.ownerId) }),
...(IS_CLOUD && { where: eq(certificates.adminId, ctx.user.adminId) }),
});
}),
});

View File

@@ -44,7 +44,6 @@ import {
findDomainsByComposeId,
findProjectById,
findServerById,
findUserById,
loadServices,
randomizeComposeFile,
randomizeIsolatedDeploymentComposeFile,
@@ -61,8 +60,8 @@ export const composeRouter = createTRPCRouter({
.input(apiCreateCompose)
.mutation(async ({ ctx, input }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -72,7 +71,7 @@ export const composeRouter = createTRPCRouter({
});
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
@@ -80,8 +79,8 @@ export const composeRouter = createTRPCRouter({
}
const newService = await createCompose(input);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newService.composeId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newService.composeId);
}
return newService;
@@ -93,12 +92,12 @@ export const composeRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindCompose)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.composeId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.composeId, "access");
}
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -111,7 +110,7 @@ export const composeRouter = createTRPCRouter({
.input(apiUpdateCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this compose",
@@ -122,12 +121,12 @@ export const composeRouter = createTRPCRouter({
delete: protectedProcedure
.input(apiDeleteCompose)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.composeId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.composeId, "delete");
}
const composeResult = await findComposeById(input.composeId);
if (composeResult.project.userId !== ctx.user.ownerId) {
if (composeResult.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this compose",
@@ -158,7 +157,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to clean this compose",
@@ -171,7 +170,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFetchServices)
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to load this compose",
@@ -185,7 +184,7 @@ export const composeRouter = createTRPCRouter({
try {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to fetch this compose",
@@ -210,7 +209,7 @@ export const composeRouter = createTRPCRouter({
.input(apiRandomizeCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to randomize this compose",
@@ -222,7 +221,7 @@ export const composeRouter = createTRPCRouter({
.input(apiRandomizeCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to randomize this compose",
@@ -237,7 +236,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFindCompose)
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to get this compose",
@@ -255,7 +254,7 @@ export const composeRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this compose",
@@ -288,7 +287,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to redeploy this compose",
@@ -320,7 +319,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this compose",
@@ -334,7 +333,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this compose",
@@ -349,7 +348,7 @@ export const composeRouter = createTRPCRouter({
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to get this compose",
@@ -362,7 +361,7 @@ export const composeRouter = createTRPCRouter({
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to refresh this compose",
@@ -376,8 +375,8 @@ export const composeRouter = createTRPCRouter({
deployTemplate: protectedProcedure
.input(apiCreateComposeByTemplate)
.mutation(async ({ ctx, input }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -391,7 +390,7 @@ export const composeRouter = createTRPCRouter({
const generate = await loadTemplateModule(input.id as TemplatesKeys);
const admin = await findUserById(ctx.user.ownerId);
const admin = await findAdminById(ctx.user.adminId);
let serverIp = admin.serverIp || "127.0.0.1";
const project = await findProjectById(input.projectId);
@@ -419,8 +418,8 @@ export const composeRouter = createTRPCRouter({
isolatedDeployment: true,
});
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, compose.composeId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, compose.composeId);
}
if (mounts && mounts?.length > 0) {

View File

@@ -19,7 +19,7 @@ export const deploymentRouter = createTRPCRouter({
.input(apiFindAllByApplication)
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this server",

View File

@@ -28,7 +28,7 @@ export const destinationRouter = createTRPCRouter({
.input(apiCreateDestination)
.mutation(async ({ input, ctx }) => {
try {
return await createDestintation(input, ctx.user.ownerId);
return await createDestintation(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (destination.adminId !== ctx.user.adminId) {
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.userId, ctx.user.ownerId),
where: eq(destinations.adminId, ctx.user.adminId),
});
}),
remove: adminProcedure
@@ -103,7 +103,7 @@ export const destinationRouter = createTRPCRouter({
try {
const destination = await findDestinationById(input.destinationId);
if (destination.userId !== ctx.user.ownerId) {
if (destination.adminId !== ctx.user.adminId) {
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.ownerId,
ctx.user.adminId,
);
} 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.userId !== ctx.user.ownerId) {
if (destination.adminId !== ctx.user.adminId) {
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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} catch (error) {
throw error;

View File

@@ -30,7 +30,7 @@ export const domainRouter = createTRPCRouter({
try {
if (input.domainType === "compose" && input.composeId) {
const compose = await findComposeById(input.composeId);
if (compose.project.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
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.ownerId,
ctx.user.adminId,
input.serverId,
);
}),
@@ -95,7 +95,7 @@ export const domainRouter = createTRPCRouter({
if (currentDomain.applicationId) {
const newApp = await findApplicationById(currentDomain.applicationId);
if (newApp.project.userId !== ctx.user.ownerId) {
if (newApp.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (newCompose.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId
newPreviewDeployment.application.project.adminId !== ctx.user.adminId
) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",

View File

@@ -18,7 +18,7 @@ export const gitProviderRouter = createTRPCRouter({
github: true,
},
orderBy: desc(gitProvider.createdAt),
...(IS_CLOUD && { where: eq(gitProvider.userId, ctx.user.ownerId) }),
...(IS_CLOUD && { where: eq(gitProvider.adminId, ctx.user.adminId) }),
//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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && gitProvider.adminId !== ctx.user.adminId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",

View File

@@ -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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
//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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
//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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
//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.userId === ctx.user.ownerId,
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
);
}
@@ -90,7 +90,7 @@ export const githubRouter = createTRPCRouter({
const githubProvider = await findGithubById(input.githubId);
if (
IS_CLOUD &&
githubProvider.gitProvider.userId !== ctx.user.ownerId
githubProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
//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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
}),
});

View File

@@ -26,7 +26,7 @@ export const gitlabRouter = createTRPCRouter({
.input(apiCreateGitlab)
.mutation(async ({ input, ctx }) => {
try {
return await createGitlab(input, ctx.user.ownerId);
return await createGitlab(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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.userId === ctx.user.ownerId,
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
);
}
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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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.userId !== ctx.user.ownerId
gitlabProvider.gitProvider.adminId !== ctx.user.adminId
) {
//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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
//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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
await updateGitlab(input.gitlabId, {

View File

@@ -37,8 +37,8 @@ export const mariadbRouter = createTRPCRouter({
.input(apiCreateMariaDB)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -49,15 +49,15 @@ export const mariadbRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newMariadb = await createMariadb(input);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newMariadb.mariadbId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newMariadb.mariadbId);
}
await createMount({
@@ -79,11 +79,11 @@ export const mariadbRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneMariaDB)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mariadbId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mariadbId, "access");
}
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.userId !== ctx.user.ownerId) {
if (mariadb.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (service.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mariadb.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mariadb.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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 === "member") {
await checkServiceAccess(ctx.user.id, input.mariadbId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mariadbId, "delete");
}
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mariadb.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mariadb.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mariadb.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this Mariadb",

View File

@@ -36,8 +36,8 @@ export const mongoRouter = createTRPCRouter({
.input(apiCreateMongo)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -48,15 +48,15 @@ export const mongoRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newMongo = await createMongo(input);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newMongo.mongoId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newMongo.mongoId);
}
await createMount({
@@ -82,12 +82,12 @@ export const mongoRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneMongo)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mongoId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mongoId, "access");
}
const mongo = await findMongoById(input.mongoId);
if (mongo.project.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (service.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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 === "member") {
await checkServiceAccess(ctx.user.id, input.mongoId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mongoId, "delete");
}
const mongo = await findMongoById(input.mongoId);
if (mongo.project.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this mongo",

View File

@@ -38,8 +38,8 @@ export const mysqlRouter = createTRPCRouter({
.input(apiCreateMySql)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, 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.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
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 === "member") {
await addNewService(ctx.user.id, newMysql.mysqlId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newMysql.mysqlId);
}
await createMount({
@@ -85,11 +85,11 @@ export const mysqlRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneMySql)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mysqlId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mysqlId, "access");
}
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.userId !== ctx.user.ownerId) {
if (mysql.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (service.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mysql.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mysql.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mysql.project.adminId !== ctx.user.adminId) {
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 === "member") {
await checkServiceAccess(ctx.user.id, input.mysqlId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mysqlId, "delete");
}
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mysql.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mysql.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this MySQL",

View File

@@ -6,6 +6,7 @@ import {
} from "@/server/api/trpc";
import { db } from "@/server/db";
import {
admins,
apiCreateDiscord,
apiCreateEmail,
apiCreateGotify,
@@ -24,7 +25,6 @@ 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.ownerId);
return await createSlackNotification(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// 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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} 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.ownerId);
return await createTelegramNotification(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// 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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} 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.ownerId);
return await createDiscordNotification(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// 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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} 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.ownerId);
return await createEmailNotification(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// 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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
// 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.userId, ctx.user.ownerId) }),
...(IS_CLOUD && { where: eq(notifications.adminId, ctx.user.adminId) }),
// TODO: Remove this line when the cloud version is ready
});
}),
@@ -332,24 +332,24 @@ export const notificationRouter = createTRPCRouter({
)
.mutation(async ({ input }) => {
try {
let userId = "";
let adminId = "";
let ServerName = "";
if (input.ServerType === "Dokploy") {
const result = await db
.select()
.from(users_temp)
.from(admins)
.where(
sql`${users_temp.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
sql`${admins.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
);
if (!result?.[0]?.id) {
if (!result?.[0]?.adminId) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Token not found",
});
}
userId = result?.[0]?.id;
adminId = result?.[0]?.adminId;
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]?.userId) {
if (!result?.[0]?.adminId) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Token not found",
});
}
userId = result?.[0]?.userId;
adminId = result?.[0]?.adminId;
ServerName = "Remote";
}
await sendServerThresholdNotifications(userId, {
await sendServerThresholdNotifications(adminId, {
...input,
ServerName,
});
@@ -386,7 +386,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiCreateGotify)
.mutation(async ({ input, ctx }) => {
try {
return await createGotifyNotification(input, ctx.user.ownerId);
return await createGotifyNotification(input, ctx.user.adminId);
} 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.userId !== ctx.user.ownerId) {
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
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,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} catch (error) {
throw error;

View File

@@ -44,8 +44,8 @@ export const postgresRouter = createTRPCRouter({
.input(apiCreatePostgres)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -56,15 +56,15 @@ export const postgresRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newPostgres = await createPostgres(input);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newPostgres.postgresId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newPostgres.postgresId);
}
await createMount({
@@ -90,12 +90,12 @@ export const postgresRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOnePostgres)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.postgresId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.postgresId, "access");
}
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (service.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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 === "member") {
await checkServiceAccess(ctx.user.id, input.postgresId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.postgresId, "delete");
}
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (postgres.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this Postgres",

View File

@@ -14,7 +14,7 @@ export const previewDeploymentRouter = createTRPCRouter({
.input(apiFindAllByApplication)
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (previewDeployment.application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (previewDeployment.application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this preview deployment",

View File

@@ -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 === "member") {
await checkProjectAccess(ctx.user.id, "create");
if (ctx.user.rol === "user") {
await checkProjectAccess(ctx.user.authId, "create");
}
const admin = await findUserById(ctx.user.ownerId);
const admin = await findAdminById(ctx.user.adminId);
if (admin.serversQuantity === 0 && IS_CLOUD) {
throw new TRPCError({
@@ -49,9 +49,9 @@ export const projectRouter = createTRPCRouter({
});
}
const project = await createProject(input, ctx.user.ownerId);
if (ctx.user.rol === "member") {
await addNewProject(ctx.user.id, project.projectId);
const project = await createProject(input, ctx.user.adminId);
if (ctx.user.rol === "user") {
await addNewProject(ctx.user.authId, project.projectId);
}
return project;
@@ -67,15 +67,15 @@ export const projectRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneProject)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
const { accessedServices } = await findUserByAuthId(ctx.user.id);
if (ctx.user.rol === "user") {
const { accessedServices } = await findUserByAuthId(ctx.user.authId);
await checkProjectAccess(ctx.user.id, "access", input.projectId);
await checkProjectAccess(ctx.user.authId, "access", input.projectId);
const project = await db.query.projects.findFirst({
where: and(
eq(projects.projectId, input.projectId),
eq(projects.userId, ctx.user.ownerId),
eq(projects.adminId, ctx.user.adminId),
),
with: {
compose: {
@@ -115,7 +115,7 @@ export const projectRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
@@ -124,10 +124,9 @@ export const projectRouter = createTRPCRouter({
return project;
}),
all: protectedProcedure.query(async ({ ctx }) => {
// console.log(ctx.user);
if (ctx.user.rol === "member") {
const { accessedProjects, accessedServices } = await findUserById(
ctx.user.id,
if (ctx.user.rol === "user") {
const { accessedProjects, accessedServices } = await findUserByAuthId(
ctx.user.authId,
);
if (accessedProjects.length === 0) {
@@ -140,7 +139,7 @@ export const projectRouter = createTRPCRouter({
accessedProjects.map((projectId) => sql`${projectId}`),
sql`, `,
)})`,
eq(projects.userId, ctx.user.id),
eq(projects.adminId, ctx.user.adminId),
),
with: {
applications: {
@@ -194,7 +193,7 @@ export const projectRouter = createTRPCRouter({
},
},
},
where: eq(projects.userId, ctx.user.id),
where: eq(projects.adminId, ctx.user.adminId),
orderBy: desc(projects.createdAt),
});
}),
@@ -203,11 +202,11 @@ export const projectRouter = createTRPCRouter({
.input(apiRemoveProject)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkProjectAccess(ctx.user.id, "delete");
if (ctx.user.rol === "user") {
await checkProjectAccess(ctx.user.authId, "delete");
}
const currentProject = await findProjectById(input.projectId);
if (currentProject.userId !== ctx.user.ownerId) {
if (currentProject.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this project",
@@ -225,7 +224,7 @@ export const projectRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const currentProject = await findProjectById(input.projectId);
if (currentProject.userId !== ctx.user.ownerId) {
if (currentProject.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this project",

View File

@@ -18,7 +18,7 @@ export const redirectsRouter = createTRPCRouter({
.input(apiCreateRedirect)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",

View File

@@ -36,8 +36,8 @@ export const redisRouter = createTRPCRouter({
.input(apiCreateRedis)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -48,15 +48,15 @@ export const redisRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.userId !== ctx.user.ownerId) {
if (project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newRedis = await createRedis(input);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newRedis.redisId);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newRedis.redisId);
}
await createMount({
@@ -75,12 +75,12 @@ export const redisRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneRedis)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.redisId, "access");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.redisId, "access");
}
const redis = await findRedisById(input.redisId);
if (redis.project.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (mongo.project.adminId !== ctx.user.adminId) {
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 === "member") {
await checkServiceAccess(ctx.user.id, input.redisId, "delete");
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.redisId, "delete");
}
const redis = await findRedisById(input.redisId);
if (redis.project.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (redis.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",

View File

@@ -10,7 +10,7 @@ import {
createRegistry,
execAsync,
execAsyncRemote,
findAllRegistryByUserId,
findAllRegistryByAdminId,
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.ownerId);
return await createRegistry(input, ctx.user.adminId);
}),
remove: adminProcedure
.input(apiRemoveRegistry)
.mutation(async ({ ctx, input }) => {
const registry = await findRegistryById(input.registryId);
if (registry.userId !== ctx.user.ownerId) {
if (registry.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (registry.adminId !== ctx.user.adminId) {
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 findAllRegistryByUserId(ctx.user.ownerId);
return await findAllRegistryByAdminId(ctx.user.adminId);
}),
one: adminProcedure
.input(apiFindOneRegistry)
.query(async ({ input, ctx }) => {
const registry = await findRegistryById(input.registryId);
if (registry.userId !== ctx.user.ownerId) {
if (registry.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this registry",

View File

@@ -18,7 +18,7 @@ export const securityRouter = createTRPCRouter({
.input(apiCreateSecurity)
.mutation(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (application.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",

View File

@@ -21,9 +21,9 @@ import {
createServer,
defaultCommand,
deleteServer,
findAdminById,
findServerById,
findServersByUserId,
findUserById,
findServersByAdminId,
getPublicIpWithFallback,
haveActiveServices,
removeDeploymentsByServerId,
@@ -42,15 +42,15 @@ export const serverRouter = createTRPCRouter({
.input(apiCreateServer)
.mutation(async ({ ctx, input }) => {
try {
const user = await findUserById(ctx.user.ownerId);
const servers = await findServersByUserId(user.id);
if (IS_CLOUD && servers.length >= user.serversQuantity) {
const admin = await findAdminById(ctx.user.adminId);
const servers = await findServersByAdminId(admin.adminId);
if (IS_CLOUD && servers.length >= admin.serversQuantity) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "You cannot create more servers",
});
}
const project = await createServer(input, ctx.user.ownerId);
const project = await createServer(input, ctx.user.adminId);
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
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.userId, ctx.user.ownerId))
.where(eq(server.adminId, ctx.user.adminId))
.orderBy(desc(server.createdAt))
.groupBy(server.serverId);
@@ -105,10 +105,10 @@ export const serverRouter = createTRPCRouter({
where: IS_CLOUD
? and(
isNotNull(server.sshKeyId),
eq(server.userId, ctx.user.ownerId),
eq(server.adminId, ctx.user.adminId),
eq(server.serverStatus, "active"),
)
: and(isNotNull(server.sshKeyId), eq(server.userId, ctx.user.ownerId)),
: and(isNotNull(server.sshKeyId), eq(server.adminId, ctx.user.adminId)),
});
return result;
}),
@@ -117,7 +117,7 @@ export const serverRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const server = await findServerById(input.serverId);
if (server.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
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.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this server",
@@ -315,9 +315,12 @@ export const serverRouter = createTRPCRouter({
await deleteServer(input.serverId);
if (IS_CLOUD) {
const admin = await findUserById(ctx.user.ownerId);
const admin = await findAdminById(ctx.user.adminId);
await updateServersBasedOnQuantity(admin.id, admin.serversQuantity);
await updateServersBasedOnQuantity(
admin.adminId,
admin.serversQuantity,
);
}
return currentServer;
@@ -330,7 +333,7 @@ export const serverRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const server = await findServerById(input.serverId);
if (server.userId !== ctx.user.ownerId) {
if (server.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this server",

View File

@@ -47,6 +47,7 @@ import {
startServiceRemote,
stopService,
stopServiceRemote,
updateAdmin,
updateLetsEncryptEmail,
updateServerById,
updateServerTraefik,
@@ -382,7 +383,7 @@ export const settingsRouter = createTRPCRouter({
.input(apiServerSchema)
.query(async ({ ctx, input }) => {
try {
if (ctx.user.rol === "member") {
if (ctx.user.rol === "user") {
const canAccess = await canAccessToTraefikFiles(ctx.user.authId);
if (!canAccess) {
@@ -400,7 +401,7 @@ export const settingsRouter = createTRPCRouter({
updateTraefikFile: protectedProcedure
.input(apiModifyTraefikConfig)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
if (ctx.user.rol === "user") {
const canAccess = await canAccessToTraefikFiles(ctx.user.authId);
if (!canAccess) {
@@ -418,7 +419,7 @@ export const settingsRouter = createTRPCRouter({
readTraefikFile: protectedProcedure
.input(apiReadTraefikConfig)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "member") {
if (ctx.user.rol === "user") {
const canAccess = await canAccessToTraefikFiles(ctx.user.authId);
if (!canAccess) {
@@ -654,7 +655,7 @@ export const settingsRouter = createTRPCRouter({
return true;
}),
isCloud: publicProcedure.query(async () => {
isCloud: protectedProcedure.query(async () => {
return IS_CLOUD;
}),
health: publicProcedure.query(async () => {

View File

@@ -24,10 +24,9 @@ export const sshRouter = createTRPCRouter({
.input(apiCreateSshKey)
.mutation(async ({ input, ctx }) => {
try {
console.log(ctx.user.ownerId);
await createSshKey({
...input,
userId: ctx.user.ownerId,
adminId: ctx.user.adminId,
});
} catch (error) {
throw new TRPCError({
@@ -42,7 +41,7 @@ export const sshRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const sshKey = await findSSHKeyById(input.sshKeyId);
if (IS_CLOUD && sshKey.userId !== ctx.user.ownerId) {
if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -60,7 +59,7 @@ export const sshRouter = createTRPCRouter({
.query(async ({ input, ctx }) => {
const sshKey = await findSSHKeyById(input.sshKeyId);
if (IS_CLOUD && sshKey.userId !== ctx.user.ownerId) {
if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -71,7 +70,7 @@ export const sshRouter = createTRPCRouter({
}),
all: protectedProcedure.query(async ({ ctx }) => {
return await db.query.sshKeys.findMany({
...(IS_CLOUD && { where: eq(sshKeys.userId, ctx.user.ownerId) }),
...(IS_CLOUD && { where: eq(sshKeys.adminId, ctx.user.adminId) }),
orderBy: desc(sshKeys.createdAt),
});
// TODO: Remove this line when the cloud version is ready
@@ -86,7 +85,7 @@ export const sshRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const sshKey = await findSSHKeyById(input.sshKeyId);
if (IS_CLOUD && sshKey.userId !== ctx.user.ownerId) {
if (IS_CLOUD && sshKey.adminId !== ctx.user.adminId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",

View File

@@ -1,9 +1,9 @@
import { WEBSITE_URL, getStripeItems } from "@/server/utils/stripe";
import {
IS_CLOUD,
findServersByUserId,
findUserById,
updateUser,
findAdminById,
findServersByAdminId,
updateAdmin,
} 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 user = await findUserById(ctx.user.ownerId);
const stripeCustomerId = user.stripeCustomerId;
const admin = await findAdminById(ctx.user.adminId);
const stripeCustomerId = admin.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 user = await findUserById(ctx.user.ownerId);
const admin = await findAdminById(ctx.user.adminId);
let stripeCustomerId = user.stripeCustomerId;
let stripeCustomerId = admin.stripeCustomerId;
if (stripeCustomerId) {
const customer = await stripe.customers.retrieve(stripeCustomerId);
if (customer.deleted) {
await updateUser(user.id, {
await updateAdmin(admin.authId, {
stripeCustomerId: null,
});
stripeCustomerId = null;
@@ -78,7 +78,7 @@ export const stripeRouter = createTRPCRouter({
customer: stripeCustomerId,
}),
metadata: {
ownerId: user.id,
adminId: admin.adminId,
},
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 user = await findUserById(ctx.user.ownerId);
const admin = await findAdminById(ctx.user.adminId);
if (!user.stripeCustomerId) {
if (!admin.stripeCustomerId) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Stripe Customer ID not found",
});
}
const stripeCustomerId = user.stripeCustomerId;
const stripeCustomerId = admin.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 user = await findUserById(ctx.user.ownerId);
const servers = await findServersByUserId(user.id);
const admin = await findAdminById(ctx.user.adminId);
const servers = await findServersByAdminId(admin.adminId);
if (!IS_CLOUD) {
return true;
}
return servers.length < user.serversQuantity;
return servers.length < admin.serversQuantity;
}),
});

View File

@@ -9,8 +9,7 @@
// import { getServerAuthSession } from "@/server/auth";
import { db } from "@/server/db";
import { validateBearerToken } from "@dokploy/server";
import { validateRequest } from "@dokploy/server/lib/auth";
import { validateBearerToken, validateRequest } from "@dokploy/server";
import type { OpenApiMeta } from "@dokploy/trpc-openapi";
import { TRPCError, initTRPC } from "@trpc/server";
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
@@ -19,7 +18,7 @@ import {
experimental_isMultipartFormDataRequest,
experimental_parseMultipartFormData,
} from "@trpc/server/adapters/node-http/content-type/form-data";
import type { Session, User } from "better-auth";
import type { Session, User } from "lucia";
import superjson from "superjson";
import { ZodError } from "zod";
/**
@@ -31,8 +30,8 @@ import { ZodError } from "zod";
*/
interface CreateContextOptions {
user: (User & { rol: "member" | "admin" | "owner"; ownerId: string }) | null;
session: (Session & { activeOrganizationId?: string }) | null;
user: (User & { authId: string; adminId: string }) | null;
session: Session | null;
req: CreateNextContextOptions["req"];
res: CreateNextContextOptions["res"];
}
@@ -66,36 +65,30 @@ const createInnerTRPCContext = (opts: CreateContextOptions) => {
export const createTRPCContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
// Get from the request
const { session, user } = await validateRequest(req);
let { session, user } = await validateBearerToken(req);
// if (!session) {
// const cookieResult = await validateRequest(req);
// session = cookieResult.session;
// user = cookieResult.user;
// }
console.log("session", session);
console.log("user", user);
if (!session) {
const cookieResult = await validateRequest(req, res);
session = cookieResult.session;
user = cookieResult.user;
}
return createInnerTRPCContext({
req,
res,
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,
session: session,
...((user && {
user: {
authId: user.id,
email: user.email,
rol: user.rol,
id: user.id,
secret: user.secret,
adminId: user.adminId,
},
}) || {
user: null,
}),
});
};
@@ -188,7 +181,7 @@ export const uploadProcedure = async (opts: any) => {
};
export const cliProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session || !ctx.user || ctx.user.rol !== "owner") {
if (!ctx.session || !ctx.user || ctx.user.rol !== "admin") {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
@@ -202,7 +195,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 !== "owner") {
if (!ctx.session || !ctx.user || ctx.user.rol !== "admin") {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({

View File

@@ -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();

View File

@@ -0,0 +1,887 @@
version: "3.8"
x-logging: &x-logging
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
services:
appwrite:
image: appwrite/appwrite:1.6.0
container_name: appwrite
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
labels:
- traefik.enable=true
- traefik.constraint-label-stack=appwrite
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
- appwrite-functions:/storage/functions:rw
depends_on:
- mariadb
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_LOCALE
- _APP_CONSOLE_WHITELIST_ROOT
- _APP_CONSOLE_WHITELIST_EMAILS
- _APP_CONSOLE_SESSION_ALERTS
- _APP_CONSOLE_WHITELIST_IPS
- _APP_CONSOLE_HOSTNAMES
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_EMAIL_SECURITY
- _APP_SYSTEM_RESPONSE_FORMAT
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
- _APP_SMTP_USERNAME
- _APP_SMTP_PASSWORD
- _APP_USAGE_STATS
- _APP_STORAGE_LIMIT
- _APP_STORAGE_PREVIEW_LIMIT
- _APP_STORAGE_ANTIVIRUS
- _APP_STORAGE_ANTIVIRUS_HOST
- _APP_STORAGE_ANTIVIRUS_PORT
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_FUNCTIONS_SIZE_LIMIT
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_MEMORY
- _APP_FUNCTIONS_RUNTIMES
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_LOGGING_CONFIG
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_DELAY
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_SMS_PROVIDER
- _APP_SMS_FROM
- _APP_GRAPHQL_MAX_BATCH_SIZE
- _APP_GRAPHQL_MAX_COMPLEXITY
- _APP_GRAPHQL_MAX_DEPTH
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_VCS_GITHUB_WEBHOOK_SECRET
- _APP_VCS_GITHUB_CLIENT_SECRET
- _APP_VCS_GITHUB_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
- _APP_ASSISTANT_OPENAI_API_KEY
appwrite-console:
image: appwrite/console:5.0.12
container_name: appwrite-console
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
labels:
- "traefik.enable=true"
- "traefik.constraint-label-stack=appwrite"
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_LOCALE
- _APP_CONSOLE_WHITELIST_ROOT
- _APP_CONSOLE_WHITELIST_EMAILS
- _APP_CONSOLE_SESSION_ALERTS
- _APP_CONSOLE_WHITELIST_IPS
- _APP_CONSOLE_HOSTNAMES
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_EMAIL_SECURITY
- _APP_SYSTEM_RESPONSE_FORMAT
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
- _APP_SMTP_USERNAME
- _APP_SMTP_PASSWORD
- _APP_USAGE_STATS
- _APP_STORAGE_LIMIT
- _APP_STORAGE_PREVIEW_LIMIT
- _APP_STORAGE_ANTIVIRUS
- _APP_STORAGE_ANTIVIRUS_HOST
- _APP_STORAGE_ANTIVIRUS_PORT
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
appwrite-realtime:
image: appwrite/appwrite:1.6.0
entrypoint: realtime
container_name: appwrite-realtime
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- mariadb
- redis
labels:
- "traefik.enable=true"
- "traefik.constraint-label-stack=appwrite"
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
appwrite-worker-audits:
image: appwrite/appwrite:1.6.0
entrypoint: worker-audits
<<: *x-logging
container_name: appwrite-worker-audits
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_CONFIG
appwrite-worker-webhooks:
image: appwrite/appwrite:1.6.0
entrypoint: worker-webhooks
<<: *x-logging
container_name: appwrite-worker-webhooks
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_EMAIL_SECURITY
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_LOGGING_CONFIG
appwrite-worker-deletes:
image: appwrite/appwrite:1.6.0
entrypoint: worker-deletes
<<: *x-logging
container_name: appwrite-worker-deletes
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
volumes:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-functions:/storage/functions:rw
- appwrite-builds:/storage/builds:rw
- appwrite-certificates:/storage/certificates:rw
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_LOGGING_CONFIG
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_EXECUTION
appwrite-worker-databases:
image: appwrite/appwrite:1.6.0
entrypoint: worker-databases
<<: *x-logging
container_name: appwrite-worker-databases
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_CONFIG
appwrite-worker-builds:
image: appwrite/appwrite:1.6.0
entrypoint: worker-builds
<<: *x-logging
container_name: appwrite-worker-builds
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
volumes:
- appwrite-functions:/storage/functions:rw
- appwrite-builds:/storage/builds:rw
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_CONFIG
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_MEMORY
- _APP_FUNCTIONS_SIZE_LIMIT
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
- _APP_DOMAIN
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
appwrite-worker-certificates:
image: appwrite/appwrite:1.6.0
entrypoint: worker-certificates
<<: *x-logging
container_name: appwrite-worker-certificates
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
volumes:
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_CONFIG
appwrite-worker-functions:
image: appwrite/appwrite:1.6.0
entrypoint: worker-functions
<<: *x-logging
container_name: appwrite-worker-functions
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
- openruntimes-executor
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_OPTIONS_FORCE_HTTPS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_MEMORY
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_USAGE_STATS
- _APP_DOCKER_HUB_USERNAME
- _APP_DOCKER_HUB_PASSWORD
- _APP_LOGGING_CONFIG
appwrite-worker-mails:
image: appwrite/appwrite:1.6.0
entrypoint: worker-mails
<<: *x-logging
container_name: appwrite-worker-mails
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
- _APP_SMTP_USERNAME
- _APP_SMTP_PASSWORD
- _APP_LOGGING_CONFIG
appwrite-worker-messaging:
image: appwrite/appwrite:1.6.0
entrypoint: worker-messaging
container_name: appwrite-worker-messaging
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
volumes:
- appwrite-uploads:/storage/uploads:rw
depends_on:
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_CONFIG
- _APP_SMS_FROM
- _APP_SMS_PROVIDER
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
appwrite-worker-migrations:
image: appwrite/appwrite:1.6.0
entrypoint: worker-migrations
<<: *x-logging
container_name: appwrite-worker-migrations
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_EMAIL_SECURITY
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_CONFIG
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
appwrite-task-maintenance:
image: appwrite/appwrite:1.6.0
entrypoint: maintenance
<<: *x-logging
container_name: appwrite-task-maintenance
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
appwrite-worker-usage:
image: appwrite/appwrite:1.6.0
entrypoint: worker-usage
container_name: appwrite-worker-usage
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-worker-usage-dump:
image: appwrite/appwrite:1.6.0
entrypoint: worker-usage-dump
container_name: appwrite-worker-usage-dump
<<: *x-logging
networks:
- dokploy-network
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-task-scheduler-functions:
image: appwrite/appwrite:1.6.0
entrypoint: schedule-functions
container_name: appwrite-task-scheduler-functions
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- mariadb
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-task-scheduler-executions:
image: appwrite/appwrite:1.6.0
entrypoint: schedule-executions
container_name: appwrite-task-scheduler-executions
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- mariadb
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-task-scheduler-messages:
image: appwrite/appwrite:1.6.0
entrypoint: schedule-messages
container_name: appwrite-task-scheduler-messages
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
depends_on:
- mariadb
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-assistant:
image: appwrite/assistant:0.4.0
container_name: appwrite-assistant
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
environment:
- _APP_ASSISTANT_OPENAI_API_KEY
openruntimes-executor:
container_name: openruntimes-executor
hostname: exc1
<<: *x-logging
restart: unless-stopped
stop_signal: SIGINT
image: openruntimes/executor:0.6.11
networks:
- dokploy-network
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-builds:/storage/builds:rw
- appwrite-functions:/storage/functions:rw
- /tmp:/tmp:rw
environment:
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
- OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
- OPR_EXECUTOR_ENV=$_APP_ENV
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
- OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
- OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
- OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=$_APP_STORAGE_DO_SPACES_BUCKET
- OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=$_APP_STORAGE_BACKBLAZE_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=$_APP_STORAGE_BACKBLAZE_SECRET
- OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=$_APP_STORAGE_BACKBLAZE_REGION
- OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=$_APP_STORAGE_BACKBLAZE_BUCKET
- OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=$_APP_STORAGE_LINODE_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_LINODE_SECRET=$_APP_STORAGE_LINODE_SECRET
- OPR_EXECUTOR_STORAGE_LINODE_REGION=$_APP_STORAGE_LINODE_REGION
- OPR_EXECUTOR_STORAGE_LINODE_BUCKET=$_APP_STORAGE_LINODE_BUCKET
- OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=$_APP_STORAGE_WASABI_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_WASABI_SECRET=$_APP_STORAGE_WASABI_SECRET
- OPR_EXECUTOR_STORAGE_WASABI_REGION=$_APP_STORAGE_WASABI_REGION
- OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET
mariadb:
image: mariadb:10.11
container_name: appwrite-mariadb
<<: *x-logging
restart: unless-stopped
networks:
- dokploy-network
volumes:
- appwrite-mariadb:/var/lib/mysql:rw
environment:
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
- MYSQL_USER=${_APP_DB_USER}
- MYSQL_PASSWORD=${_APP_DB_PASS}
- MARIADB_AUTO_UPGRADE=1
command: "mysqld --innodb-flush-method=fsync"
redis:
image: redis:7.2.4-alpine
container_name: appwrite-redis
<<: *x-logging
restart: unless-stopped
command: >
redis-server
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--maxmemory-samples 5
networks:
- dokploy-network
volumes:
- appwrite-redis:/data:rw
# Uncomment and configure if ClamAV is needed
# clamav:
# image: appwrite/clamav:1.2.0
# container_name: appwrite-clamav
# restart: unless-stopped
# networks:
# - dokploy-network
# volumes:
# - appwrite-uploads:/storage/uploads
volumes:
appwrite-mariadb:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
appwrite-certificates:
appwrite-functions:
appwrite-builds:
appwrite-config:
networks:
dokploy-network:
external: true

View File

@@ -0,0 +1,153 @@
import {
type DomainSchema,
type Schema,
type Template,
generateRandomDomain,
} from "../utils";
export function generate(schema: Schema): Template {
const mainDomain = generateRandomDomain(schema);
const domains: DomainSchema[] = [
{ host: mainDomain, port: 80, serviceName: "appwrite", path: "/" },
{
host: mainDomain,
port: 80,
serviceName: "appwrite-console",
path: "/console",
},
{
host: mainDomain,
port: 80,
serviceName: "appwrite-realtime",
path: "/v1/realtime",
},
];
const envs = [
"_APP_ENV=production",
"_APP_LOCALE=en",
"_APP_OPTIONS_ABUSE=enabled",
"_APP_OPTIONS_FORCE_HTTPS=disabled",
"_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled",
"_APP_OPTIONS_ROUTER_PROTECTION=disabled",
"_APP_OPENSSL_KEY_V1=your-secret-key",
`_APP_DOMAIN=${mainDomain}`,
`_APP_DOMAIN_FUNCTIONS=${mainDomain}`,
`_APP_DOMAIN_TARGET=${mainDomain}`,
"_APP_CONSOLE_WHITELIST_ROOT=enabled",
"_APP_CONSOLE_WHITELIST_EMAILS=",
"_APP_CONSOLE_WHITELIST_IPS=",
"_APP_CONSOLE_HOSTNAMES=",
"_APP_SYSTEM_EMAIL_NAME=Appwrite",
"_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io",
"_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io",
"_APP_SYSTEM_RESPONSE_FORMAT=",
"_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=certs@appwrite.io",
"_APP_EMAIL_SECURITY=",
"_APP_EMAIL_CERTIFICATES=",
"_APP_USAGE_STATS=enabled",
"_APP_LOGGING_PROVIDER=",
"_APP_LOGGING_CONFIG=",
"_APP_USAGE_AGGREGATION_INTERVAL=30",
"_APP_USAGE_TIMESERIES_INTERVAL=30",
"_APP_USAGE_DATABASE_INTERVAL=900",
"_APP_WORKER_PER_CORE=6",
"_APP_CONSOLE_SESSION_ALERTS=disabled",
"_APP_REDIS_HOST=redis",
"_APP_REDIS_PORT=6379",
"_APP_REDIS_USER=",
"_APP_REDIS_PASS=",
"_APP_DB_HOST=mariadb",
"_APP_DB_PORT=3306",
"_APP_DB_SCHEMA=appwrite",
"_APP_DB_USER=user",
"_APP_DB_PASS=password",
"_APP_DB_ROOT_PASS=rootsecretpassword",
"_APP_INFLUXDB_HOST=influxdb",
"_APP_INFLUXDB_PORT=8086",
"_APP_STATSD_HOST=telegraf",
"_APP_STATSD_PORT=8125",
"_APP_SMTP_HOST=",
"_APP_SMTP_PORT=",
"_APP_SMTP_SECURE=",
"_APP_SMTP_USERNAME=",
"_APP_SMTP_PASSWORD=",
"_APP_SMS_PROVIDER=",
"_APP_SMS_FROM=",
"_APP_STORAGE_LIMIT=30000000",
"_APP_STORAGE_PREVIEW_LIMIT=20000000",
"_APP_STORAGE_ANTIVIRUS=disabled",
"_APP_STORAGE_ANTIVIRUS_HOST=clamav",
"_APP_STORAGE_ANTIVIRUS_PORT=3310",
"_APP_STORAGE_DEVICE=local",
"_APP_STORAGE_S3_ACCESS_KEY=",
"_APP_STORAGE_S3_SECRET=",
"_APP_STORAGE_S3_REGION=us-east-1",
"_APP_STORAGE_S3_BUCKET=",
"_APP_STORAGE_DO_SPACES_ACCESS_KEY=",
"_APP_STORAGE_DO_SPACES_SECRET=",
"_APP_STORAGE_DO_SPACES_REGION=us-east-1",
"_APP_STORAGE_DO_SPACES_BUCKET=",
"_APP_STORAGE_BACKBLAZE_ACCESS_KEY=",
"_APP_STORAGE_BACKBLAZE_SECRET=",
"_APP_STORAGE_BACKBLAZE_REGION=us-west-004",
"_APP_STORAGE_BACKBLAZE_BUCKET=",
"_APP_STORAGE_LINODE_ACCESS_KEY=",
"_APP_STORAGE_LINODE_SECRET=",
"_APP_STORAGE_LINODE_REGION=eu-central-1",
"_APP_STORAGE_LINODE_BUCKET=",
"_APP_STORAGE_WASABI_ACCESS_KEY=",
"_APP_STORAGE_WASABI_SECRET=",
"_APP_STORAGE_WASABI_REGION=eu-central-1",
"_APP_STORAGE_WASABI_BUCKET=",
"_APP_FUNCTIONS_SIZE_LIMIT=30000000",
"_APP_FUNCTIONS_BUILD_SIZE_LIMIT=2000000000",
"_APP_FUNCTIONS_TIMEOUT=900",
"_APP_FUNCTIONS_BUILD_TIMEOUT=900",
"_APP_FUNCTIONS_CONTAINERS=10",
"_APP_FUNCTIONS_CPUS=0",
"_APP_FUNCTIONS_MEMORY=0",
"_APP_FUNCTIONS_MEMORY_SWAP=0",
"_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0",
"_APP_EXECUTOR_SECRET=your-secret-key",
"_APP_EXECUTOR_HOST=http://exc1/v1",
"_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes",
"_APP_FUNCTIONS_ENVS=node-16.0,php-7.4,python-3.9,ruby-3.0",
"_APP_FUNCTIONS_INACTIVE_THRESHOLD=60",
"DOCKERHUB_PULL_USERNAME=",
"DOCKERHUB_PULL_PASSWORD=",
"DOCKERHUB_PULL_EMAIL=",
"OPEN_RUNTIMES_NETWORK=appwrite_runtimes",
"_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes",
"_APP_DOCKER_HUB_USERNAME=",
"_APP_DOCKER_HUB_PASSWORD=",
"_APP_FUNCTIONS_MAINTENANCE_INTERVAL=3600",
"_APP_VCS_GITHUB_APP_NAME=",
"_APP_VCS_GITHUB_PRIVATE_KEY=",
"_APP_VCS_GITHUB_APP_ID=",
"_APP_VCS_GITHUB_CLIENT_ID=",
"_APP_VCS_GITHUB_CLIENT_SECRET=",
"_APP_VCS_GITHUB_WEBHOOK_SECRET=",
"_APP_MAINTENANCE_INTERVAL=86400",
"_APP_MAINTENANCE_DELAY=0",
"_APP_MAINTENANCE_RETENTION_CACHE=2592000",
"_APP_MAINTENANCE_RETENTION_EXECUTION=1209600",
"_APP_MAINTENANCE_RETENTION_AUDIT=1209600",
"_APP_MAINTENANCE_RETENTION_ABUSE=86400",
"_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000",
"_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
"_APP_GRAPHQL_MAX_BATCH_SIZE=10",
"_APP_GRAPHQL_MAX_COMPLEXITY=250",
"_APP_GRAPHQL_MAX_DEPTH=3",
"_APP_MIGRATIONS_FIREBASE_CLIENT_ID=",
"_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=",
"_APP_ASSISTANT_OPENAI_API_KEY=",
];
return {
domains,
envs,
mounts: [],
};
}

View File

@@ -0,0 +1,37 @@
services:
backend:
image: ghcr.io/get-convex/convex-backend:6c974d219776b753cd23d26f4a296629ff7c2cad
ports:
- "${PORT:-3210}:3210"
- "${SITE_PROXY_PORT:-3211}:3211"
volumes:
- data:/convex/data
environment:
- INSTANCE_NAME=${INSTANCE_NAME:-}
- INSTANCE_SECRET=${INSTANCE_SECRET:-}
- CONVEX_RELEASE_VERSION_DEV=${CONVEX_RELEASE_VERSION_DEV:-}
- ACTIONS_USER_TIMEOUT_SECS=${ACTIONS_USER_TIMEOUT_SECS:-}
- CONVEX_CLOUD_ORIGIN=${CONVEX_CLOUD_ORIGIN:-http://127.0.0.1:3210}
- CONVEX_SITE_ORIGIN=${CONVEX_SITE_ORIGIN:-http://127.0.0.1:3211}
- DATABASE_URL=${DATABASE_URL:-}
- DISABLE_BEACON=${DISABLE_BEACON:-}
- REDACT_LOGS_TO_CLIENT=${REDACT_LOGS_TO_CLIENT:-}
- RUST_LOG=${RUST_LOG:-info}
- RUST_BACKTRACE=${RUST_BACKTRACE:-}
healthcheck:
test: curl -f http://localhost:3210/version
interval: 5s
start_period: 5s
dashboard:
image: ghcr.io/get-convex/convex-dashboard:4499dd4fd7f2148687a7774599c613d052950f46
ports:
- "${DASHBOARD_PORT:-6791}:6791"
environment:
- NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://127.0.0.1:3210}
depends_on:
backend:
condition: service_healthy
volumes:
data:

View File

@@ -0,0 +1,38 @@
import {
type DomainSchema,
type Schema,
type Template,
generateRandomDomain,
} from "../utils";
export function generate(schema: Schema): Template {
const dashboardDomain = generateRandomDomain(schema);
const backendDomain = generateRandomDomain(schema);
const actionsDomain = generateRandomDomain(schema);
const domains: DomainSchema[] = [
{
host: dashboardDomain,
port: 6791,
serviceName: "dashboard",
},
{
host: backendDomain,
port: 3210,
serviceName: "backend",
},
{
host: actionsDomain,
port: 3211,
serviceName: "backend",
},
];
const envs = [
`NEXT_PUBLIC_DEPLOYMENT_URL=http://${backendDomain}`,
`CONVEX_CLOUD_ORIGIN=http://${backendDomain}`,
`CONVEX_SITE_ORIGIN=http://${actionsDomain}`,
];
return { envs, domains };
}

View File

@@ -0,0 +1,57 @@
services:
outline:
image: outlinewiki/outline:0.82.0
restart: always
depends_on:
- postgres
- redis
- dex
ports:
- 3000
environment:
NODE_ENV: production
URL: ${URL}
FORCE_HTTPS: 'false'
SECRET_KEY: ${SECRET_KEY}
UTILS_SECRET: ${UTILS_SECRET}
DATABASE_URL: postgres://outline:${POSTGRES_PASSWORD}@postgres:5432/outline
PGSSLMODE: disable
REDIS_URL: redis://redis:6379
OIDC_CLIENT_ID: outline
OIDC_CLIENT_SECRET: ${CLIENT_SECRET}
OIDC_AUTH_URI: ${DEX_URL}/auth
OIDC_TOKEN_URI: ${DEX_URL}/token
OIDC_USERINFO_URI: ${DEX_URL}/userinfo
dex:
image: ghcr.io/dexidp/dex:v2.37.0
restart: always
volumes:
- ../files/etc/dex/config.yaml:/etc/dex/config.yaml
command:
- dex
- serve
- /etc/dex/config.yaml
ports:
- 5556
postgres:
image: postgres:15
restart: always
environment:
POSTGRES_DB: outline
POSTGRES_USER: outline
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data-test-outline-khufpx:/var/lib/postgresql/data
redis:
image: redis:latest
restart: always
command: redis-server --appendonly yes
volumes:
- redis_data-test-outline-khufpx:/data
volumes:
postgres_data-test-outline-khufpx:
redis_data-test-outline-khufpx:

View File

@@ -0,0 +1,90 @@
import {
type DomainSchema,
type Schema,
type Template,
generateBase64,
generatePassword,
generateRandomDomain,
} from "../utils";
export function generate(schema: Schema): Template {
const mainDomain = generateRandomDomain(schema);
const dexDomain = generateRandomDomain(schema);
const SECRET_KEY = generateBase64(32);
const UTILS_SECRET = generateBase64(32);
const CLIENT_SECRET = generateBase64(32);
const POSTGRES_PASSWORD = generatePassword();
const mainURL = `http://${mainDomain}`;
const dexURL = `http://${dexDomain}`;
const domains: DomainSchema[] = [
{
host: mainDomain,
port: 3000,
serviceName: "outline",
},
{
host: dexDomain,
port: 5556,
serviceName: "dex",
},
];
const mounts: Template["mounts"] = [
{
filePath: "/etc/dex/config.yaml",
content: `issuer: ${dexURL}
web:
http: 0.0.0.0:5556
storage:
type: memory
enablePasswordDB: true
frontend:
issuer: Outline
logger:
level: debug
staticPasswords:
- email: "admin@example.com"
# bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
hash: "$2y$10$jsRWHw54uxTUIfhjgUrB9u8HSzPk7TUuQri9sXZrKzRXcScvwYor."
username: "admin"
userID: "1"
oauth2:
skipApprovalScreen: true
alwaysShowLoginScreen: false
passwordConnector: local
staticClients:
- id: "outline"
redirectURIs:
- ${mainURL}/auth/oidc.callback
name: "Outline"
secret: "${CLIENT_SECRET}"`,
},
];
const envs = [
`URL=${mainURL}`,
`DEX_URL=${dexURL}`,
`DOMAIN_NAME=${mainDomain}`,
`POSTGRES_PASSWORD=${POSTGRES_PASSWORD}`,
`SECRET_KEY=${SECRET_KEY}`,
`UTILS_SECRET=${UTILS_SECRET}`,
`CLIENT_SECRET=${CLIENT_SECRET}`,
];
return {
domains,
envs,
mounts,
};
}

View File

@@ -1,4 +1,3 @@
version: "3.8"
services:
plausible_db:
image: postgres:16-alpine
@@ -24,7 +23,7 @@ services:
hard: 262144
plausible:
image: ghcr.io/plausible/community-edition:v2.1.4
image: ghcr.io/plausible/community-edition:v2.1.5
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:

View File

@@ -0,0 +1,19 @@
services:
registry:
restart: always
image: registry:2
ports:
- 5000
volumes:
- ../files/auth/registry.password:/auth/registry.password
- registry-data:/var/lib/registry
environment:
REGISTRY_STORAGE_DELETE_ENABLED: true
REGISTRY_HEALTH_STORAGEDRIVER_ENABLED: false
REGISTRY_HTTP_SECRET: ${REGISTRY_HTTP_SECRET}
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
volumes:
registry-data:

View File

@@ -0,0 +1,35 @@
import {
type DomainSchema,
type Schema,
type Template,
generatePassword,
generateRandomDomain,
} from "../utils";
export function generate(schema: Schema): Template {
const domains: DomainSchema[] = [
{
host: generateRandomDomain(schema),
port: 5000,
serviceName: "registry",
},
];
const registryHttpSecret = generatePassword(30);
const envs = [`REGISTRY_HTTP_SECRET=${registryHttpSecret}`];
const mounts: Template["mounts"] = [
{
filePath: "/auth/registry.password",
content:
"# from: docker run --rm --entrypoint htpasswd httpd:2 -Bbn docker password\ndocker:$2y$10$qWZoWev/u5PV7WneFoRAMuoGpRcAQOgUuIIdLnU7pJXogrBSY23/2\n",
},
];
return {
domains,
envs,
mounts,
};
}

View File

@@ -1,5 +1,8 @@
# Note: this is an UNOFFICIAL production docker image build for Superset:
# This is an UNOFFICIAL production docker image build for Superset:
# - https://github.com/amancevice/docker-superset
# ## SETUP INSTRUCTIONS
#
# After deploying this image, you will need to run one of the two
# commands below in a terminal within the superset container:
@@ -7,11 +10,30 @@
# $ superset-init # Initialise database only
#
# You will be prompted to enter the credentials for the admin user.
# ## NETWORK INSTRUCTIONS
#
# If you want to connect superset with other internal databases managed by
# Dokploy (on dokploy-network) using internal hostnames, you will need to
# uncomment the `networks` section, both for the superset container and
# at the very bottom of this docker-compose template.
#
# Note that the `superset` service name/hostname will not be unique on the
# global `dokploy-network`. If you plan to:
#
# 1. deploy a second instance of superset on dokploy-network, and
# 2. have other containers on dokploy-network utilise the second instance's
# Superset API (https://superset.apache.org/docs/api)
#
# Please change the service name of the second instance.
services:
superset:
image: amancevice/superset
restart: always
#networks:
# - dokploy-network
depends_on:
- superset_postgres
- superset_redis
@@ -44,8 +66,7 @@ services:
timeout: 10s
retries: 3
superset_redis:
superset_redis:
image: redis
restart: always
volumes:
@@ -57,6 +78,9 @@ services:
timeout: 10s
retries: 3
#networks:
# dokploy-network:
# external: true
volumes:
superset_postgres_data:

View File

@@ -1,6 +1,37 @@
import type { TemplateData } from "./types/templates-data.type";
export const templates: TemplateData[] = [
{
id: "appwrite",
name: "Appwrite",
version: "1.6.0",
description:
"Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.\n" +
"Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and more services.",
links: {
github: "https://github.com/appwrite/appwrite",
website: "https://appwrite.io/",
docs: "https://appwrite.io/docs",
},
logo: "appwrite.svg",
tags: ["database", "firebase", "postgres"],
load: () => import("./appwrite/index").then((m) => m.generate),
},
{
id: "outline",
name: "Outline",
version: "0.82.0",
description:
"Outline is a self-hosted knowledge base and documentation platform that allows you to build and manage your own knowledge base applications.",
links: {
github: "https://github.com/outline/outline",
website: "https://outline.com/",
docs: "https://docs.outline.com/",
},
logo: "outline.png",
load: () => import("./outline/index").then((m) => m.generate),
tags: ["documentation", "knowledge-base", "self-hosted"],
},
{
id: "supabase",
name: "SupaBase",
@@ -34,7 +65,7 @@ export const templates: TemplateData[] = [
{
id: "plausible",
name: "Plausible",
version: "v2.1.4",
version: "v2.1.5",
description:
"Plausible is a open source, self-hosted web analytics platform that lets you track website traffic and user behavior.",
logo: "plausible.svg",
@@ -170,7 +201,7 @@ export const templates: TemplateData[] = [
{
id: "wordpress",
name: "Wordpress",
version: "5.8.3",
version: "6.7.1",
description:
"Wordpress is a free and open source content management system (CMS) for publishing and managing websites.",
logo: "wordpress.png",
@@ -1408,6 +1439,21 @@ export const templates: TemplateData[] = [
tags: ["file-manager", "vdfs", "storage"],
load: () => import("./spacedrive/index").then((m) => m.generate),
},
{
id: "registry",
name: "Docker Registry",
version: "2",
description:
"Distribution implementation for storing and distributing of Docker container images and artifacts.",
links: {
github: "https://github.com/distribution/distribution",
website: "https://hub.docker.com/_/registry",
docs: "https://distribution.github.io/distribution/",
},
logo: "registry.png",
tags: ["registry", "docker", "self-hosted"],
load: () => import("./registry/index").then((m) => m.generate),
},
{
id: "alist",
name: "AList",
@@ -1483,4 +1529,34 @@ export const templates: TemplateData[] = [
tags: ["forms", "analytics"],
load: () => import("./formbricks/index").then((m) => m.generate),
},
{
id: "trilium",
name: "Trilium",
description:
"Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases.",
logo: "trilium.png",
version: "latest",
links: {
github: "https://github.com/zadam/trilium",
website: "https://github.com/zadam/trilium",
docs: "https://github.com/zadam/trilium/wiki/",
},
tags: ["self-hosted", "productivity", "personal-use"],
load: () => import("./trilium/index").then((m) => m.generate),
},
{
id: "convex",
name: "Convex",
version: "latest",
description:
"Convex is an open-source reactive database designed to make life easy for web app developers.",
logo: "convex.svg",
links: {
github: "https://github.com/get-convex/convex",
website: "https://www.convex.dev/",
docs: "https://www.convex.dev/docs",
},
tags: ["backend", "database", "api"],
load: () => import("./convex/index").then((m) => m.generate),
},
];

View File

@@ -0,0 +1,14 @@
services:
trilium:
image: zadam/trilium:latest
ports:
- 8080
networks:
- dokploy-network
restart: always
volumes:
- /root/trilium-backups:/home/node/trilium-data/backup
networks:
dokploy-network:
external: true

View File

@@ -0,0 +1,22 @@
import {
type DomainSchema,
type Schema,
type Template,
generateRandomDomain,
} from "../utils";
export function generate(schema: Schema): Template {
const triliumDomain = generateRandomDomain(schema);
const domains: DomainSchema[] = [
{
host: triliumDomain,
port: 8080,
serviceName: "trilium",
},
];
return {
domains,
};
}

View File

@@ -12,7 +12,9 @@ export interface Schema {
projectName: string;
}
export type DomainSchema = Pick<Domain, "host" | "port" | "serviceName">;
export type DomainSchema = Pick<Domain, "host" | "port" | "serviceName"> & {
path?: string;
};
export interface Template {
envs?: string[];

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