mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor: filter by adminId
This commit is contained in:
6
apps/dokploy/drizzle/0039_workable_speed_demon.sql
Normal file
6
apps/dokploy/drizzle/0039_workable_speed_demon.sql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE "ssh-key" ADD COLUMN "adminId" text;--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "ssh-key" ADD CONSTRAINT "ssh-key_adminId_admin_adminId_fk" FOREIGN KEY ("adminId") REFERENCES "public"."admin"("adminId") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
3850
apps/dokploy/drizzle/meta/0039_snapshot.json
Normal file
3850
apps/dokploy/drizzle/meta/0039_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -274,6 +274,13 @@
|
|||||||
"when": 1727903587684,
|
"when": 1727903587684,
|
||||||
"tag": "0038_mushy_blindfold",
|
"tag": "0038_mushy_blindfold",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 39,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1727937385754,
|
||||||
|
"tag": "0039_workable_speed_demon",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -179,13 +179,11 @@ export default function Home({ hasAdmin }: Props) {
|
|||||||
)}
|
)}
|
||||||
<div className="flex flex-row justify-between flex-wrap">
|
<div className="flex flex-row justify-between flex-wrap">
|
||||||
<div className="mt-4 text-center text-sm flex flex-row justify-center gap-2">
|
<div className="mt-4 text-center text-sm flex flex-row justify-center gap-2">
|
||||||
Need help?
|
|
||||||
<Link
|
<Link
|
||||||
className="underline"
|
className="hover:underline text-muted-foreground"
|
||||||
href="https://dokploy.com"
|
href="/register"
|
||||||
target="_blank"
|
|
||||||
>
|
>
|
||||||
Contact us
|
Create an account
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { isAdminPresent } from "@dokploy/builders";
|
import { IS_CLOUD, isAdminPresent } from "@dokploy/builders";
|
||||||
// import { IS_CLOUD } from "@/server/constants";
|
// import { IS_CLOUD } from "@/server/constants";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
@@ -67,9 +67,10 @@ type Register = z.infer<typeof registerSchema>;
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
hasAdmin: boolean;
|
hasAdmin: boolean;
|
||||||
|
isCloud: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Register = ({ hasAdmin }: Props) => {
|
const Register = ({ hasAdmin, isCloud }: Props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { mutateAsync, error, isError } = api.auth.createAdmin.useMutation();
|
const { mutateAsync, error, isError } = api.auth.createAdmin.useMutation();
|
||||||
|
|
||||||
@@ -112,9 +113,12 @@ const Register = ({ hasAdmin }: Props) => {
|
|||||||
<span className="font-medium text-sm">Dokploy</span>
|
<span className="font-medium text-sm">Dokploy</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<CardTitle className="text-2xl font-bold">Setup the server</CardTitle>
|
<CardTitle className="text-2xl font-bold">
|
||||||
|
{isCloud ? "Create an account" : "Setup the server"}
|
||||||
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Enter your email and password to setup the server
|
Enter your email and password to{" "}
|
||||||
|
{isCloud ? "create an account" : "setup the server"}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
<Card className="mx-auto w-full max-w-lg bg-transparent">
|
<Card className="mx-auto w-full max-w-lg bg-transparent">
|
||||||
<div className="p-3" />
|
<div className="p-3" />
|
||||||
@@ -192,24 +196,26 @@ const Register = ({ hasAdmin }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
{hasAdmin && (
|
<div className="flex flex-row justify-between flex-wrap">
|
||||||
<div className="mt-4 text-center text-sm">
|
{isCloud && (
|
||||||
Already have account?
|
<div className="mt-4 text-center text-sm flex gap-2">
|
||||||
<Link className="underline" href="/">
|
Already have account?
|
||||||
Sign in
|
<Link className="underline" href="/">
|
||||||
|
Sign in
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-4 text-center text-sm flex flex-row justify-center gap-2">
|
||||||
|
Need help?
|
||||||
|
<Link
|
||||||
|
className="underline"
|
||||||
|
href="https://dokploy.com"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Contact us
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="mt-4 text-center text-sm flex flex-row justify-center gap-2">
|
|
||||||
Need help?
|
|
||||||
<Link
|
|
||||||
className="underline"
|
|
||||||
href="https://dokploy.com"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Contact us
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -221,11 +227,13 @@ const Register = ({ hasAdmin }: Props) => {
|
|||||||
|
|
||||||
export default Register;
|
export default Register;
|
||||||
export async function getServerSideProps() {
|
export async function getServerSideProps() {
|
||||||
// if (IS_CLOUD) {
|
if (IS_CLOUD) {
|
||||||
// return {
|
return {
|
||||||
// props: {},
|
props: {
|
||||||
// };
|
isCloud: true,
|
||||||
// }
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
const hasAdmin = await isAdminPresent();
|
const hasAdmin = await isAdminPresent();
|
||||||
|
|
||||||
if (hasAdmin) {
|
if (hasAdmin) {
|
||||||
@@ -239,6 +247,7 @@ export async function getServerSideProps() {
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
hasAdmin,
|
hasAdmin,
|
||||||
|
isCloud: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
lucia,
|
lucia,
|
||||||
validateRequest,
|
validateRequest,
|
||||||
luciaToken,
|
luciaToken,
|
||||||
|
IS_CLOUD,
|
||||||
} from "@dokploy/builders";
|
} from "@dokploy/builders";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
@@ -36,15 +37,15 @@ export const authRouter = createTRPCRouter({
|
|||||||
.input(apiCreateAdmin)
|
.input(apiCreateAdmin)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
try {
|
try {
|
||||||
// if (!IS_CLOUD) {
|
if (!IS_CLOUD) {
|
||||||
const admin = await db.query.admins.findFirst({});
|
const admin = await db.query.admins.findFirst({});
|
||||||
if (admin) {
|
if (admin) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: "Admin already exists",
|
message: "Admin already exists",
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
const newAdmin = await createAdmin(input);
|
const newAdmin = await createAdmin(input);
|
||||||
const session = await lucia.createSession(newAdmin.id || "", {});
|
const session = await lucia.createSession(newAdmin.id || "", {});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
apiGenerateSSHKey,
|
apiGenerateSSHKey,
|
||||||
apiRemoveSshKey,
|
apiRemoveSshKey,
|
||||||
apiUpdateSshKey,
|
apiUpdateSshKey,
|
||||||
|
sshKeys,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import {
|
import {
|
||||||
@@ -15,13 +16,17 @@ import {
|
|||||||
removeSSHKeyById,
|
removeSSHKeyById,
|
||||||
updateSSHKeyById,
|
updateSSHKeyById,
|
||||||
} from "@dokploy/builders";
|
} from "@dokploy/builders";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
export const sshRouter = createTRPCRouter({
|
export const sshRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateSshKey)
|
.input(apiCreateSshKey)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
try {
|
try {
|
||||||
await createSshKey(input);
|
await createSshKey({
|
||||||
|
...input,
|
||||||
|
adminId: ctx.user.adminId,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
@@ -46,8 +51,10 @@ export const sshRouter = createTRPCRouter({
|
|||||||
const sshKey = await findSSHKeyById(input.sshKeyId);
|
const sshKey = await findSSHKeyById(input.sshKeyId);
|
||||||
return sshKey;
|
return sshKey;
|
||||||
}),
|
}),
|
||||||
all: protectedProcedure.query(async () => {
|
all: protectedProcedure.query(async ({ ctx }) => {
|
||||||
return await db.query.sshKeys.findMany({});
|
return await db.query.sshKeys.findMany({
|
||||||
|
where: eq(sshKeys.adminId, ctx.user.adminId),
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
generate: protectedProcedure
|
generate: protectedProcedure
|
||||||
.input(apiGenerateSSHKey)
|
.input(apiGenerateSSHKey)
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
|
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
|
||||||
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
|
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
|
||||||
|
|
||||||
import { findUserByAuthId, findUserById, findUsers } from "@dokploy/builders";
|
import { findUserByAuthId, findUserById, findUsers } from "@dokploy/builders";
|
||||||
|
|
||||||
export const userRouter = createTRPCRouter({
|
export const userRouter = createTRPCRouter({
|
||||||
all: adminProcedure.query(async () => {
|
all: adminProcedure.query(async ({ ctx }) => {
|
||||||
return await findUsers();
|
return await findUsers(ctx.user.adminId);
|
||||||
}),
|
}),
|
||||||
byAuthId: protectedProcedure
|
byAuthId: protectedProcedure
|
||||||
.input(apiFindOneUserByAuth)
|
.input(apiFindOneUserByAuth)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { auth } from "./auth";
|
|||||||
import { registry } from "./registry";
|
import { registry } from "./registry";
|
||||||
import { certificateType } from "./shared";
|
import { certificateType } from "./shared";
|
||||||
import { users } from "./user";
|
import { users } from "./user";
|
||||||
|
import { sshKeys } from "./ssh-key";
|
||||||
|
|
||||||
export const admins = pgTable("admin", {
|
export const admins = pgTable("admin", {
|
||||||
adminId: text("adminId")
|
adminId: text("adminId")
|
||||||
@@ -35,6 +36,7 @@ export const adminsRelations = relations(admins, ({ one, many }) => ({
|
|||||||
}),
|
}),
|
||||||
users: many(users),
|
users: many(users),
|
||||||
registry: many(registry),
|
registry: many(registry),
|
||||||
|
sshKeys: many(sshKeys),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const createSchema = createInsertSchema(admins, {
|
const createSchema = createInsertSchema(admins, {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { pgTable, text } from "drizzle-orm/pg-core";
|
|||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { server } from "./server";
|
import { server } from "./server";
|
||||||
|
import { admins } from "./admin";
|
||||||
|
|
||||||
export const sshKeys = pgTable("ssh-key", {
|
export const sshKeys = pgTable("ssh-key", {
|
||||||
sshKeyId: text("sshKeyId")
|
sshKeyId: text("sshKeyId")
|
||||||
@@ -20,12 +21,19 @@ export const sshKeys = pgTable("ssh-key", {
|
|||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
lastUsedAt: text("lastUsedAt"),
|
lastUsedAt: text("lastUsedAt"),
|
||||||
|
adminId: text("adminId").references(() => admins.adminId, {
|
||||||
|
onDelete: "cascade",
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const sshKeysRelations = relations(sshKeys, ({ many }) => ({
|
export const sshKeysRelations = relations(sshKeys, ({ many, one }) => ({
|
||||||
applications: many(applications),
|
applications: many(applications),
|
||||||
compose: many(compose),
|
compose: many(compose),
|
||||||
servers: many(server),
|
servers: many(server),
|
||||||
|
admin: one(admins, {
|
||||||
|
fields: [sshKeys.adminId],
|
||||||
|
references: [admins.adminId],
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const createSchema = createInsertSchema(
|
const createSchema = createInsertSchema(
|
||||||
@@ -40,6 +48,7 @@ export const apiCreateSshKey = createSchema
|
|||||||
description: true,
|
description: true,
|
||||||
privateKey: true,
|
privateKey: true,
|
||||||
publicKey: true,
|
publicKey: true,
|
||||||
|
adminId: true,
|
||||||
})
|
})
|
||||||
.merge(sshKeyCreate.pick({ privateKey: true }));
|
.merge(sshKeyCreate.pick({ privateKey: true }));
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ export const findUserByAuthId = async (authId: string) => {
|
|||||||
return user;
|
return user;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const findUsers = async () => {
|
export const findUsers = async (adminId: string) => {
|
||||||
const users = await db.query.users.findMany({
|
const currentUsers = await db.query.users.findMany({
|
||||||
|
where: eq(users.adminId, adminId),
|
||||||
with: {
|
with: {
|
||||||
auth: {
|
auth: {
|
||||||
columns: {
|
columns: {
|
||||||
@@ -44,7 +45,7 @@ export const findUsers = async () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return users;
|
return currentUsers;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addNewProject = async (authId: string, projectId: string) => {
|
export const addNewProject = async (authId: string, projectId: string) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user