Compare commits

...

26 Commits

Author SHA1 Message Date
Mauricio Siu
8b71f963cc refactor: update logic 2025-02-15 19:35:22 -06:00
Mauricio Siu
1c5cc5a0db refactor: update roles 2025-02-15 19:23:08 -06:00
Mauricio Siu
d233f2c764 feat: adjust roles 2025-02-15 19:12:44 -06:00
Mauricio Siu
1bbb4c9b64 refactor: update migration 2025-02-15 18:13:20 -06:00
Mauricio Siu
6ec60b6bab refactor: update validation 2025-02-15 13:14:48 -06:00
Mauricio Siu
55abac3f2f refactor: migrate endpoints 2025-02-14 02:52:37 -06:00
Mauricio Siu
b6c29ccf05 refactor: update 2025-02-14 02:40:11 -06:00
Mauricio Siu
ca217affe6 feat: update references 2025-02-14 02:18:53 -06:00
Mauricio Siu
5c24281f72 refactor: return correct information 2025-02-13 02:45:33 -06:00
Mauricio Siu
bc901bcb25 refactor: update 2025-02-13 02:36:08 -06:00
Mauricio Siu
7c0d223e17 refactor: add fields 2025-02-13 01:42:58 -06:00
Mauricio Siu
74ee024cf9 refactor: update temps 2025-02-13 01:24:25 -06:00
Mauricio Siu
140a871275 refactor: update 2025-02-13 01:21:49 -06:00
Mauricio Siu
d1f72a2e20 refactor: update migration 2025-02-13 00:57:22 -06:00
Mauricio Siu
0d525398a8 feat: migrate rest schemas 2025-02-13 00:45:29 -06:00
Mauricio Siu
7c62408070 refactor: delete 2025-02-13 00:38:39 -06:00
Mauricio Siu
23f1ce17de refactor: add migration 2025-02-13 00:38:22 -06:00
Mauricio Siu
60eee55f2d refactor: test migrastion 2025-02-12 23:41:04 -06:00
Mauricio Siu
8f562eefc1 Merge branch 'canary' into feat/better-auth 2025-02-12 20:56:23 -06:00
Mauricio Siu
6179cef1ee refactor: update name 2025-02-10 02:13:52 -06:00
Mauricio Siu
b7112b89fd refactor: add migration 2025-02-10 00:39:46 -06:00
Mauricio Siu
1db6ba94f4 refactor: remove 2025-02-09 21:36:36 -06:00
Mauricio Siu
afd3d2eea3 refactor: lint 2025-02-09 20:53:14 -06:00
Mauricio Siu
8bd72a8a34 refactor: add organizations system 2025-02-09 20:53:06 -06:00
Mauricio Siu
fafc238e70 refactor: migration 2025-02-09 18:56:17 -06:00
Mauricio Siu
c04bf3c7e0 feat: add migration 2025-02-09 18:19:21 -06:00
132 changed files with 24380 additions and 893 deletions

View File

@@ -21,6 +21,7 @@ import {
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { authClient } from "@/lib/auth";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon, SquarePen } from "lucide-react";
@@ -97,6 +98,18 @@ export const HandleProject = ({ projectId }: Props) => {
);
});
};
// useEffect(() => {
// const getUsers = async () => {
// const users = await authClient.admin.listUsers({
// query: {
// limit: 100,
// },
// });
// console.log(users);
// };
// getUsers();
// });
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>

View File

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

View File

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

View File

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

View File

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

View File

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

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?.rol === "admin" || user?.canAccessToTraefikFiles) &&
(auth?.role === "owner" || user?.canAccessToTraefikFiles) &&
!isCloud
),
},
@@ -166,7 +166,7 @@ const MENU: Menu = {
icon: BlocksIcon,
// Only enabled for admins and users with access to Docker in non-cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!((auth?.rol === "admin" || user?.canAccessToDocker) && !isCloud),
!!((auth?.role === "owner" || user?.canAccessToDocker) && !isCloud),
},
{
isSingle: true,
@@ -175,7 +175,7 @@ const MENU: Menu = {
icon: PieChart,
// Only enabled for admins and users with access to Docker in non-cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!((auth?.rol === "admin" || user?.canAccessToDocker) && !isCloud),
!!((auth?.role === "owner" || user?.canAccessToDocker) && !isCloud),
},
{
isSingle: true,
@@ -184,7 +184,7 @@ const MENU: Menu = {
icon: Forward,
// Only enabled for admins and users with access to Docker in non-cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!((auth?.rol === "admin" || user?.canAccessToDocker) && !isCloud),
!!((auth?.role === "owner" || user?.canAccessToDocker) && !isCloud),
},
// Legacy unused menu, adjusted to the new structure
@@ -252,7 +252,7 @@ const MENU: Menu = {
icon: Activity,
// Only enabled for admins in non-cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!(auth?.rol === "admin" && !isCloud),
!!(auth?.role === "owner" && !isCloud),
},
{
isSingle: true,
@@ -266,7 +266,7 @@ const MENU: Menu = {
url: "/dashboard/settings/servers",
icon: Server,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
},
{
isSingle: true,
@@ -274,7 +274,7 @@ const MENU: Menu = {
icon: Users,
url: "/dashboard/settings/users",
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
},
{
isSingle: true,
@@ -283,7 +283,7 @@ const MENU: Menu = {
url: "/dashboard/settings/ssh-keys",
// Only enabled for admins and users with access to SSH keys
isEnabled: ({ auth, user }) =>
!!(auth?.rol === "admin" || user?.canAccessToSSHKeys),
!!(auth?.role === "owner" || user?.canAccessToSSHKeys),
},
{
isSingle: true,
@@ -292,7 +292,7 @@ const MENU: Menu = {
icon: GitBranch,
// Only enabled for admins and users with access to Git providers
isEnabled: ({ auth, user }) =>
!!(auth?.rol === "admin" || user?.canAccessToGitProviders),
!!(auth?.role === "owner" || user?.canAccessToGitProviders),
},
{
isSingle: true,
@@ -300,7 +300,7 @@ const MENU: Menu = {
url: "/dashboard/settings/registry",
icon: Package,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
},
{
isSingle: true,
@@ -308,7 +308,7 @@ const MENU: Menu = {
url: "/dashboard/settings/destinations",
icon: Database,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
},
{
@@ -317,7 +317,7 @@ const MENU: Menu = {
url: "/dashboard/settings/certificates",
icon: ShieldCheck,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
},
{
isSingle: true,
@@ -326,7 +326,7 @@ const MENU: Menu = {
icon: Boxes,
// Only enabled for admins in non-cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!(auth?.rol === "admin" && !isCloud),
!!(auth?.role === "owner" && !isCloud),
},
{
isSingle: true,
@@ -334,7 +334,7 @@ const MENU: Menu = {
url: "/dashboard/settings/notifications",
icon: Bell,
// Only enabled for admins
isEnabled: ({ auth, user, isCloud }) => !!(auth?.rol === "admin"),
isEnabled: ({ auth, user, isCloud }) => !!(auth?.role === "owner"),
},
{
isSingle: true,
@@ -343,7 +343,7 @@ const MENU: Menu = {
icon: CreditCard,
// Only enabled for admins in cloud environments
isEnabled: ({ auth, user, isCloud }) =>
!!(auth?.rol === "admin" && isCloud),
!!(auth?.role === "owner" && isCloud),
},
],
@@ -537,7 +537,7 @@ export default function Page({ children }: Props) {
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.rol === "user",
enabled: !!auth?.id && auth?.role === "member",
},
);
@@ -557,7 +557,7 @@ export default function Page({ children }: Props) {
// const showProjectsButton =
// currentPath === "/dashboard/projects" &&
// (auth?.rol === "admin" || user?.canCreateProjects);
// (auth?.rol === "owner" || user?.canCreateProjects);
return (
<SidebarProvider
@@ -783,7 +783,7 @@ export default function Page({ children }: Props) {
</SidebarMenuButton>
</SidebarMenuItem>
))}
{!isCloud && auth?.rol === "admin" && (
{!isCloud && auth?.role === "owner" && (
<SidebarMenuItem>
<SidebarMenuButton asChild>
<UpdateServerButton />

View File

@@ -15,6 +15,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { authClient } from "@/lib/auth";
import { Languages } from "@/lib/languages";
import { api } from "@/utils/api";
import useLocale from "@/utils/hooks/use-locale";
@@ -36,11 +37,11 @@ export const UserNav = () => {
authId: data?.id || "",
},
{
enabled: !!data?.id && data?.rol === "user",
enabled: !!data?.id && data?.role === "member",
},
);
const { locale, setLocale } = useLocale();
const { mutateAsync } = api.auth.logout.useMutation();
// const { mutateAsync } = api.auth.logout.useMutation();
return (
<DropdownMenu>
@@ -50,12 +51,15 @@ export const UserNav = () => {
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={data?.image || ""} alt={data?.image || ""} />
<AvatarImage
src={data?.user?.image || ""}
alt={data?.user?.image || ""}
/>
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">Account</span>
<span className="truncate text-xs">{data?.email}</span>
<span className="truncate text-xs">{data?.user?.email}</span>
</div>
<ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton>
@@ -70,7 +74,7 @@ export const UserNav = () => {
<DropdownMenuLabel className="flex flex-col">
My Account
<span className="text-xs font-normal text-muted-foreground">
{data?.email}
{data?.user?.email}
</span>
</DropdownMenuLabel>
<ModeToggle />
@@ -95,7 +99,7 @@ export const UserNav = () => {
>
Monitoring
</DropdownMenuItem>
{(data?.rol === "admin" || user?.canAccessToTraefikFiles) && (
{(data?.role === "owner" || user?.canAccessToTraefikFiles) && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -105,7 +109,7 @@ export const UserNav = () => {
Traefik
</DropdownMenuItem>
)}
{(data?.rol === "admin" || user?.canAccessToDocker) && (
{(data?.role === "owner" || user?.canAccessToDocker) && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -118,7 +122,7 @@ export const UserNav = () => {
</DropdownMenuItem>
)}
{data?.rol === "admin" && (
{data?.role === "owner" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -139,7 +143,7 @@ export const UserNav = () => {
>
Profile
</DropdownMenuItem>
{data?.rol === "admin" && (
{data?.role === "owner" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -150,7 +154,7 @@ export const UserNav = () => {
</DropdownMenuItem>
)}
{data?.rol === "admin" && (
{data?.role === "owner" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -163,7 +167,7 @@ export const UserNav = () => {
</>
)}
</DropdownMenuGroup>
{isCloud && data?.rol === "admin" && (
{isCloud && data?.role === "owner" && (
<DropdownMenuItem
className="cursor-pointer"
onClick={() => {
@@ -178,9 +182,12 @@ export const UserNav = () => {
<DropdownMenuItem
className="cursor-pointer"
onClick={async () => {
await mutateAsync().then(() => {
await authClient.signOut().then(() => {
router.push("/");
});
// await mutateAsync().then(() => {
// router.push("/");
// });
}}
>
Log out

View File

@@ -0,0 +1,127 @@
CREATE TABLE "user_temp" (
"id" text PRIMARY KEY NOT NULL,
"name" text DEFAULT '' NOT NULL,
"token" text NOT NULL,
"isRegistered" boolean DEFAULT false NOT NULL,
"expirationDate" text NOT NULL,
"createdAt" text NOT NULL,
"canCreateProjects" boolean DEFAULT false NOT NULL,
"canAccessToSSHKeys" boolean DEFAULT false NOT NULL,
"canCreateServices" boolean DEFAULT false NOT NULL,
"canDeleteProjects" boolean DEFAULT false NOT NULL,
"canDeleteServices" boolean DEFAULT false NOT NULL,
"canAccessToDocker" boolean DEFAULT false NOT NULL,
"canAccessToAPI" boolean DEFAULT false NOT NULL,
"canAccessToGitProviders" boolean DEFAULT false NOT NULL,
"canAccessToTraefikFiles" boolean DEFAULT false NOT NULL,
"accesedProjects" text[] DEFAULT ARRAY[]::text[] NOT NULL,
"accesedServices" text[] DEFAULT ARRAY[]::text[] NOT NULL,
"email" text NOT NULL,
"email_verified" boolean NOT NULL,
"image" text,
"banned" boolean,
"ban_reason" text,
"ban_expires" timestamp,
"updated_at" timestamp NOT NULL,
"serverIp" text,
"certificateType" "certificateType" DEFAULT 'none' NOT NULL,
"host" text,
"letsEncryptEmail" text,
"sshPrivateKey" text,
"enableDockerCleanup" boolean DEFAULT false NOT NULL,
"enableLogRotation" boolean DEFAULT false NOT NULL,
"enablePaidFeatures" boolean DEFAULT false NOT NULL,
"metricsConfig" jsonb DEFAULT '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}'::jsonb NOT NULL,
"cleanupCacheApplications" boolean DEFAULT false NOT NULL,
"cleanupCacheOnPreviews" boolean DEFAULT false NOT NULL,
"cleanupCacheOnCompose" boolean DEFAULT false NOT NULL,
"stripeCustomerId" text,
"stripeSubscriptionId" text,
"serversQuantity" integer DEFAULT 0 NOT NULL,
CONSTRAINT "user_temp_email_unique" UNIQUE("email")
);
--> statement-breakpoint
CREATE TABLE "session_temp" (
"id" text PRIMARY KEY NOT NULL,
"expires_at" timestamp NOT NULL,
"token" text NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"ip_address" text,
"user_agent" text,
"user_id" text NOT NULL,
"impersonated_by" text,
"active_organization_id" text,
CONSTRAINT "session_temp_token_unique" UNIQUE("token")
);
--> statement-breakpoint
CREATE TABLE "account" (
"id" text PRIMARY KEY NOT NULL,
"account_id" text NOT NULL,
"provider_id" text NOT NULL,
"user_id" text NOT NULL,
"access_token" text,
"refresh_token" text,
"id_token" text,
"access_token_expires_at" timestamp,
"refresh_token_expires_at" timestamp,
"scope" text,
"password" text,
"is2FAEnabled" boolean DEFAULT false NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"resetPasswordToken" text,
"resetPasswordExpiresAt" text,
"confirmationToken" text,
"confirmationExpiresAt" text
);
--> statement-breakpoint
CREATE TABLE "invitation" (
"id" text PRIMARY KEY NOT NULL,
"organization_id" text NOT NULL,
"email" text NOT NULL,
"role" text,
"status" text NOT NULL,
"expires_at" timestamp NOT NULL,
"inviter_id" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE "member" (
"id" text PRIMARY KEY NOT NULL,
"organization_id" text NOT NULL,
"user_id" text NOT NULL,
"role" text NOT NULL,
"created_at" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE "organization" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"slug" text,
"logo" text,
"created_at" timestamp NOT NULL,
"metadata" text,
"owner_id" text NOT NULL,
CONSTRAINT "organization_slug_unique" UNIQUE("slug")
);
--> statement-breakpoint
CREATE TABLE "verification" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp,
"updated_at" timestamp
);
--> statement-breakpoint
ALTER TABLE "certificate" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "notification" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "ssh-key" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "git_provider" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "session_temp" ADD CONSTRAINT "session_temp_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_user_temp_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "organization" ADD CONSTRAINT "organization_owner_id_user_temp_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;

View File

@@ -0,0 +1,211 @@
-- Custom SQL migration file, put your code below! --
WITH inserted_users AS (
-- Insertar usuarios desde admins
INSERT INTO user_temp (
id,
email,
token,
"email_verified",
"updated_at",
"serverIp",
image,
"certificateType",
host,
"letsEncryptEmail",
"sshPrivateKey",
"enableDockerCleanup",
"enableLogRotation",
"enablePaidFeatures",
"metricsConfig",
"cleanupCacheApplications",
"cleanupCacheOnPreviews",
"cleanupCacheOnCompose",
"stripeCustomerId",
"stripeSubscriptionId",
"serversQuantity",
"expirationDate",
"createdAt"
)
SELECT
a."adminId",
auth.email,
COALESCE(auth.token, ''),
true,
CURRENT_TIMESTAMP,
a."serverIp",
auth.image,
a."certificateType",
a.host,
a."letsEncryptEmail",
a."sshPrivateKey",
a."enableDockerCleanup",
a."enableLogRotation",
a."enablePaidFeatures",
a."metricsConfig",
a."cleanupCacheApplications",
a."cleanupCacheOnPreviews",
a."cleanupCacheOnCompose",
a."stripeCustomerId",
a."stripeSubscriptionId",
a."serversQuantity",
NOW() + INTERVAL '1 year',
NOW()
FROM admin a
JOIN auth ON auth.id = a."authId"
RETURNING *
),
inserted_accounts AS (
-- Insertar cuentas para los admins
INSERT INTO account (
id,
"account_id",
"provider_id",
"user_id",
password,
"is2FAEnabled",
"created_at",
"updated_at"
)
SELECT
gen_random_uuid(),
gen_random_uuid(),
'credential',
a."adminId",
auth.password,
COALESCE(auth."is2FAEnabled", false),
NOW(),
NOW()
FROM admin a
JOIN auth ON auth.id = a."authId"
RETURNING *
),
inserted_orgs AS (
-- Crear organizaciones para cada admin
INSERT INTO organization (
id,
name,
slug,
"owner_id",
"created_at"
)
SELECT
gen_random_uuid(),
'My Organization',
-- Generamos un slug único usando una función de hash
encode(sha256((a."adminId" || CURRENT_TIMESTAMP)::bytea), 'hex'),
a."adminId",
NOW()
FROM admin a
RETURNING *
),
inserted_members AS (
-- Insertar usuarios miembros
INSERT INTO user_temp (
id,
email,
token,
"email_verified",
"updated_at",
image,
"createdAt",
"canAccessToAPI",
"canAccessToDocker",
"canAccessToGitProviders",
"canAccessToSSHKeys",
"canAccessToTraefikFiles",
"canCreateProjects",
"canCreateServices",
"canDeleteProjects",
"canDeleteServices",
"accesedProjects",
"accesedServices",
"expirationDate"
)
SELECT
u."userId",
auth.email,
COALESCE(u.token, ''),
true,
CURRENT_TIMESTAMP,
auth.image,
NOW(),
COALESCE(u."canAccessToAPI", false),
COALESCE(u."canAccessToDocker", false),
COALESCE(u."canAccessToGitProviders", false),
COALESCE(u."canAccessToSSHKeys", false),
COALESCE(u."canAccessToTraefikFiles", false),
COALESCE(u."canCreateProjects", false),
COALESCE(u."canCreateServices", false),
COALESCE(u."canDeleteProjects", false),
COALESCE(u."canDeleteServices", false),
COALESCE(u."accesedProjects", '{}'),
COALESCE(u."accesedServices", '{}'),
NOW() + INTERVAL '1 year'
FROM "user" u
JOIN admin a ON u."adminId" = a."adminId"
JOIN auth ON auth.id = u."authId"
RETURNING *
),
inserted_member_accounts AS (
-- Insertar cuentas para los usuarios miembros
INSERT INTO account (
id,
"account_id",
"provider_id",
"user_id",
password,
"is2FAEnabled",
"created_at",
"updated_at"
)
SELECT
gen_random_uuid(),
gen_random_uuid(),
'credential',
u."userId",
auth.password,
COALESCE(auth."is2FAEnabled", false),
NOW(),
NOW()
FROM "user" u
JOIN admin a ON u."adminId" = a."adminId"
JOIN auth ON auth.id = u."authId"
RETURNING *
),
inserted_admin_members AS (
-- Insertar miembros en las organizaciones (admins como owners)
INSERT INTO member (
id,
"organization_id",
"user_id",
role,
"created_at"
)
SELECT
gen_random_uuid(),
o.id,
a."adminId",
'owner',
NOW()
FROM admin a
JOIN inserted_orgs o ON o."owner_id" = a."adminId"
RETURNING *
)
-- Insertar miembros regulares en las organizaciones
INSERT INTO member (
id,
"organization_id",
"user_id",
role,
"created_at"
)
SELECT
gen_random_uuid(),
o.id,
u."userId",
'member',
NOW()
FROM "user" u
JOIN admin a ON u."adminId" = a."adminId"
JOIN inserted_orgs o ON o."owner_id" = a."adminId";

View File

@@ -0,0 +1,32 @@
ALTER TABLE "project" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "destination" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "certificate" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "registry" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "notification" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "ssh-key" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "git_provider" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "server" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "project" DROP CONSTRAINT "project_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "destination" DROP CONSTRAINT "destination_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "certificate" DROP CONSTRAINT "certificate_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "registry" DROP CONSTRAINT "registry_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "notification" DROP CONSTRAINT "notification_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "ssh-key" DROP CONSTRAINT "ssh-key_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "git_provider" DROP CONSTRAINT "git_provider_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "server" DROP CONSTRAINT "server_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "project" ADD CONSTRAINT "project_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "destination" ADD CONSTRAINT "destination_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "certificate" ADD CONSTRAINT "certificate_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "registry" ADD CONSTRAINT "registry_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "notification" ADD CONSTRAINT "notification_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "ssh-key" ADD CONSTRAINT "ssh-key_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "server" ADD CONSTRAINT "server_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;

View File

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

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,6 +463,34 @@
"when": 1739087857244,
"tag": "0065_daily_zaladane",
"breakpoints": true
},
{
"idx": 66,
"version": "7",
"when": 1739426913392,
"tag": "0066_yielding_echo",
"breakpoints": true
},
{
"idx": 67,
"version": "7",
"when": 1739427057545,
"tag": "0067_migrate-data",
"breakpoints": true
},
{
"idx": 68,
"version": "7",
"when": 1739428942964,
"tag": "0068_sour_professor_monster",
"breakpoints": true
},
{
"idx": 69,
"version": "7",
"when": 1739664410814,
"tag": "0069_broad_ken_ellis",
"breakpoints": true
}
]
}

7
apps/dokploy/lib/auth.ts Normal file
View File

@@ -0,0 +1,7 @@
import { organizationClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: "http://localhost:3000", // the base url of your auth server
plugins: [organizationClient()],
});

126
apps/dokploy/migrate.ts Normal file
View File

@@ -0,0 +1,126 @@
import { drizzle } from "drizzle-orm/postgres-js";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import { nanoid } from "nanoid";
import postgres from "postgres";
import * as schema from "./server/db/schema";
const connectionString = process.env.DATABASE_URL!;
const sql = postgres(connectionString, { max: 1 });
const db = drizzle(sql, {
schema,
});
await db
.transaction(async (db) => {
const admins = await db.query.admins.findMany({
with: {
auth: true,
users: {
with: {
auth: true,
},
},
},
});
for (const admin of admins) {
const user = await db
.insert(schema.users_temp)
.values({
id: admin.adminId,
email: admin.auth.email,
token: admin.auth.token || "",
emailVerified: true,
updatedAt: new Date(),
role: "admin",
serverIp: admin.serverIp,
image: admin.auth.image,
certificateType: admin.certificateType,
host: admin.host,
letsEncryptEmail: admin.letsEncryptEmail,
sshPrivateKey: admin.sshPrivateKey,
enableDockerCleanup: admin.enableDockerCleanup,
enableLogRotation: admin.enableLogRotation,
enablePaidFeatures: admin.enablePaidFeatures,
metricsConfig: admin.metricsConfig,
cleanupCacheApplications: admin.cleanupCacheApplications,
cleanupCacheOnPreviews: admin.cleanupCacheOnPreviews,
cleanupCacheOnCompose: admin.cleanupCacheOnCompose,
stripeCustomerId: admin.stripeCustomerId,
stripeSubscriptionId: admin.stripeSubscriptionId,
serversQuantity: admin.serversQuantity,
})
.returning()
.then((user) => user[0]);
await db.insert(schema.account).values({
providerId: "credential",
userId: user?.id || "",
password: admin.auth.password,
is2FAEnabled: admin.auth.is2FAEnabled || false,
createdAt: new Date(admin.auth.createdAt) || new Date(),
updatedAt: new Date(admin.auth.createdAt) || new Date(),
});
const organization = await db
.insert(schema.organization)
.values({
name: "My Organization",
slug: nanoid(),
ownerId: user?.id || "",
createdAt: new Date(admin.createdAt) || new Date(),
})
.returning()
.then((organization) => organization[0]);
for (const member of admin.users) {
const userTemp = await db
.insert(schema.users_temp)
.values({
id: member.userId,
email: member.auth.email,
token: member.token || "",
emailVerified: true,
updatedAt: new Date(admin.createdAt) || new Date(),
role: "user",
image: member.auth.image,
createdAt: admin.createdAt,
canAccessToAPI: member.canAccessToAPI || false,
canAccessToDocker: member.canAccessToDocker || false,
canAccessToGitProviders: member.canAccessToGitProviders || false,
canAccessToSSHKeys: member.canAccessToSSHKeys || false,
canAccessToTraefikFiles: member.canAccessToTraefikFiles || false,
canCreateProjects: member.canCreateProjects || false,
canCreateServices: member.canCreateServices || false,
canDeleteProjects: member.canDeleteProjects || false,
canDeleteServices: member.canDeleteServices || false,
accessedProjects: member.accessedProjects || [],
accessedServices: member.accessedServices || [],
})
.returning()
.then((userTemp) => userTemp[0]);
await db.insert(schema.account).values({
providerId: "credential",
userId: member?.userId || "",
password: member.auth.password,
is2FAEnabled: member.auth.is2FAEnabled || false,
createdAt: new Date(member.auth.createdAt) || new Date(),
updatedAt: new Date(member.auth.createdAt) || new Date(),
});
await db.insert(schema.member).values({
organizationId: organization?.id || "",
userId: userTemp?.id || "",
role: "admin",
createdAt: new Date(member.createdAt) || new Date(),
});
}
}
})
.then(() => {
console.log("Migration finished");
})
.catch((error) => {
console.error(error);
});

View File

@@ -1,6 +1,6 @@
{
"name": "dokploy",
"version": "v0.18.3",
"version": "v0.18.2",
"private": true,
"license": "Apache-2.0",
"type": "module",
@@ -16,6 +16,7 @@
"studio": "drizzle-kit studio --config ./server/db/drizzle.config.ts",
"migration:generate": "drizzle-kit generate --config ./server/db/drizzle.config.ts",
"migration:run": "tsx -r dotenv/config migration.ts",
"manual-migration:run": "tsx -r dotenv/config migrate.ts",
"migration:up": "drizzle-kit up --config ./server/db/drizzle.config.ts",
"migration:drop": "drizzle-kit drop --config ./server/db/drizzle.config.ts",
"db:push": "drizzle-kit push --config ./server/db/drizzle.config.ts",
@@ -35,6 +36,7 @@
"test": "vitest --config __test__/vitest.config.ts"
},
"dependencies": {
"better-auth": "1.1.16",
"bl": "6.0.11",
"rotating-file-stream": "3.2.3",
"qrcode": "^1.5.3",

View File

@@ -0,0 +1,7 @@
import { auth } from "@dokploy/server/index";
import { toNodeHandler } from "better-auth/node";
// Disallow body parsing, we will parse it manually
export const config = { api: { bodyParser: false } };
export default toNodeHandler(auth.handler);

View File

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

View File

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

View File

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

View File

@@ -70,9 +70,9 @@ import type {
} from "next";
import Head from "next/head";
import { useRouter } from "next/router";
import { useMemo, useState, type ReactElement } from "react";
import superjson from "superjson";
import { type ReactElement, useMemo, useState } from "react";
import { toast } from "sonner";
import superjson from "superjson";
export type Services = {
appName: string;
@@ -206,7 +206,7 @@ const Project = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.rol === "user",
enabled: !!auth?.id && auth?.role === "member",
},
);
const { data, isLoading, refetch } = api.project.one.useQuery({ projectId });
@@ -335,7 +335,7 @@ const Project = (
</CardTitle>
<CardDescription>{data?.description}</CardDescription>
</CardHeader>
{(auth?.rol === "admin" || user?.canCreateServices) && (
{(auth?.role === "owner" || user?.canCreateServices) && (
<div className="flex flex-row gap-4 flex-wrap">
<ProjectEnvironment projectId={projectId}>
<Button variant="outline">Project Environment</Button>

View File

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

View File

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

View File

@@ -68,7 +68,7 @@ const Mariadb = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.rol === "user",
enabled: !!auth?.id && auth?.role === "member",
},
);
const { data: isCloud } = api.settings.isCloud.useQuery();
@@ -154,7 +154,7 @@ const Mariadb = (
</div>
<div className="flex flex-row gap-2 justify-end">
<UpdateMariadb mariadbId={mariadbId} />
{(auth?.rol === "admin" || user?.canDeleteServices) && (
{(auth?.role === "owner" || user?.canDeleteServices) && (
<DeleteService id={mariadbId} type="mariadb" />
)}
</div>

View File

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

View File

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

View File

@@ -66,7 +66,7 @@ const Postgresql = (
authId: auth?.id || "",
},
{
enabled: !!auth?.id && auth?.rol === "user",
enabled: !!auth?.id && auth?.role === "member",
},
);
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
@@ -154,7 +154,7 @@ const Postgresql = (
<div className="flex flex-row gap-2 justify-end">
<UpdatePostgres postgresId={postgresId} />
{(auth?.rol === "admin" || user?.canDeleteServices) && (
{(auth?.role === "owner" || user?.canDeleteServices) && (
<DeleteService id={postgresId} type="postgres" />
)}
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -19,7 +19,7 @@ const Page = () => {
authId: data?.id || "",
},
{
enabled: !!data?.id && data?.rol === "user",
enabled: !!data?.id && data?.role === "user",
},
);
@@ -28,7 +28,7 @@ const Page = () => {
<div className="w-full">
<div className="h-full rounded-xl max-w-5xl mx-auto flex flex-col gap-4">
<ProfileForm />
{(user?.canAccessToAPI || data?.rol === "admin") && <GenerateToken />}
{(user?.canAccessToAPI || data?.role === "owner") && <GenerateToken />}
{isCloud && <RemoveSelfAccount />}
</div>
@@ -62,7 +62,7 @@ export async function getServerSideProps(
await helpers.settings.isCloud.prefetch();
await helpers.auth.get.prefetch();
if (user?.rol === "user") {
if (user?.role === "user") {
await helpers.user.byAuthId.prefetch({
authId: user.authId,
});

View File

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

View File

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

View File

@@ -36,7 +36,7 @@ export async function getServerSideProps(
},
};
}
if (user.rol === "user") {
if (user.role === "member") {
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.rol === "user") {
if (auth.role === "member") {
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.rol === "user") {
if (!user || user.role === "member") {
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.rol === "user") {
if (auth.role === "member") {
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.rol === "user") {
if (auth.role === "member") {
const user = await helpers.user.byAuthId.fetch({
authId: auth.id,
});

View File

@@ -13,10 +13,14 @@ import {
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth";
import { cn } from "@/lib/utils";
import { api } from "@/utils/api";
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
import { IS_CLOUD, auth, isAdminPresent } from "@dokploy/server";
import { validateRequest } from "@dokploy/server/lib/auth";
import { zodResolver } from "@hookform/resolvers/zod";
import { Session, getSessionCookie } from "better-auth";
import { betterFetch } from "better-auth/react";
import type { GetServerSidePropsContext } from "next";
import Link from "next/link";
import { useRouter } from "next/router";
@@ -56,17 +60,18 @@ interface Props {
IS_CLOUD: boolean;
}
export default function Home({ IS_CLOUD }: Props) {
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const [error, setError] = useState<string | null>(null);
const [temp, setTemp] = useState<AuthResponse>({
is2FAEnabled: false,
authId: "",
});
const { mutateAsync, isLoading, error, isError } =
api.auth.login.useMutation();
const router = useRouter();
const form = useForm<Login>({
defaultValues: {
email: "",
password: "",
email: "siumauricio@hotmail.com",
password: "Password123",
},
resolver: zodResolver(loginSchema),
});
@@ -76,25 +81,49 @@ export default function Home({ IS_CLOUD }: Props) {
}, [form, form.reset, form.formState.isSubmitSuccessful]);
const onSubmit = async (values: Login) => {
await mutateAsync({
email: values.email.toLowerCase(),
setIsLoading(true);
const { data, error } = await authClient.signIn.email({
email: values.email,
password: values.password,
})
.then((data) => {
if (data.is2FAEnabled) {
setTemp(data);
} else {
toast.success("Successfully signed in", {
duration: 2000,
});
router.push("/dashboard/projects");
}
})
.catch(() => {
toast.error("Signin failed", {
duration: 2000,
});
});
if (!error) {
// if (data) {
// setTemp(data);
// } else {
toast.success("Successfully signed in", {
duration: 2000,
});
router.push("/dashboard/projects");
// }
} else {
setIsError(true);
setError(error.message ?? "Error to signup");
toast.error("Error to sign up", {
description: error.message,
});
}
setIsLoading(false);
// await mutateAsync({
// email: values.email.toLowerCase(),
// password: values.password,
// })
// .then((data) => {
// if (data.is2FAEnabled) {
// setTemp(data);
// } else {
// toast.success("Successfully signed in", {
// duration: 2000,
// });
// router.push("/dashboard/projects");
// }
// })
// .catch(() => {
// toast.error("Signin failed", {
// duration: 2000,
// });
// });
};
return (
<>
@@ -111,7 +140,7 @@ export default function Home({ IS_CLOUD }: Props) {
</div>
{isError && (
<AlertBlock type="error" className="my-2">
<span>{error?.message}</span>
<span>{error}</span>
</AlertBlock>
)}
<CardContent className="p-0">
@@ -203,8 +232,7 @@ Home.getLayout = (page: ReactElement) => {
export async function getServerSideProps(context: GetServerSidePropsContext) {
if (IS_CLOUD) {
try {
const { user } = await validateRequest(context.req, context.res);
const { user } = await validateRequest(context.req);
if (user) {
return {
redirect: {
@@ -232,7 +260,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
};
}
const { user } = await validateRequest(context.req, context.res);
const { user } = await validateRequest(context.req);
if (user) {
return {

View File

@@ -17,6 +17,7 @@ import {
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth";
import { api } from "@/utils/api";
import { IS_CLOUD, isAdminPresent, validateRequest } from "@dokploy/server";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -31,6 +32,9 @@ import { z } from "zod";
const registerSchema = z
.object({
name: z.string().min(1, {
message: "Name is required",
}),
email: z
.string()
.min(1, {
@@ -79,9 +83,10 @@ const Register = ({ isCloud }: Props) => {
const form = useForm<Register>({
defaultValues: {
email: "",
password: "",
confirmPassword: "",
name: "Mauricio Siu",
email: "user5@yopmail.com",
password: "Password1234",
confirmPassword: "Password1234",
},
resolver: zodResolver(registerSchema),
});
@@ -91,19 +96,33 @@ const Register = ({ isCloud }: Props) => {
}, [form, form.reset, form.formState.isSubmitSuccessful]);
const onSubmit = async (values: Register) => {
await mutateAsync({
email: values.email.toLowerCase(),
const { data, error } = await authClient.signUp.email({
email: values.email,
password: values.password,
})
.then(() => {
toast.success("User registered successfuly", {
duration: 2000,
});
if (!isCloud) {
router.push("/");
}
})
.catch((e) => e);
name: values.name,
});
// const { data, error } = await authClient.admin.createUser({
// name: values.name,
// email: values.email,
// password: values.password,
// role: "superAdmin",
// });
// consol/e.log(data, error);
// await mutateAsync({
// email: values.email.toLowerCase(),
// password: values.password,
// })
// .then(() => {
// toast.success("User registered successfuly", {
// duration: 2000,
// });
// if (!isCloud) {
// router.push("/");
// }
// })
// .catch((e) => e);
};
return (
<div className="">
@@ -147,6 +166,19 @@ const Register = ({ isCloud }: Props) => {
className="grid gap-4"
>
<div className="space-y-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input placeholder="name" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"

View File

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

View File

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

View File

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

View File

@@ -7,6 +7,7 @@ import {
apiVerify2FA,
apiVerifyLogin2FA,
auth,
member,
} from "@/server/db/schema";
import { WEBSITE_URL } from "@/server/utils/stripe";
import {
@@ -16,22 +17,23 @@ import {
createUser,
findAuthByEmail,
findAuthById,
findUserById,
generate2FASecret,
getUserByToken,
lucia,
luciaToken,
removeAdminByAuthId,
removeUserByAuthId,
sendDiscordNotification,
sendEmailNotification,
updateAuthById,
updateUser,
validateRequest,
verify2FA,
} from "@dokploy/server";
import { TRPCError } from "@trpc/server";
import * as bcrypt from "bcrypt";
import { isBefore } from "date-fns";
import { eq } from "drizzle-orm";
import { and, eq } from "drizzle-orm";
import { nanoid } from "nanoid";
import { z } from "zod";
import { db } from "../../db";
@@ -169,8 +171,17 @@ export const authRouter = createTRPCRouter({
}),
get: protectedProcedure.query(async ({ ctx }) => {
const auth = await findAuthById(ctx.user.authId);
return auth;
const memberResult = await db.query.member.findFirst({
where: and(
eq(member.userId, ctx.user.id),
eq(member.organizationId, ctx.session?.activeOrganizationId || ""),
),
with: {
user: true,
},
});
return memberResult;
}),
logout: protectedProcedure.mutation(async ({ ctx }) => {
@@ -243,7 +254,7 @@ export const authRouter = createTRPCRouter({
await lucia.invalidateSession(session.id);
res.setHeader("Set-Cookie", lucia.createBlankSessionCookie().serialize());
if (ctx.user.rol === "admin") {
if (ctx.user.rol === "owner") {
await removeAdminByAuthId(ctx.user.authId);
} else {
await removeUserByAuthId(ctx.user.authId);
@@ -253,19 +264,18 @@ export const authRouter = createTRPCRouter({
}),
generateToken: protectedProcedure.mutation(async ({ ctx, input }) => {
const auth = await findAuthById(ctx.user.authId);
const auth = await findUserById(ctx.user.id);
console.log(auth);
if (auth.token) {
await luciaToken.invalidateSession(auth.token);
}
const session = await luciaToken.createSession(auth?.id || "", {
expiresIn: 60 * 60 * 24 * 30,
});
await updateAuthById(auth.id, {
token: session.id,
});
// const session = await luciaToken.createSession(auth?.id || "", {
// expiresIn: 60 * 60 * 24 * 30,
// });
// await updateUser(auth.id, {
// token: session.id,
// });
return auth;
}),
verifyToken: protectedProcedure.mutation(async () => {
@@ -277,7 +287,7 @@ export const authRouter = createTRPCRouter({
}),
generate2FASecret: protectedProcedure.query(async ({ ctx }) => {
return await generate2FASecret(ctx.user.authId);
return await generate2FASecret(ctx.user.id);
}),
verify2FASetup: protectedProcedure
.input(apiVerify2FA)

View File

@@ -23,7 +23,7 @@ export const bitbucketRouter = createTRPCRouter({
.input(apiCreateBitbucket)
.mutation(async ({ input, ctx }) => {
try {
return await createBitbucket(input, ctx.user.adminId);
return await createBitbucket(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -38,7 +38,7 @@ export const bitbucketRouter = createTRPCRouter({
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -61,7 +61,7 @@ export const bitbucketRouter = createTRPCRouter({
if (IS_CLOUD) {
// TODO: mAyBe a rEfaCtoR 🤫
result = result.filter(
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
(provider) => provider.gitProvider.userId === ctx.user.ownerId,
);
}
return result;
@@ -73,7 +73,7 @@ export const bitbucketRouter = createTRPCRouter({
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -91,7 +91,7 @@ export const bitbucketRouter = createTRPCRouter({
);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -108,7 +108,7 @@ export const bitbucketRouter = createTRPCRouter({
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -132,7 +132,7 @@ export const bitbucketRouter = createTRPCRouter({
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if (
IS_CLOUD &&
bitbucketProvider.gitProvider.adminId !== ctx.user.adminId
bitbucketProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -142,7 +142,7 @@ export const bitbucketRouter = createTRPCRouter({
}
return await updateBitbucket(input.bitbucketId, {
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
}),
});

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.adminId);
return await createCertificate(input, ctx.user.ownerId);
}),
one: adminProcedure
.input(apiFindCertificate)
.query(async ({ input, ctx }) => {
const certificates = await findCertificateById(input.certificateId);
if (IS_CLOUD && certificates.adminId !== ctx.user.adminId) {
if (IS_CLOUD && certificates.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this certificate",
@@ -44,7 +44,7 @@ export const certificateRouter = createTRPCRouter({
.input(apiFindCertificate)
.mutation(async ({ input, ctx }) => {
const certificates = await findCertificateById(input.certificateId);
if (IS_CLOUD && certificates.adminId !== ctx.user.adminId) {
if (IS_CLOUD && certificates.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this certificate",
@@ -56,7 +56,7 @@ export const certificateRouter = createTRPCRouter({
all: adminProcedure.query(async ({ ctx }) => {
return await db.query.certificates.findMany({
// TODO: Remove this line when the cloud version is ready
...(IS_CLOUD && { where: eq(certificates.adminId, ctx.user.adminId) }),
...(IS_CLOUD && { where: eq(certificates.userId, ctx.user.ownerId) }),
});
}),
});

View File

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

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

View File

@@ -28,7 +28,7 @@ export const destinationRouter = createTRPCRouter({
.input(apiCreateDestination)
.mutation(async ({ input, ctx }) => {
try {
return await createDestintation(input, ctx.user.adminId);
return await createDestintation(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -84,7 +84,7 @@ export const destinationRouter = createTRPCRouter({
.input(apiFindOneDestination)
.query(async ({ input, ctx }) => {
const destination = await findDestinationById(input.destinationId);
if (destination.adminId !== ctx.user.adminId) {
if (destination.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this destination",
@@ -94,7 +94,7 @@ export const destinationRouter = createTRPCRouter({
}),
all: protectedProcedure.query(async ({ ctx }) => {
return await db.query.destinations.findMany({
where: eq(destinations.adminId, ctx.user.adminId),
where: eq(destinations.userId, ctx.user.ownerId),
});
}),
remove: adminProcedure
@@ -103,7 +103,7 @@ export const destinationRouter = createTRPCRouter({
try {
const destination = await findDestinationById(input.destinationId);
if (destination.adminId !== ctx.user.adminId) {
if (destination.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this destination",
@@ -111,7 +111,7 @@ export const destinationRouter = createTRPCRouter({
}
return await removeDestinationById(
input.destinationId,
ctx.user.adminId,
ctx.user.ownerId,
);
} catch (error) {
throw error;
@@ -122,7 +122,7 @@ export const destinationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const destination = await findDestinationById(input.destinationId);
if (destination.adminId !== ctx.user.adminId) {
if (destination.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to update this destination",
@@ -130,7 +130,7 @@ export const destinationRouter = createTRPCRouter({
}
return await updateDestinationById(input.destinationId, {
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
} catch (error) {
throw error;

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.adminId !== ctx.user.adminId) {
if (compose.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -38,7 +38,7 @@ export const domainRouter = createTRPCRouter({
}
} else if (input.domainType === "application" && input.applicationId) {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
if (application.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
@@ -58,7 +58,7 @@ export const domainRouter = createTRPCRouter({
.input(apiFindOneApplication)
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
if (application.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
@@ -70,7 +70,7 @@ export const domainRouter = createTRPCRouter({
.input(apiFindCompose)
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
if (compose.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -83,7 +83,7 @@ export const domainRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
return generateTraefikMeDomain(
input.appName,
ctx.user.adminId,
ctx.user.ownerId,
input.serverId,
);
}),
@@ -95,7 +95,7 @@ export const domainRouter = createTRPCRouter({
if (currentDomain.applicationId) {
const newApp = await findApplicationById(currentDomain.applicationId);
if (newApp.project.adminId !== ctx.user.adminId) {
if (newApp.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
@@ -103,7 +103,7 @@ export const domainRouter = createTRPCRouter({
}
} else if (currentDomain.composeId) {
const newCompose = await findComposeById(currentDomain.composeId);
if (newCompose.project.adminId !== ctx.user.adminId) {
if (newCompose.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -114,7 +114,7 @@ export const domainRouter = createTRPCRouter({
currentDomain.previewDeploymentId,
);
if (
newPreviewDeployment.application.project.adminId !== ctx.user.adminId
newPreviewDeployment.application.project.userId !== ctx.user.ownerId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -143,7 +143,7 @@ export const domainRouter = createTRPCRouter({
const domain = await findDomainById(input.domainId);
if (domain.applicationId) {
const application = await findApplicationById(domain.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
if (application.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
@@ -151,7 +151,7 @@ export const domainRouter = createTRPCRouter({
}
} else if (domain.composeId) {
const compose = await findComposeById(domain.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
if (compose.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -166,7 +166,7 @@ export const domainRouter = createTRPCRouter({
const domain = await findDomainById(input.domainId);
if (domain.applicationId) {
const application = await findApplicationById(domain.applicationId);
if (application.project.adminId !== ctx.user.adminId) {
if (application.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this application",
@@ -174,7 +174,7 @@ export const domainRouter = createTRPCRouter({
}
} else if (domain.composeId) {
const compose = await findComposeById(domain.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
if (compose.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",

View File

@@ -18,7 +18,7 @@ export const gitProviderRouter = createTRPCRouter({
github: true,
},
orderBy: desc(gitProvider.createdAt),
...(IS_CLOUD && { where: eq(gitProvider.adminId, ctx.user.adminId) }),
...(IS_CLOUD && { where: eq(gitProvider.userId, ctx.user.ownerId) }),
//TODO: Remove this line when the cloud version is ready
});
}),
@@ -28,7 +28,7 @@ export const gitProviderRouter = createTRPCRouter({
try {
const gitProvider = await findGitProviderById(input.gitProviderId);
if (IS_CLOUD && gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && gitProvider.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",

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.adminId !== ctx.user.adminId) {
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -33,7 +33,7 @@ export const githubRouter = createTRPCRouter({
.input(apiFindOneGithub)
.query(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId);
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -46,7 +46,7 @@ export const githubRouter = createTRPCRouter({
.input(apiFindGithubBranches)
.query(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId || "");
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -65,7 +65,7 @@ export const githubRouter = createTRPCRouter({
if (IS_CLOUD) {
// TODO: mAyBe a rEfaCtoR 🤫
result = result.filter(
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
(provider) => provider.gitProvider.userId === ctx.user.ownerId,
);
}
@@ -90,7 +90,7 @@ export const githubRouter = createTRPCRouter({
const githubProvider = await findGithubById(input.githubId);
if (
IS_CLOUD &&
githubProvider.gitProvider.adminId !== ctx.user.adminId
githubProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -111,7 +111,7 @@ export const githubRouter = createTRPCRouter({
.input(apiUpdateGithub)
.mutation(async ({ input, ctx }) => {
const githubProvider = await findGithubById(input.githubId);
if (IS_CLOUD && githubProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && githubProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -120,7 +120,7 @@ export const githubRouter = createTRPCRouter({
}
await updateGitProvider(input.gitProviderId, {
name: input.name,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
}),
});

View File

@@ -26,7 +26,7 @@ export const gitlabRouter = createTRPCRouter({
.input(apiCreateGitlab)
.mutation(async ({ input, ctx }) => {
try {
return await createGitlab(input, ctx.user.adminId);
return await createGitlab(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -39,7 +39,7 @@ export const gitlabRouter = createTRPCRouter({
.input(apiFindOneGitlab)
.query(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId);
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -58,7 +58,7 @@ export const gitlabRouter = createTRPCRouter({
if (IS_CLOUD) {
// TODO: mAyBe a rEfaCtoR 🤫
result = result.filter(
(provider) => provider.gitProvider.adminId === ctx.user.adminId,
(provider) => provider.gitProvider.userId === ctx.user.ownerId,
);
}
const filtered = result
@@ -78,7 +78,7 @@ export const gitlabRouter = createTRPCRouter({
.input(apiFindOneGitlab)
.query(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId);
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -92,7 +92,7 @@ export const gitlabRouter = createTRPCRouter({
.input(apiFindGitlabBranches)
.query(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId || "");
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -108,7 +108,7 @@ export const gitlabRouter = createTRPCRouter({
const gitlabProvider = await findGitlabById(input.gitlabId || "");
if (
IS_CLOUD &&
gitlabProvider.gitProvider.adminId !== ctx.user.adminId
gitlabProvider.gitProvider.userId !== ctx.user.ownerId
) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
@@ -130,7 +130,7 @@ export const gitlabRouter = createTRPCRouter({
.input(apiUpdateGitlab)
.mutation(async ({ input, ctx }) => {
const gitlabProvider = await findGitlabById(input.gitlabId);
if (IS_CLOUD && gitlabProvider.gitProvider.adminId !== ctx.user.adminId) {
if (IS_CLOUD && gitlabProvider.gitProvider.userId !== ctx.user.ownerId) {
//TODO: Remove this line when the cloud version is ready
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -140,7 +140,7 @@ export const gitlabRouter = createTRPCRouter({
if (input.name) {
await updateGitProvider(input.gitProviderId, {
name: input.name,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
await updateGitlab(input.gitlabId, {

View File

@@ -37,8 +37,8 @@ export const mariadbRouter = createTRPCRouter({
.input(apiCreateMariaDB)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -49,15 +49,15 @@ export const mariadbRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.adminId !== ctx.user.adminId) {
if (project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newMariadb = await createMariadb(input);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newMariadb.mariadbId);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newMariadb.mariadbId);
}
await createMount({
@@ -79,11 +79,11 @@ export const mariadbRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneMariaDB)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mariadbId, "access");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mariadbId, "access");
}
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
if (mariadb.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this Mariadb",
@@ -96,7 +96,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiFindOneMariaDB)
.mutation(async ({ input, ctx }) => {
const service = await findMariadbById(input.mariadbId);
if (service.project.adminId !== ctx.user.adminId) {
if (service.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this Mariadb",
@@ -133,7 +133,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiSaveExternalPortMariaDB)
.mutation(async ({ input, ctx }) => {
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
@@ -149,7 +149,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiDeployMariaDB)
.mutation(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
if (mariadb.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this Mariadb",
@@ -170,7 +170,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiDeployMariaDB)
.subscription(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
if (mariadb.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this Mariadb",
@@ -187,7 +187,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiChangeMariaDBStatus)
.mutation(async ({ input, ctx }) => {
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this Mariadb status",
@@ -201,12 +201,12 @@ export const mariadbRouter = createTRPCRouter({
remove: protectedProcedure
.input(apiFindOneMariaDB)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mariadbId, "delete");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mariadbId, "delete");
}
const mongo = await findMariadbById(input.mariadbId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this Mariadb",
@@ -232,7 +232,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiSaveEnvironmentVariablesMariaDB)
.mutation(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
if (mariadb.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
@@ -255,7 +255,7 @@ export const mariadbRouter = createTRPCRouter({
.input(apiResetMariadb)
.mutation(async ({ input, ctx }) => {
const mariadb = await findMariadbById(input.mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
if (mariadb.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this Mariadb",
@@ -285,7 +285,7 @@ export const mariadbRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const { mariadbId, ...rest } = input;
const mariadb = await findMariadbById(mariadbId);
if (mariadb.project.adminId !== ctx.user.adminId) {
if (mariadb.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this Mariadb",

View File

@@ -36,8 +36,8 @@ export const mongoRouter = createTRPCRouter({
.input(apiCreateMongo)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -48,15 +48,15 @@ export const mongoRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.adminId !== ctx.user.adminId) {
if (project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newMongo = await createMongo(input);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newMongo.mongoId);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newMongo.mongoId);
}
await createMount({
@@ -82,12 +82,12 @@ export const mongoRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneMongo)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mongoId, "access");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mongoId, "access");
}
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this mongo",
@@ -101,7 +101,7 @@ export const mongoRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const service = await findMongoById(input.mongoId);
if (service.project.adminId !== ctx.user.adminId) {
if (service.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this mongo",
@@ -124,7 +124,7 @@ export const mongoRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this mongo",
@@ -146,7 +146,7 @@ export const mongoRouter = createTRPCRouter({
.input(apiSaveExternalPortMongo)
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
@@ -162,7 +162,7 @@ export const mongoRouter = createTRPCRouter({
.input(apiDeployMongo)
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this mongo",
@@ -182,7 +182,7 @@ export const mongoRouter = createTRPCRouter({
.input(apiDeployMongo)
.subscription(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this mongo",
@@ -199,7 +199,7 @@ export const mongoRouter = createTRPCRouter({
.input(apiChangeMongoStatus)
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this mongo status",
@@ -214,7 +214,7 @@ export const mongoRouter = createTRPCRouter({
.input(apiResetMongo)
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this mongo",
@@ -242,13 +242,13 @@ export const mongoRouter = createTRPCRouter({
remove: protectedProcedure
.input(apiFindOneMongo)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mongoId, "delete");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mongoId, "delete");
}
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this mongo",
@@ -274,7 +274,7 @@ export const mongoRouter = createTRPCRouter({
.input(apiSaveEnvironmentVariablesMongo)
.mutation(async ({ input, ctx }) => {
const mongo = await findMongoById(input.mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
@@ -298,7 +298,7 @@ export const mongoRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const { mongoId, ...rest } = input;
const mongo = await findMongoById(mongoId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this mongo",

View File

@@ -38,8 +38,8 @@ export const mysqlRouter = createTRPCRouter({
.input(apiCreateMySql)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -50,7 +50,7 @@ export const mysqlRouter = createTRPCRouter({
}
1;
const project = await findProjectById(input.projectId);
if (project.adminId !== ctx.user.adminId) {
if (project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
@@ -58,8 +58,8 @@ export const mysqlRouter = createTRPCRouter({
}
const newMysql = await createMysql(input);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newMysql.mysqlId);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newMysql.mysqlId);
}
await createMount({
@@ -85,11 +85,11 @@ export const mysqlRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneMySql)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mysqlId, "access");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mysqlId, "access");
}
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
if (mysql.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this MySQL",
@@ -102,7 +102,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiFindOneMySql)
.mutation(async ({ input, ctx }) => {
const service = await findMySqlById(input.mysqlId);
if (service.project.adminId !== ctx.user.adminId) {
if (service.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this MySQL",
@@ -124,7 +124,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiFindOneMySql)
.mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this MySQL",
@@ -145,7 +145,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiSaveExternalPortMySql)
.mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
@@ -161,7 +161,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiDeployMySql)
.mutation(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
if (mysql.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this MySQL",
@@ -181,7 +181,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiDeployMySql)
.subscription(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
if (mysql.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this MySQL",
@@ -198,7 +198,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiChangeMySqlStatus)
.mutation(async ({ input, ctx }) => {
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this MySQL status",
@@ -213,7 +213,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiResetMysql)
.mutation(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
if (mysql.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this MySQL",
@@ -240,11 +240,11 @@ export const mysqlRouter = createTRPCRouter({
remove: protectedProcedure
.input(apiFindOneMySql)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.mysqlId, "delete");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.mysqlId, "delete");
}
const mongo = await findMySqlById(input.mysqlId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this MySQL",
@@ -270,7 +270,7 @@ export const mysqlRouter = createTRPCRouter({
.input(apiSaveEnvironmentVariablesMySql)
.mutation(async ({ input, ctx }) => {
const mysql = await findMySqlById(input.mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
if (mysql.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
@@ -294,7 +294,7 @@ export const mysqlRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const { mysqlId, ...rest } = input;
const mysql = await findMySqlById(mysqlId);
if (mysql.project.adminId !== ctx.user.adminId) {
if (mysql.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this MySQL",

View File

@@ -6,7 +6,6 @@ import {
} from "@/server/api/trpc";
import { db } from "@/server/db";
import {
admins,
apiCreateDiscord,
apiCreateEmail,
apiCreateGotify,
@@ -25,6 +24,7 @@ import {
apiUpdateTelegram,
notifications,
server,
users_temp,
} from "@/server/db/schema";
import {
IS_CLOUD,
@@ -57,7 +57,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiCreateSlack)
.mutation(async ({ input, ctx }) => {
try {
return await createSlackNotification(input, ctx.user.adminId);
return await createSlackNotification(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -71,7 +71,7 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -80,7 +80,7 @@ export const notificationRouter = createTRPCRouter({
}
return await updateSlackNotification({
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
} catch (error) {
throw error;
@@ -107,7 +107,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiCreateTelegram)
.mutation(async ({ input, ctx }) => {
try {
return await createTelegramNotification(input, ctx.user.adminId);
return await createTelegramNotification(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -122,7 +122,7 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -131,7 +131,7 @@ export const notificationRouter = createTRPCRouter({
}
return await updateTelegramNotification({
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
} catch (error) {
throw new TRPCError({
@@ -159,7 +159,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiCreateDiscord)
.mutation(async ({ input, ctx }) => {
try {
return await createDiscordNotification(input, ctx.user.adminId);
return await createDiscordNotification(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -174,7 +174,7 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -183,7 +183,7 @@ export const notificationRouter = createTRPCRouter({
}
return await updateDiscordNotification({
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
} catch (error) {
throw new TRPCError({
@@ -220,7 +220,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiCreateEmail)
.mutation(async ({ input, ctx }) => {
try {
return await createEmailNotification(input, ctx.user.adminId);
return await createEmailNotification(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -234,7 +234,7 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -243,7 +243,7 @@ export const notificationRouter = createTRPCRouter({
}
return await updateEmailNotification({
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
} catch (error) {
throw new TRPCError({
@@ -276,7 +276,7 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -295,7 +295,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiFindOneNotification)
.query(async ({ input, ctx }) => {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
// TODO: Remove isCloud in the next versions of dokploy
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -314,7 +314,7 @@ export const notificationRouter = createTRPCRouter({
gotify: true,
},
orderBy: desc(notifications.createdAt),
...(IS_CLOUD && { where: eq(notifications.adminId, ctx.user.adminId) }),
...(IS_CLOUD && { where: eq(notifications.userId, ctx.user.ownerId) }),
// TODO: Remove this line when the cloud version is ready
});
}),
@@ -332,24 +332,24 @@ export const notificationRouter = createTRPCRouter({
)
.mutation(async ({ input }) => {
try {
let adminId = "";
let userId = "";
let ServerName = "";
if (input.ServerType === "Dokploy") {
const result = await db
.select()
.from(admins)
.from(users_temp)
.where(
sql`${admins.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
sql`${users_temp.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
);
if (!result?.[0]?.adminId) {
if (!result?.[0]?.id) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Token not found",
});
}
adminId = result?.[0]?.adminId;
userId = result?.[0]?.id;
ServerName = "Dokploy";
} else {
const result = await db
@@ -359,18 +359,18 @@ export const notificationRouter = createTRPCRouter({
sql`${server.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
);
if (!result?.[0]?.adminId) {
if (!result?.[0]?.userId) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Token not found",
});
}
adminId = result?.[0]?.adminId;
userId = result?.[0]?.userId;
ServerName = "Remote";
}
await sendServerThresholdNotifications(adminId, {
await sendServerThresholdNotifications(userId, {
...input,
ServerName,
});
@@ -386,7 +386,7 @@ export const notificationRouter = createTRPCRouter({
.input(apiCreateGotify)
.mutation(async ({ input, ctx }) => {
try {
return await createGotifyNotification(input, ctx.user.adminId);
return await createGotifyNotification(input, ctx.user.ownerId);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -400,7 +400,7 @@ export const notificationRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
try {
const notification = await findNotificationById(input.notificationId);
if (IS_CLOUD && notification.adminId !== ctx.user.adminId) {
if (IS_CLOUD && notification.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this notification",
@@ -408,7 +408,7 @@ export const notificationRouter = createTRPCRouter({
}
return await updateGotifyNotification({
...input,
adminId: ctx.user.adminId,
userId: ctx.user.ownerId,
});
} catch (error) {
throw error;

View File

@@ -44,8 +44,8 @@ export const postgresRouter = createTRPCRouter({
.input(apiCreatePostgres)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -56,15 +56,15 @@ export const postgresRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.adminId !== ctx.user.adminId) {
if (project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newPostgres = await createPostgres(input);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newPostgres.postgresId);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newPostgres.postgresId);
}
await createMount({
@@ -90,12 +90,12 @@ export const postgresRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOnePostgres)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.postgresId, "access");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.postgresId, "access");
}
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this Postgres",
@@ -109,7 +109,7 @@ export const postgresRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const service = await findPostgresById(input.postgresId);
if (service.project.adminId !== ctx.user.adminId) {
if (service.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this Postgres",
@@ -131,7 +131,7 @@ export const postgresRouter = createTRPCRouter({
.input(apiFindOnePostgres)
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this Postgres",
@@ -153,7 +153,7 @@ export const postgresRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
@@ -169,7 +169,7 @@ export const postgresRouter = createTRPCRouter({
.input(apiDeployPostgres)
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this Postgres",
@@ -190,7 +190,7 @@ export const postgresRouter = createTRPCRouter({
.input(apiDeployPostgres)
.subscription(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this Postgres",
@@ -207,7 +207,7 @@ export const postgresRouter = createTRPCRouter({
.input(apiChangePostgresStatus)
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this Postgres status",
@@ -221,12 +221,12 @@ export const postgresRouter = createTRPCRouter({
remove: protectedProcedure
.input(apiFindOnePostgres)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.postgresId, "delete");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.postgresId, "delete");
}
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this Postgres",
@@ -249,7 +249,7 @@ export const postgresRouter = createTRPCRouter({
.input(apiSaveEnvironmentVariablesPostgres)
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",
@@ -272,7 +272,7 @@ export const postgresRouter = createTRPCRouter({
.input(apiResetPostgres)
.mutation(async ({ input, ctx }) => {
const postgres = await findPostgresById(input.postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this Postgres",
@@ -302,7 +302,7 @@ export const postgresRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const { postgresId, ...rest } = input;
const postgres = await findPostgresById(postgresId);
if (postgres.project.adminId !== ctx.user.adminId) {
if (postgres.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to update this Postgres",

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

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

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

View File

@@ -36,8 +36,8 @@ export const redisRouter = createTRPCRouter({
.input(apiCreateRedis)
.mutation(async ({ input, ctx }) => {
try {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.projectId, "create");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.projectId, "create");
}
if (IS_CLOUD && !input.serverId) {
@@ -48,15 +48,15 @@ export const redisRouter = createTRPCRouter({
}
const project = await findProjectById(input.projectId);
if (project.adminId !== ctx.user.adminId) {
if (project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this project",
});
}
const newRedis = await createRedis(input);
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, newRedis.redisId);
if (ctx.user.rol === "member") {
await addNewService(ctx.user.id, newRedis.redisId);
}
await createMount({
@@ -75,12 +75,12 @@ export const redisRouter = createTRPCRouter({
one: protectedProcedure
.input(apiFindOneRedis)
.query(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.redisId, "access");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.redisId, "access");
}
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this Redis",
@@ -93,7 +93,7 @@ export const redisRouter = createTRPCRouter({
.input(apiFindOneRedis)
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to start this Redis",
@@ -115,7 +115,7 @@ export const redisRouter = createTRPCRouter({
.input(apiResetRedis)
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to reload this Redis",
@@ -145,7 +145,7 @@ export const redisRouter = createTRPCRouter({
.input(apiFindOneRedis)
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this Redis",
@@ -166,7 +166,7 @@ export const redisRouter = createTRPCRouter({
.input(apiSaveExternalPortRedis)
.mutation(async ({ input, ctx }) => {
const mongo = await findRedisById(input.redisId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this external port",
@@ -182,7 +182,7 @@ export const redisRouter = createTRPCRouter({
.input(apiDeployRedis)
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this Redis",
@@ -202,7 +202,7 @@ export const redisRouter = createTRPCRouter({
.input(apiDeployRedis)
.subscription(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to deploy this Redis",
@@ -218,7 +218,7 @@ export const redisRouter = createTRPCRouter({
.input(apiChangeRedisStatus)
.mutation(async ({ input, ctx }) => {
const mongo = await findRedisById(input.redisId);
if (mongo.project.adminId !== ctx.user.adminId) {
if (mongo.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to change this Redis status",
@@ -232,13 +232,13 @@ export const redisRouter = createTRPCRouter({
remove: protectedProcedure
.input(apiFindOneRedis)
.mutation(async ({ input, ctx }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.authId, input.redisId, "delete");
if (ctx.user.rol === "member") {
await checkServiceAccess(ctx.user.id, input.redisId, "delete");
}
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to delete this Redis",
@@ -261,7 +261,7 @@ export const redisRouter = createTRPCRouter({
.input(apiSaveEnvironmentVariablesRedis)
.mutation(async ({ input, ctx }) => {
const redis = await findRedisById(input.redisId);
if (redis.project.adminId !== ctx.user.adminId) {
if (redis.project.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to save this environment",

View File

@@ -10,7 +10,7 @@ import {
createRegistry,
execAsync,
execAsyncRemote,
findAllRegistryByAdminId,
findAllRegistryByUserId,
findRegistryById,
removeRegistry,
updateRegistry,
@@ -22,13 +22,13 @@ export const registryRouter = createTRPCRouter({
create: adminProcedure
.input(apiCreateRegistry)
.mutation(async ({ ctx, input }) => {
return await createRegistry(input, ctx.user.adminId);
return await createRegistry(input, ctx.user.ownerId);
}),
remove: adminProcedure
.input(apiRemoveRegistry)
.mutation(async ({ ctx, input }) => {
const registry = await findRegistryById(input.registryId);
if (registry.adminId !== ctx.user.adminId) {
if (registry.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to delete this registry",
@@ -41,7 +41,7 @@ export const registryRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const { registryId, ...rest } = input;
const registry = await findRegistryById(registryId);
if (registry.adminId !== ctx.user.adminId) {
if (registry.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to update this registry",
@@ -61,13 +61,13 @@ export const registryRouter = createTRPCRouter({
return true;
}),
all: protectedProcedure.query(async ({ ctx }) => {
return await findAllRegistryByAdminId(ctx.user.adminId);
return await findAllRegistryByUserId(ctx.user.ownerId);
}),
one: adminProcedure
.input(apiFindOneRegistry)
.query(async ({ input, ctx }) => {
const registry = await findRegistryById(input.registryId);
if (registry.adminId !== ctx.user.adminId) {
if (registry.userId !== ctx.user.ownerId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not allowed to access this registry",

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,9 @@
import { WEBSITE_URL, getStripeItems } from "@/server/utils/stripe";
import {
IS_CLOUD,
findAdminById,
findServersByAdminId,
updateAdmin,
findServersByUserId,
findUserById,
updateUser,
} from "@dokploy/server";
import { TRPCError } from "@trpc/server";
import Stripe from "stripe";
@@ -12,8 +12,8 @@ import { adminProcedure, createTRPCRouter } from "../trpc";
export const stripeRouter = createTRPCRouter({
getProducts: adminProcedure.query(async ({ ctx }) => {
const admin = await findAdminById(ctx.user.adminId);
const stripeCustomerId = admin.stripeCustomerId;
const user = await findUserById(ctx.user.ownerId);
const stripeCustomerId = user.stripeCustomerId;
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-09-30.acacia",
@@ -56,15 +56,15 @@ export const stripeRouter = createTRPCRouter({
});
const items = getStripeItems(input.serverQuantity, input.isAnnual);
const admin = await findAdminById(ctx.user.adminId);
const user = await findUserById(ctx.user.ownerId);
let stripeCustomerId = admin.stripeCustomerId;
let stripeCustomerId = user.stripeCustomerId;
if (stripeCustomerId) {
const customer = await stripe.customers.retrieve(stripeCustomerId);
if (customer.deleted) {
await updateAdmin(admin.authId, {
await updateUser(user.id, {
stripeCustomerId: null,
});
stripeCustomerId = null;
@@ -78,7 +78,7 @@ export const stripeRouter = createTRPCRouter({
customer: stripeCustomerId,
}),
metadata: {
adminId: admin.adminId,
ownerId: user.id,
},
allow_promotion_codes: true,
success_url: `${WEBSITE_URL}/dashboard/settings/servers?success=true`,
@@ -89,15 +89,15 @@ export const stripeRouter = createTRPCRouter({
}),
createCustomerPortalSession: adminProcedure.mutation(
async ({ ctx, input }) => {
const admin = await findAdminById(ctx.user.adminId);
const user = await findUserById(ctx.user.ownerId);
if (!admin.stripeCustomerId) {
if (!user.stripeCustomerId) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Stripe Customer ID not found",
});
}
const stripeCustomerId = admin.stripeCustomerId;
const stripeCustomerId = user.stripeCustomerId;
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-09-30.acacia",
@@ -119,13 +119,13 @@ export const stripeRouter = createTRPCRouter({
),
canCreateMoreServers: adminProcedure.query(async ({ ctx }) => {
const admin = await findAdminById(ctx.user.adminId);
const servers = await findServersByAdminId(admin.adminId);
const user = await findUserById(ctx.user.ownerId);
const servers = await findServersByUserId(user.id);
if (!IS_CLOUD) {
return true;
}
return servers.length < admin.serversQuantity;
return servers.length < user.serversQuantity;
}),
});

View File

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

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,96 @@
import {
boolean,
integer,
pgTable,
text,
timestamp,
} from "drizzle-orm/pg-core";
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified").notNull(),
image: text("image"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
});
export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id),
activeOrganizationId: text("active_organization_id"),
});
export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
});
export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at"),
updatedAt: timestamp("updated_at"),
});
export const organization = pgTable("organization", {
id: text("id").primaryKey(),
name: text("name").notNull(),
slug: text("slug").unique(),
logo: text("logo"),
createdAt: timestamp("created_at").notNull(),
metadata: text("metadata"),
ownerId: text("owner_id")
.notNull()
.references(() => user.userId),
});
export const member = pgTable("member", {
id: text("id").primaryKey(),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id),
userId: text("user_id")
.notNull()
.references(() => user.userId),
role: text("role").notNull(),
createdAt: timestamp("created_at").notNull(),
});
export const invitation = pgTable("invitation", {
id: text("id").primaryKey(),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id),
email: text("email").notNull(),
role: text("role"),
status: text("status").notNull(),
expiresAt: timestamp("expires_at").notNull(),
inviterId: text("inviter_id")
.notNull()
.references(() => user.userId),
});

View File

@@ -28,6 +28,10 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@oslojs/encoding":"1.1.0",
"@oslojs/crypto":"1.0.1",
"drizzle-dbml-generator":"0.10.0",
"better-auth":"1.1.16",
"rotating-file-stream": "3.2.3",
"@faker-js/faker": "^8.4.1",
"@lucia-auth/adapter-drizzle": "1.0.7",

View File

@@ -6,9 +6,9 @@ import { TimeSpan } from "lucia";
import { Lucia } from "lucia/dist/core.js";
import type { Session, User } from "lucia/dist/core.js";
import { db } from "../db";
import { type DatabaseUser, auth, sessionTable } from "../db/schema";
import { type DatabaseUser, auth, session } from "../db/schema";
export const adapter = new DrizzlePostgreSQLAdapter(db, sessionTable, auth);
export const adapter = new DrizzlePostgreSQLAdapter(db, session, auth);
export const lucia = new Lucia(adapter, {
sessionCookie: {
@@ -16,6 +16,7 @@ export const lucia = new Lucia(adapter, {
secure: false,
},
},
sessionExpiresIn: new TimeSpan(1, "d"),
getUserAttributes: (attributes) => {
return {
@@ -46,6 +47,7 @@ export async function validateRequest(
req: IncomingMessage,
res: ServerResponse,
): ReturnValidateToken {
console.log(session);
const sessionId = lucia.readSessionCookie(req.headers.cookie ?? "");
if (!sessionId) {
@@ -69,10 +71,10 @@ export async function validateRequest(
}
if (result.user) {
try {
if (result.user?.rol === "admin") {
if (result.user?.rol === "owner") {
const admin = await findAdminByAuthId(result.user.id);
result.user.adminId = admin.adminId;
} else if (result.user?.rol === "user") {
} else if (result.user?.rol === "member") {
const userResult = await findUserByAuthId(result.user.id);
result.user.adminId = userResult.adminId;
}

View File

@@ -35,10 +35,10 @@ export const validateBearerToken = async (
const result = await luciaToken.validateSession(sessionId);
if (result.user) {
if (result.user?.rol === "admin") {
if (result.user?.rol === "owner") {
const admin = await findAdminByAuthId(result.user.id);
result.user.adminId = admin.adminId;
} else if (result.user?.rol === "user") {
} else if (result.user?.rol === "member") {
const userResult = await findUserByAuthId(result.user.id);
result.user.adminId = userResult.adminId;
}
@@ -73,10 +73,10 @@ export const validateBearerTokenAPI = async (
const result = await luciaToken.validateSession(sessionId);
if (result.user) {
if (result.user?.rol === "admin") {
if (result.user?.rol === "owner") {
const admin = await findAdminByAuthId(result.user.id);
result.user.adminId = admin.adminId;
} else if (result.user?.rol === "user") {
} else if (result.user?.rol === "member") {
const userResult = await findUserByAuthId(result.user.id);
result.user.adminId = userResult.adminId;
}

View File

@@ -0,0 +1,114 @@
import { relations } from "drizzle-orm";
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { nanoid } from "nanoid";
import { users_temp } from "./user";
export const account = pgTable("account", {
id: text("id")
.primaryKey()
.$defaultFn(() => nanoid()),
accountId: text("account_id")
.notNull()
.$defaultFn(() => nanoid()),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
is2FAEnabled: boolean("is2FAEnabled").notNull().default(false),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
resetPasswordToken: text("resetPasswordToken"),
resetPasswordExpiresAt: text("resetPasswordExpiresAt"),
confirmationToken: text("confirmationToken"),
confirmationExpiresAt: text("confirmationExpiresAt"),
});
export const accountRelations = relations(account, ({ one }) => ({
user: one(users_temp, {
fields: [account.userId],
references: [users_temp.id],
}),
}));
export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at"),
updatedAt: timestamp("updated_at"),
});
export const organization = pgTable("organization", {
id: text("id")
.primaryKey()
.$defaultFn(() => nanoid()),
name: text("name").notNull(),
slug: text("slug").unique(),
logo: text("logo"),
createdAt: timestamp("created_at").notNull(),
metadata: text("metadata"),
ownerId: text("owner_id")
.notNull()
.references(() => users_temp.id),
});
export const organizationRelations = relations(organization, ({ one }) => ({
owner: one(users_temp, {
fields: [organization.ownerId],
references: [users_temp.id],
}),
}));
export const member = pgTable("member", {
id: text("id")
.primaryKey()
.$defaultFn(() => nanoid()),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id),
userId: text("user_id")
.notNull()
.references(() => users_temp.id),
role: text("role").notNull().$type<"owner" | "member" | "admin">(),
createdAt: timestamp("created_at").notNull(),
});
export const memberRelations = relations(member, ({ one }) => ({
organization: one(organization, {
fields: [member.organizationId],
references: [organization.id],
}),
user: one(users_temp, {
fields: [member.userId],
references: [users_temp.id],
}),
}));
export const invitation = pgTable("invitation", {
id: text("id").primaryKey(),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id),
email: text("email").notNull(),
role: text("role").$type<"owner" | "member" | "admin">(),
status: text("status").notNull(),
expiresAt: timestamp("expires_at").notNull(),
inviterId: text("inviter_id")
.notNull()
.references(() => users_temp.id),
});
export const invitationRelations = relations(invitation, ({ one }) => ({
organization: one(organization, {
fields: [invitation.organizationId],
references: [organization.id],
}),
}));

View File

@@ -4,7 +4,7 @@ import { boolean, pgEnum, pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
// import { admins } from "./admin";
import { users } from "./user";
const randomImages = [
@@ -55,7 +55,7 @@ export const auth = pgTable("auth", {
});
export const authRelations = relations(auth, ({ many }) => ({
admins: many(admins),
// admins: many(admins),
users: many(users),
}));
const createSchema = createInsertSchema(auth, {

View File

@@ -61,5 +61,5 @@ export const apiUpdateBitbucket = createSchema.extend({
name: z.string().min(1),
bitbucketUsername: z.string().optional(),
bitbucketWorkspaceName: z.string().optional(),
adminId: z.string().optional(),
userId: z.string().optional(),
});

View File

@@ -5,6 +5,8 @@ import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
import { server } from "./server";
import { users_temp } from "./user";
// import { user } from "./user";
import { generateAppName } from "./utils";
export const certificates = pgTable("certificate", {
@@ -20,9 +22,12 @@ export const certificates = pgTable("certificate", {
.$defaultFn(() => generateAppName("certificate"))
.unique(),
autoRenew: boolean("autoRenew"),
adminId: text("adminId").references(() => admins.adminId, {
onDelete: "cascade",
}),
// userId: text("userId").references(() => user.userId, {
// onDelete: "cascade",
// }),
userId: text("userId")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
@@ -35,9 +40,9 @@ export const certificatesRelations = relations(
fields: [certificates.serverId],
references: [server.serverId],
}),
admin: one(admins, {
fields: [certificates.adminId],
references: [admins.adminId],
user: one(users_temp, {
fields: [certificates.userId],
references: [users_temp.id],
}),
}),
);

View File

@@ -0,0 +1,7 @@
import { pgGenerate } from "drizzle-dbml-generator"; // Using Postgres for this example
import * as schema from "./index";
const out = "./schema.dbml";
const relational = true;
pgGenerate({ schema, out, relational });

View File

@@ -5,6 +5,8 @@ import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
import { backups } from "./backups";
import { users_temp } from "./user";
// import { user } from "./user";
export const destinations = pgTable("destination", {
destinationId: text("destinationId")
@@ -19,19 +21,22 @@ export const destinations = pgTable("destination", {
region: text("region").notNull(),
// maybe it can be null
endpoint: text("endpoint").notNull(),
adminId: text("adminId")
// userId: text("userId")
// .notNull()
// .references(() => user.userId, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.references(() => admins.adminId, { onDelete: "cascade" }),
.references(() => users_temp.id, { onDelete: "cascade" }),
});
export const destinationsRelations = relations(
destinations,
({ many, one }) => ({
backups: many(backups),
admin: one(admins, {
fields: [destinations.adminId],
references: [admins.adminId],
}),
// user: one(user, {
// fields: [destinations.userId],
// references: [user.id],
// }),
}),
);

View File

@@ -7,6 +7,8 @@ import { admins } from "./admin";
import { bitbucket } from "./bitbucket";
import { github } from "./github";
import { gitlab } from "./gitlab";
import { users_temp } from "./user";
// import { user } from "./user";
export const gitProviderType = pgEnum("gitProviderType", [
"github",
@@ -24,9 +26,12 @@ export const gitProvider = pgTable("git_provider", {
createdAt: text("createdAt")
.notNull()
.$defaultFn(() => new Date().toISOString()),
adminId: text("adminId").references(() => admins.adminId, {
onDelete: "cascade",
}),
// userId: text("userId").references(() => user.userId, {
// onDelete: "cascade",
// }),
userId: text("userId")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
});
export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
@@ -42,9 +47,9 @@ export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
fields: [gitProvider.gitProviderId],
references: [bitbucket.gitProviderId],
}),
admin: one(admins, {
fields: [gitProvider.adminId],
references: [admins.adminId],
user: one(users_temp, {
fields: [gitProvider.userId],
references: [users_temp.id],
}),
}));

View File

@@ -30,3 +30,4 @@ export * from "./gitlab";
export * from "./server";
export * from "./utils";
export * from "./preview-deployments";
export * from "./account";

View File

@@ -3,7 +3,8 @@ import { boolean, integer, pgEnum, pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
import { users_temp } from "./user";
// import { user } from "./user";
export const notificationType = pgEnum("notificationType", [
"slack",
@@ -44,9 +45,12 @@ export const notifications = pgTable("notification", {
gotifyId: text("gotifyId").references(() => gotify.gotifyId, {
onDelete: "cascade",
}),
adminId: text("adminId").references(() => admins.adminId, {
onDelete: "cascade",
}),
// userId: text("userId").references(() => user.userId, {
// onDelete: "cascade",
// }),
userId: text("userId")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
});
export const slack = pgTable("slack", {
@@ -121,9 +125,9 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({
fields: [notifications.gotifyId],
references: [gotify.gotifyId],
}),
admin: one(admins, {
fields: [notifications.adminId],
references: [admins.adminId],
user: one(users_temp, {
fields: [notifications.userId],
references: [users_temp.id],
}),
}));
@@ -148,7 +152,7 @@ export const apiCreateSlack = notificationsSchema
export const apiUpdateSlack = apiCreateSlack.partial().extend({
notificationId: z.string().min(1),
slackId: z.string(),
adminId: z.string().optional(),
userId: z.string().optional(),
});
export const apiTestSlackConnection = apiCreateSlack.pick({
@@ -175,7 +179,7 @@ export const apiCreateTelegram = notificationsSchema
export const apiUpdateTelegram = apiCreateTelegram.partial().extend({
notificationId: z.string().min(1),
telegramId: z.string().min(1),
adminId: z.string().optional(),
userId: z.string().optional(),
});
export const apiTestTelegramConnection = apiCreateTelegram.pick({
@@ -202,7 +206,7 @@ export const apiCreateDiscord = notificationsSchema
export const apiUpdateDiscord = apiCreateDiscord.partial().extend({
notificationId: z.string().min(1),
discordId: z.string().min(1),
adminId: z.string().optional(),
userId: z.string().optional(),
});
export const apiTestDiscordConnection = apiCreateDiscord
@@ -236,7 +240,7 @@ export const apiCreateEmail = notificationsSchema
export const apiUpdateEmail = apiCreateEmail.partial().extend({
notificationId: z.string().min(1),
emailId: z.string().min(1),
adminId: z.string().optional(),
userId: z.string().optional(),
});
export const apiTestEmailConnection = apiCreateEmail.pick({
@@ -268,7 +272,7 @@ export const apiCreateGotify = notificationsSchema
export const apiUpdateGotify = apiCreateGotify.partial().extend({
notificationId: z.string().min(1),
gotifyId: z.string().min(1),
adminId: z.string().optional(),
userId: z.string().optional(),
});
export const apiTestGotifyConnection = apiCreateGotify

View File

@@ -5,6 +5,7 @@ import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
// import { admins } from "./admin";
import { applications } from "./application";
import { compose } from "./compose";
import { mariadb } from "./mariadb";
@@ -12,6 +13,7 @@ import { mongo } from "./mongo";
import { mysql } from "./mysql";
import { postgres } from "./postgres";
import { redis } from "./redis";
import { users, users_temp } from "./user";
export const projects = pgTable("project", {
projectId: text("projectId")
@@ -23,9 +25,12 @@ export const projects = pgTable("project", {
createdAt: text("createdAt")
.notNull()
.$defaultFn(() => new Date().toISOString()),
adminId: text("adminId")
// userId: text("userId")
// .notNull()
// .references(() => user.userId, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.references(() => admins.adminId, { onDelete: "cascade" }),
.references(() => users_temp.id, { onDelete: "cascade" }),
env: text("env").notNull().default(""),
});
@@ -37,10 +42,10 @@ export const projectRelations = relations(projects, ({ many, one }) => ({
mongo: many(mongo),
redis: many(redis),
compose: many(compose),
admin: one(admins, {
fields: [projects.adminId],
references: [admins.adminId],
}),
// user: one(user, {
// fields: [projects.userId],
// references: [user.id],
// }),
}));
const createSchema = createInsertSchema(projects, {

View File

@@ -5,6 +5,8 @@ import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
import { applications } from "./application";
import { users_temp } from "./user";
// import { user } from "./user";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
@@ -27,16 +29,19 @@ export const registry = pgTable("registry", {
.notNull()
.$defaultFn(() => new Date().toISOString()),
registryType: registryType("selfHosted").notNull().default("cloud"),
adminId: text("adminId")
// userId: text("userId")
// .notNull()
// .references(() => user.userId, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.references(() => admins.adminId, { onDelete: "cascade" }),
.references(() => users_temp.id, { onDelete: "cascade" }),
});
export const registryRelations = relations(registry, ({ one, many }) => ({
admin: one(admins, {
fields: [registry.adminId],
references: [admins.adminId],
}),
// user: one(user, {
// fields: [registry.userId],
// references: [user.id],
// }),
applications: many(applications),
}));
@@ -45,7 +50,7 @@ const createSchema = createInsertSchema(registry, {
username: z.string().min(1),
password: z.string().min(1),
registryUrl: z.string(),
adminId: z.string().min(1),
userId: z.string().min(1),
registryId: z.string().min(1),
registryType: z.enum(["cloud"]),
imagePrefix: z.string().nullable().optional(),

View File

@@ -0,0 +1,872 @@
enum applicationStatus {
idle
running
done
error
}
enum buildType {
dockerfile
heroku_buildpacks
paketo_buildpacks
nixpacks
static
}
enum certificateType {
letsencrypt
none
}
enum composeType {
"docker-compose"
stack
}
enum databaseType {
postgres
mariadb
mysql
mongo
}
enum deploymentStatus {
running
done
error
}
enum domainType {
compose
application
preview
}
enum gitProviderType {
github
gitlab
bitbucket
}
enum mountType {
bind
volume
file
}
enum notificationType {
slack
telegram
discord
email
gotify
}
enum protocolType {
tcp
udp
}
enum RegistryType {
selfHosted
cloud
}
enum Roles {
admin
user
}
enum serverStatus {
active
inactive
}
enum serviceType {
application
postgres
mysql
mariadb
mongo
redis
compose
}
enum sourceType {
docker
git
github
gitlab
bitbucket
drop
}
enum sourceTypeCompose {
git
github
gitlab
bitbucket
raw
}
table account {
id text [pk, not null]
account_id text [not null]
provider_id text [not null]
user_id text [not null]
access_token text
refresh_token text
id_token text
access_token_expires_at timestamp
refresh_token_expires_at timestamp
scope text
password text
is2FAEnabled boolean [not null, default: false]
created_at timestamp [not null]
updated_at timestamp [not null]
resetPasswordToken text
resetPasswordExpiresAt text
confirmationToken text
confirmationExpiresAt text
}
table admin {
}
table application {
applicationId text [pk, not null]
name text [not null]
appName text [not null, unique]
description text
env text
previewEnv text
previewBuildArgs text
previewWildcard text
previewPort integer [default: 3000]
previewHttps boolean [not null, default: false]
previewPath text [default: '/']
certificateType certificateType [not null, default: 'none']
previewLimit integer [default: 3]
isPreviewDeploymentsActive boolean [default: false]
buildArgs text
memoryReservation text
memoryLimit text
cpuReservation text
cpuLimit text
title text
enabled boolean
subtitle text
command text
refreshToken text
sourceType sourceType [not null, default: 'github']
repository text
owner text
branch text
buildPath text [default: '/']
autoDeploy boolean
gitlabProjectId integer
gitlabRepository text
gitlabOwner text
gitlabBranch text
gitlabBuildPath text [default: '/']
gitlabPathNamespace text
bitbucketRepository text
bitbucketOwner text
bitbucketBranch text
bitbucketBuildPath text [default: '/']
username text
password text
dockerImage text
registryUrl text
customGitUrl text
customGitBranch text
customGitBuildPath text
customGitSSHKeyId text
dockerfile text
dockerContextPath text
dockerBuildStage text
dropBuildPath text
healthCheckSwarm json
restartPolicySwarm json
placementSwarm json
updateConfigSwarm json
rollbackConfigSwarm json
modeSwarm json
labelsSwarm json
networkSwarm json
replicas integer [not null, default: 1]
applicationStatus applicationStatus [not null, default: 'idle']
buildType buildType [not null, default: 'nixpacks']
herokuVersion text [default: '24']
publishDirectory text
createdAt text [not null]
registryId text
projectId text [not null]
githubId text
gitlabId text
bitbucketId text
serverId text
}
table auth {
id text [pk, not null]
email text [not null, unique]
password text [not null]
rol Roles [not null]
image text
secret text
token text
is2FAEnabled boolean [not null, default: false]
createdAt text [not null]
resetPasswordToken text
resetPasswordExpiresAt text
confirmationToken text
confirmationExpiresAt text
}
table backup {
backupId text [pk, not null]
schedule text [not null]
enabled boolean
database text [not null]
prefix text [not null]
destinationId text [not null]
databaseType databaseType [not null]
postgresId text
mariadbId text
mysqlId text
mongoId text
}
table bitbucket {
bitbucketId text [pk, not null]
bitbucketUsername text
appPassword text
bitbucketWorkspaceName text
gitProviderId text [not null]
}
table certificate {
certificateId text [pk, not null]
name text [not null]
certificateData text [not null]
privateKey text [not null]
certificatePath text [not null, unique]
autoRenew boolean
userId text
serverId text
}
table compose {
composeId text [pk, not null]
name text [not null]
appName text [not null]
description text
env text
composeFile text [not null, default: '']
refreshToken text
sourceType sourceTypeCompose [not null, default: 'github']
composeType composeType [not null, default: 'docker-compose']
repository text
owner text
branch text
autoDeploy boolean
gitlabProjectId integer
gitlabRepository text
gitlabOwner text
gitlabBranch text
gitlabPathNamespace text
bitbucketRepository text
bitbucketOwner text
bitbucketBranch text
customGitUrl text
customGitBranch text
customGitSSHKeyId text
command text [not null, default: '']
composePath text [not null, default: './docker-compose.yml']
suffix text [not null, default: '']
randomize boolean [not null, default: false]
isolatedDeployment boolean [not null, default: false]
composeStatus applicationStatus [not null, default: 'idle']
projectId text [not null]
createdAt text [not null]
githubId text
gitlabId text
bitbucketId text
serverId text
}
table deployment {
deploymentId text [pk, not null]
title text [not null]
description text
status deploymentStatus [default: 'running']
logPath text [not null]
applicationId text
composeId text
serverId text
isPreviewDeployment boolean [default: false]
previewDeploymentId text
createdAt text [not null]
errorMessage text
}
table destination {
destinationId text [pk, not null]
name text [not null]
provider text
accessKey text [not null]
secretAccessKey text [not null]
bucket text [not null]
region text [not null]
endpoint text [not null]
userId text [not null]
}
table discord {
discordId text [pk, not null]
webhookUrl text [not null]
decoration boolean
}
table domain {
domainId text [pk, not null]
host text [not null]
https boolean [not null, default: false]
port integer [default: 3000]
path text [default: '/']
serviceName text
domainType domainType [default: 'application']
uniqueConfigKey serial [not null, increment]
createdAt text [not null]
composeId text
applicationId text
previewDeploymentId text
certificateType certificateType [not null, default: 'none']
}
table email {
emailId text [pk, not null]
smtpServer text [not null]
smtpPort integer [not null]
username text [not null]
password text [not null]
fromAddress text [not null]
toAddress text[] [not null]
}
table git_provider {
gitProviderId text [pk, not null]
name text [not null]
providerType gitProviderType [not null, default: 'github']
createdAt text [not null]
userId text
}
table github {
githubId text [pk, not null]
githubAppName text
githubAppId integer
githubClientId text
githubClientSecret text
githubInstallationId text
githubPrivateKey text
githubWebhookSecret text
gitProviderId text [not null]
}
table gitlab {
gitlabId text [pk, not null]
gitlabUrl text [not null, default: 'https://gitlab.com']
application_id text
redirect_uri text
secret text
access_token text
refresh_token text
group_name text
expires_at integer
gitProviderId text [not null]
}
table gotify {
gotifyId text [pk, not null]
serverUrl text [not null]
appToken text [not null]
priority integer [not null, default: 5]
decoration boolean
}
table invitation {
id text [pk, not null]
organization_id text [not null]
email text [not null]
role text
status text [not null]
expires_at timestamp [not null]
inviter_id text [not null]
}
table mariadb {
mariadbId text [pk, not null]
name text [not null]
appName text [not null, unique]
description text
databaseName text [not null]
databaseUser text [not null]
databasePassword text [not null]
rootPassword text [not null]
dockerImage text [not null]
command text
env text
memoryReservation text
memoryLimit text
cpuReservation text
cpuLimit text
externalPort integer
applicationStatus applicationStatus [not null, default: 'idle']
createdAt text [not null]
projectId text [not null]
serverId text
}
table member {
id text [pk, not null]
organization_id text [not null]
user_id text [not null]
role text [not null]
created_at timestamp [not null]
}
table mongo {
mongoId text [pk, not null]
name text [not null]
appName text [not null, unique]
description text
databaseUser text [not null]
databasePassword text [not null]
dockerImage text [not null]
command text
env text
memoryReservation text
memoryLimit text
cpuReservation text
cpuLimit text
externalPort integer
applicationStatus applicationStatus [not null, default: 'idle']
createdAt text [not null]
projectId text [not null]
serverId text
replicaSets boolean [default: false]
}
table mount {
mountId text [pk, not null]
type mountType [not null]
hostPath text
volumeName text
filePath text
content text
serviceType serviceType [not null, default: 'application']
mountPath text [not null]
applicationId text
postgresId text
mariadbId text
mongoId text
mysqlId text
redisId text
composeId text
}
table mysql {
mysqlId text [pk, not null]
name text [not null]
appName text [not null, unique]
description text
databaseName text [not null]
databaseUser text [not null]
databasePassword text [not null]
rootPassword text [not null]
dockerImage text [not null]
command text
env text
memoryReservation text
memoryLimit text
cpuReservation text
cpuLimit text
externalPort integer
applicationStatus applicationStatus [not null, default: 'idle']
createdAt text [not null]
projectId text [not null]
serverId text
}
table notification {
notificationId text [pk, not null]
name text [not null]
appDeploy boolean [not null, default: false]
appBuildError boolean [not null, default: false]
databaseBackup boolean [not null, default: false]
dokployRestart boolean [not null, default: false]
dockerCleanup boolean [not null, default: false]
serverThreshold boolean [not null, default: false]
notificationType notificationType [not null]
createdAt text [not null]
slackId text
telegramId text
discordId text
emailId text
gotifyId text
userId text
}
table organization {
id text [pk, not null]
name text [not null]
slug text [unique]
logo text
created_at timestamp [not null]
metadata text
owner_id text [not null]
}
table port {
portId text [pk, not null]
publishedPort integer [not null]
targetPort integer [not null]
protocol protocolType [not null]
applicationId text [not null]
}
table postgres {
postgresId text [pk, not null]
name text [not null]
appName text [not null, unique]
databaseName text [not null]
databaseUser text [not null]
databasePassword text [not null]
description text
dockerImage text [not null]
command text
env text
memoryReservation text
externalPort integer
memoryLimit text
cpuReservation text
cpuLimit text
applicationStatus applicationStatus [not null, default: 'idle']
createdAt text [not null]
projectId text [not null]
serverId text
}
table preview_deployments {
previewDeploymentId text [pk, not null]
branch text [not null]
pullRequestId text [not null]
pullRequestNumber text [not null]
pullRequestURL text [not null]
pullRequestTitle text [not null]
pullRequestCommentId text [not null]
previewStatus applicationStatus [not null, default: 'idle']
appName text [not null, unique]
applicationId text [not null]
domainId text
createdAt text [not null]
expiresAt text
}
table project {
projectId text [pk, not null]
name text [not null]
description text
createdAt text [not null]
userId text [not null]
env text [not null, default: '']
}
table redirect {
redirectId text [pk, not null]
regex text [not null]
replacement text [not null]
permanent boolean [not null, default: false]
uniqueConfigKey serial [not null, increment]
createdAt text [not null]
applicationId text [not null]
}
table redis {
redisId text [pk, not null]
name text [not null]
appName text [not null, unique]
description text
password text [not null]
dockerImage text [not null]
command text
env text
memoryReservation text
memoryLimit text
cpuReservation text
cpuLimit text
externalPort integer
createdAt text [not null]
applicationStatus applicationStatus [not null, default: 'idle']
projectId text [not null]
serverId text
}
table registry {
registryId text [pk, not null]
registryName text [not null]
imagePrefix text
username text [not null]
password text [not null]
registryUrl text [not null, default: '']
createdAt text [not null]
selfHosted RegistryType [not null, default: 'cloud']
userId text [not null]
}
table security {
securityId text [pk, not null]
username text [not null]
password text [not null]
createdAt text [not null]
applicationId text [not null]
indexes {
(username, applicationId) [name: 'security_username_applicationId_unique', unique]
}
}
table server {
serverId text [pk, not null]
name text [not null]
description text
ipAddress text [not null]
port integer [not null]
username text [not null, default: 'root']
appName text [not null]
enableDockerCleanup boolean [not null, default: false]
createdAt text [not null]
userId text [not null]
serverStatus serverStatus [not null, default: 'active']
command text [not null, default: '']
sshKeyId text
metricsConfig jsonb [not null, default: `{"server":{"type":"Remote","refreshRate":60,"port":4500,"token":"","urlCallback":"","cronJob":"","retentionDays":2,"thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}`]
}
table session {
id text [pk, not null]
expires_at timestamp [not null]
token text [not null, unique]
created_at timestamp [not null]
updated_at timestamp [not null]
ip_address text
user_agent text
user_id text [not null]
impersonated_by text
active_organization_id text
}
table slack {
slackId text [pk, not null]
webhookUrl text [not null]
channel text
}
table "ssh-key" {
sshKeyId text [pk, not null]
privateKey text [not null, default: '']
publicKey text [not null]
name text [not null]
description text
createdAt text [not null]
lastUsedAt text
userId text
}
table telegram {
telegramId text [pk, not null]
botToken text [not null]
chatId text [not null]
}
table user {
id text [pk, not null]
name text [not null, default: '']
token text [not null]
isRegistered boolean [not null, default: false]
expirationDate text [not null]
createdAt text [not null]
canCreateProjects boolean [not null, default: false]
canAccessToSSHKeys boolean [not null, default: false]
canCreateServices boolean [not null, default: false]
canDeleteProjects boolean [not null, default: false]
canDeleteServices boolean [not null, default: false]
canAccessToDocker boolean [not null, default: false]
canAccessToAPI boolean [not null, default: false]
canAccessToGitProviders boolean [not null, default: false]
canAccessToTraefikFiles boolean [not null, default: false]
accesedProjects text[] [not null, default: `ARRAY[]::text[]`]
accesedServices text[] [not null, default: `ARRAY[]::text[]`]
email text [not null, unique]
email_verified boolean [not null]
image text
role text
banned boolean
ban_reason text
ban_expires timestamp
updated_at timestamp [not null]
serverIp text
certificateType certificateType [not null, default: 'none']
host text
letsEncryptEmail text
sshPrivateKey text
enableDockerCleanup boolean [not null, default: false]
enableLogRotation boolean [not null, default: false]
enablePaidFeatures boolean [not null, default: false]
metricsConfig jsonb [not null, default: `{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}`]
cleanupCacheApplications boolean [not null, default: false]
cleanupCacheOnPreviews boolean [not null, default: false]
cleanupCacheOnCompose boolean [not null, default: false]
stripeCustomerId text
stripeSubscriptionId text
serversQuantity integer [not null, default: 0]
}
table verification {
id text [pk, not null]
identifier text [not null]
value text [not null]
expires_at timestamp [not null]
created_at timestamp
updated_at timestamp
}
ref: mount.applicationId > application.applicationId
ref: mount.postgresId > postgres.postgresId
ref: mount.mariadbId > mariadb.mariadbId
ref: mount.mongoId > mongo.mongoId
ref: mount.mysqlId > mysql.mysqlId
ref: mount.redisId > redis.redisId
ref: mount.composeId > compose.composeId
ref: application.projectId > project.projectId
ref: application.customGitSSHKeyId > "ssh-key".sshKeyId
ref: application.registryId > registry.registryId
ref: application.githubId - github.githubId
ref: application.gitlabId - gitlab.gitlabId
ref: application.bitbucketId - bitbucket.bitbucketId
ref: application.serverId > server.serverId
ref: backup.destinationId > destination.destinationId
ref: backup.postgresId > postgres.postgresId
ref: backup.mariadbId > mariadb.mariadbId
ref: backup.mysqlId > mysql.mysqlId
ref: backup.mongoId > mongo.mongoId
ref: git_provider.gitProviderId - bitbucket.gitProviderId
ref: certificate.serverId > server.serverId
ref: certificate.userId - user.id
ref: compose.projectId > project.projectId
ref: compose.customGitSSHKeyId > "ssh-key".sshKeyId
ref: compose.githubId - github.githubId
ref: compose.gitlabId - gitlab.gitlabId
ref: compose.bitbucketId - bitbucket.bitbucketId
ref: compose.serverId > server.serverId
ref: deployment.applicationId > application.applicationId
ref: deployment.composeId > compose.composeId
ref: deployment.serverId > server.serverId
ref: deployment.previewDeploymentId > preview_deployments.previewDeploymentId
ref: destination.userId - user.id
ref: domain.applicationId > application.applicationId
ref: domain.composeId > compose.composeId
ref: preview_deployments.domainId - domain.domainId
ref: github.gitProviderId - git_provider.gitProviderId
ref: gitlab.gitProviderId - git_provider.gitProviderId
ref: git_provider.userId - user.id
ref: mariadb.projectId > project.projectId
ref: mariadb.serverId > server.serverId
ref: mongo.projectId > project.projectId
ref: mongo.serverId > server.serverId
ref: mysql.projectId > project.projectId
ref: mysql.serverId > server.serverId
ref: notification.slackId - slack.slackId
ref: notification.telegramId - telegram.telegramId
ref: notification.discordId - discord.discordId
ref: notification.emailId - email.emailId
ref: notification.gotifyId - gotify.gotifyId
ref: notification.userId - user.id
ref: port.applicationId > application.applicationId
ref: postgres.projectId > project.projectId
ref: postgres.serverId > server.serverId
ref: preview_deployments.applicationId > application.applicationId
ref: project.userId - user.id
ref: redirect.applicationId > application.applicationId
ref: redis.projectId > project.projectId
ref: redis.serverId > server.serverId
ref: registry.userId - user.id
ref: security.applicationId > application.applicationId
ref: server.userId - user.id
ref: server.sshKeyId > "ssh-key".sshKeyId
ref: "ssh-key".userId - user.id

View File

@@ -22,6 +22,8 @@ import { mysql } from "./mysql";
import { postgres } from "./postgres";
import { redis } from "./redis";
import { sshKeys } from "./ssh-key";
import { users_temp } from "./user";
// import { user } from "./user";
import { generateAppName } from "./utils";
export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]);
@@ -40,12 +42,14 @@ export const server = pgTable("server", {
.notNull()
.$defaultFn(() => generateAppName("server")),
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
createdAt: text("createdAt")
createdAt: text("createdAt").notNull(),
// .$defaultFn(() => new Date().toISOString()),
// userId: text("userId")
// .notNull()
// .references(() => user.userId, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.$defaultFn(() => new Date().toISOString()),
adminId: text("adminId")
.notNull()
.references(() => admins.adminId, { onDelete: "cascade" }),
.references(() => users_temp.id, { onDelete: "cascade" }),
serverStatus: serverStatus("serverStatus").notNull().default("active"),
command: text("command").notNull().default(""),
sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, {
@@ -100,10 +104,10 @@ export const server = pgTable("server", {
});
export const serverRelations = relations(server, ({ one, many }) => ({
admin: one(admins, {
fields: [server.adminId],
references: [admins.adminId],
}),
// user: one(user, {
// fields: [server.userId],
// references: [user.id],
// }),
deployments: many(deployments),
sshKey: one(sshKeys, {
fields: [server.sshKeyId],

View File

@@ -1,5 +1,23 @@
import { sql } from "drizzle-orm";
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { auth } from "./auth";
import { users_temp } from "./user";
// OLD TABLE
export const session = pgTable("session_temp", {
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => users_temp.id),
impersonatedBy: text("impersonated_by"),
activeOrganizationId: text("active_organization_id"),
});
export const sessionTable = pgTable("session", {
id: text("id").primaryKey(),

View File

@@ -7,6 +7,8 @@ import { admins } from "./admin";
import { applications } from "./application";
import { compose } from "./compose";
import { server } from "./server";
import { users_temp } from "./user";
// import { user } from "./user";
export const sshKeys = pgTable("ssh-key", {
sshKeyId: text("sshKeyId")
@@ -21,18 +23,21 @@ export const sshKeys = pgTable("ssh-key", {
.notNull()
.$defaultFn(() => new Date().toISOString()),
lastUsedAt: text("lastUsedAt"),
adminId: text("adminId").references(() => admins.adminId, {
onDelete: "cascade",
}),
// userId: text("userId").references(() => user.userId, {
// onDelete: "cascade",
// }),
userId: text("userId")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
});
export const sshKeysRelations = relations(sshKeys, ({ many, one }) => ({
applications: many(applications),
compose: many(compose),
servers: many(server),
admin: one(admins, {
fields: [sshKeys.adminId],
references: [admins.adminId],
user: one(users_temp, {
fields: [sshKeys.userId],
references: [users_temp.id],
}),
}));
@@ -48,7 +53,7 @@ export const apiCreateSshKey = createSchema
description: true,
privateKey: true,
publicKey: true,
adminId: true,
userId: true,
})
.merge(sshKeyCreate.pick({ privateKey: true }));

View File

@@ -1,10 +1,19 @@
import { relations, sql } from "drizzle-orm";
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
import {
boolean,
integer,
jsonb,
pgTable,
text,
timestamp,
} from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { account, organization } from "./account";
import { admins } from "./admin";
import { auth } from "./auth";
import { certificateType } from "./shared";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
@@ -12,6 +21,8 @@ import { auth } from "./auth";
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
// OLD TABLE
export const users = pgTable("user", {
userId: text("userId")
.notNull()
@@ -56,23 +67,146 @@ export const users = pgTable("user", {
.references(() => auth.id, { onDelete: "cascade" }),
});
export const usersRelations = relations(users, ({ one }) => ({
auth: one(auth, {
fields: [users.authId],
references: [auth.id],
}),
admin: one(admins, {
fields: [users.adminId],
references: [admins.adminId],
// TEMP
export const users_temp = pgTable("user_temp", {
id: text("id")
.notNull()
.primaryKey()
.$defaultFn(() => nanoid()),
name: text("name").notNull().default(""),
token: text("token").notNull().default(""),
isRegistered: boolean("isRegistered").notNull().default(false),
expirationDate: text("expirationDate")
.notNull()
.$defaultFn(() => new Date().toISOString()),
createdAt2: text("createdAt")
.notNull()
.$defaultFn(() => new Date().toISOString()),
createdAt: timestamp("created_at").defaultNow(),
canCreateProjects: boolean("canCreateProjects").notNull().default(false),
canAccessToSSHKeys: boolean("canAccessToSSHKeys").notNull().default(false),
canCreateServices: boolean("canCreateServices").notNull().default(false),
canDeleteProjects: boolean("canDeleteProjects").notNull().default(false),
canDeleteServices: boolean("canDeleteServices").notNull().default(false),
canAccessToDocker: boolean("canAccessToDocker").notNull().default(false),
canAccessToAPI: boolean("canAccessToAPI").notNull().default(false),
canAccessToGitProviders: boolean("canAccessToGitProviders")
.notNull()
.default(false),
canAccessToTraefikFiles: boolean("canAccessToTraefikFiles")
.notNull()
.default(false),
accessedProjects: text("accesedProjects")
.array()
.notNull()
.default(sql`ARRAY[]::text[]`),
accessedServices: text("accesedServices")
.array()
.notNull()
.default(sql`ARRAY[]::text[]`),
// authId: text("authId")
// .notNull()
// .references(() => auth.id, { onDelete: "cascade" }),
// Auth
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified").notNull(),
image: text("image"),
banned: boolean("banned"),
banReason: text("ban_reason"),
banExpires: timestamp("ban_expires"),
updatedAt: timestamp("updated_at").notNull(),
// Admin
serverIp: text("serverIp"),
certificateType: certificateType("certificateType").notNull().default("none"),
host: text("host"),
letsEncryptEmail: text("letsEncryptEmail"),
sshPrivateKey: text("sshPrivateKey"),
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
enableLogRotation: boolean("enableLogRotation").notNull().default(false),
// Metrics
enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false),
metricsConfig: jsonb("metricsConfig")
.$type<{
server: {
type: "Dokploy" | "Remote";
refreshRate: number;
port: number;
token: string;
urlCallback: string;
retentionDays: number;
cronJob: string;
thresholds: {
cpu: number;
memory: number;
};
};
containers: {
refreshRate: number;
services: {
include: string[];
exclude: string[];
};
};
}>()
.notNull()
.default({
server: {
type: "Dokploy",
refreshRate: 60,
port: 4500,
token: "",
retentionDays: 2,
cronJob: "",
urlCallback: "",
thresholds: {
cpu: 0,
memory: 0,
},
},
containers: {
refreshRate: 60,
services: {
include: [],
exclude: [],
},
},
}),
cleanupCacheApplications: boolean("cleanupCacheApplications")
.notNull()
.default(false),
cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews")
.notNull()
.default(false),
cleanupCacheOnCompose: boolean("cleanupCacheOnCompose")
.notNull()
.default(false),
stripeCustomerId: text("stripeCustomerId"),
stripeSubscriptionId: text("stripeSubscriptionId"),
serversQuantity: integer("serversQuantity").notNull().default(0),
});
export const usersRelations = relations(users_temp, ({ one, many }) => ({
// auth: one(auth, {
// fields: [users.authId],
// references: [auth.id],
// }),
account: one(account, {
fields: [users_temp.id],
references: [account.userId],
}),
organizations: many(organization),
// admin: one(admins, {
// fields: [users.adminId],
// references: [admins.adminId],
// }),
}));
const createSchema = createInsertSchema(users, {
userId: z.string().min(1),
authId: z.string().min(1),
const createSchema = createInsertSchema(users_temp, {
id: z.string().min(1),
// authId: z.string().min(1),
token: z.string().min(1),
isRegistered: z.boolean().optional(),
adminId: z.string(),
// adminId: z.string(),
accessedProjects: z.array(z.string()).optional(),
accessedServices: z.array(z.string()).optional(),
canCreateProjects: z.boolean().optional(),
@@ -89,7 +223,7 @@ export const apiCreateUserInvitation = createSchema.pick({}).extend({
export const apiRemoveUser = createSchema
.pick({
authId: true,
id: true,
})
.required();
@@ -101,7 +235,7 @@ export const apiFindOneToken = createSchema
export const apiAssignPermissions = createSchema
.pick({
userId: true,
id: true,
canCreateProjects: true,
canCreateServices: true,
canDeleteProjects: true,
@@ -118,12 +252,12 @@ export const apiAssignPermissions = createSchema
export const apiFindOneUser = createSchema
.pick({
userId: true,
id: true,
})
.required();
export const apiFindOneUserByAuth = createSchema
.pick({
authId: true,
// authId: true,
})
.required();

View File

@@ -118,3 +118,5 @@ export * from "./monitoring/utils";
export * from "./db/validations/domain";
export * from "./db/validations/index";
export * from "./utils/gpu-setup";
export * from "./lib/auth";

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