refactor: filter by adminId

This commit is contained in:
Mauricio Siu
2024-10-03 00:45:46 -06:00
parent 600f4b2106
commit 5c72e5a452
11 changed files with 3938 additions and 49 deletions

View 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 $$;

File diff suppressed because it is too large Load Diff

View File

@@ -274,6 +274,13 @@
"when": 1727903587684,
"tag": "0038_mushy_blindfold",
"breakpoints": true
},
{
"idx": 39,
"version": "6",
"when": 1727937385754,
"tag": "0039_workable_speed_demon",
"breakpoints": true
}
]
}

View File

@@ -179,13 +179,11 @@ export default function Home({ hasAdmin }: Props) {
)}
<div className="flex flex-row justify-between flex-wrap">
<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"
className="hover:underline text-muted-foreground"
href="/register"
>
Contact us
Create an account
</Link>
</div>

View File

@@ -15,7 +15,7 @@ import {
FormMessage,
} from "@/components/ui/form";
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 { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -67,9 +67,10 @@ type Register = z.infer<typeof registerSchema>;
interface Props {
hasAdmin: boolean;
isCloud: boolean;
}
const Register = ({ hasAdmin }: Props) => {
const Register = ({ hasAdmin, isCloud }: Props) => {
const router = useRouter();
const { mutateAsync, error, isError } = api.auth.createAdmin.useMutation();
@@ -112,9 +113,12 @@ const Register = ({ hasAdmin }: Props) => {
<span className="font-medium text-sm">Dokploy</span>
</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>
Enter your email and password to setup the server
Enter your email and password to{" "}
{isCloud ? "create an account" : "setup the server"}
</CardDescription>
<Card className="mx-auto w-full max-w-lg bg-transparent">
<div className="p-3" />
@@ -192,24 +196,26 @@ const Register = ({ hasAdmin }: Props) => {
</div>
</form>
</Form>
{hasAdmin && (
<div className="mt-4 text-center text-sm">
Already have account?
<Link className="underline" href="/">
Sign in
<div className="flex flex-row justify-between flex-wrap">
{isCloud && (
<div className="mt-4 text-center text-sm flex gap-2">
Already have account?
<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>
</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>
</CardContent>
</Card>
@@ -221,11 +227,13 @@ const Register = ({ hasAdmin }: Props) => {
export default Register;
export async function getServerSideProps() {
// if (IS_CLOUD) {
// return {
// props: {},
// };
// }
if (IS_CLOUD) {
return {
props: {
isCloud: true,
},
};
}
const hasAdmin = await isAdminPresent();
if (hasAdmin) {
@@ -239,6 +247,7 @@ export async function getServerSideProps() {
return {
props: {
hasAdmin,
isCloud: false,
},
};
}

View File

@@ -23,6 +23,7 @@ import {
lucia,
validateRequest,
luciaToken,
IS_CLOUD,
} from "@dokploy/builders";
import {
adminProcedure,
@@ -36,15 +37,15 @@ export const authRouter = createTRPCRouter({
.input(apiCreateAdmin)
.mutation(async ({ ctx, input }) => {
try {
// if (!IS_CLOUD) {
const admin = await db.query.admins.findFirst({});
if (admin) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Admin already exists",
});
if (!IS_CLOUD) {
const admin = await db.query.admins.findFirst({});
if (admin) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Admin already exists",
});
}
}
// }
const newAdmin = await createAdmin(input);
const session = await lucia.createSession(newAdmin.id || "", {});

View File

@@ -6,6 +6,7 @@ import {
apiGenerateSSHKey,
apiRemoveSshKey,
apiUpdateSshKey,
sshKeys,
} from "@/server/db/schema";
import { TRPCError } from "@trpc/server";
import {
@@ -15,13 +16,17 @@ import {
removeSSHKeyById,
updateSSHKeyById,
} from "@dokploy/builders";
import { eq } from "drizzle-orm";
export const sshRouter = createTRPCRouter({
create: protectedProcedure
.input(apiCreateSshKey)
.mutation(async ({ input }) => {
.mutation(async ({ input, ctx }) => {
try {
await createSshKey(input);
await createSshKey({
...input,
adminId: ctx.user.adminId,
});
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
@@ -46,8 +51,10 @@ export const sshRouter = createTRPCRouter({
const sshKey = await findSSHKeyById(input.sshKeyId);
return sshKey;
}),
all: protectedProcedure.query(async () => {
return await db.query.sshKeys.findMany({});
all: protectedProcedure.query(async ({ ctx }) => {
return await db.query.sshKeys.findMany({
where: eq(sshKeys.adminId, ctx.user.adminId),
});
}),
generate: protectedProcedure
.input(apiGenerateSSHKey)

View File

@@ -1,11 +1,10 @@
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
import { findUserByAuthId, findUserById, findUsers } from "@dokploy/builders";
export const userRouter = createTRPCRouter({
all: adminProcedure.query(async () => {
return await findUsers();
all: adminProcedure.query(async ({ ctx }) => {
return await findUsers(ctx.user.adminId);
}),
byAuthId: protectedProcedure
.input(apiFindOneUserByAuth)

View File

@@ -7,6 +7,7 @@ import { auth } from "./auth";
import { registry } from "./registry";
import { certificateType } from "./shared";
import { users } from "./user";
import { sshKeys } from "./ssh-key";
export const admins = pgTable("admin", {
adminId: text("adminId")
@@ -35,6 +36,7 @@ export const adminsRelations = relations(admins, ({ one, many }) => ({
}),
users: many(users),
registry: many(registry),
sshKeys: many(sshKeys),
}));
const createSchema = createInsertSchema(admins, {

View File

@@ -6,6 +6,7 @@ import { pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { server } from "./server";
import { admins } from "./admin";
export const sshKeys = pgTable("ssh-key", {
sshKeyId: text("sshKeyId")
@@ -20,12 +21,19 @@ export const sshKeys = pgTable("ssh-key", {
.notNull()
.$defaultFn(() => new Date().toISOString()),
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),
compose: many(compose),
servers: many(server),
admin: one(admins, {
fields: [sshKeys.adminId],
references: [admins.adminId],
}),
}));
const createSchema = createInsertSchema(
@@ -40,6 +48,7 @@ export const apiCreateSshKey = createSchema
description: true,
privateKey: true,
publicKey: true,
adminId: true,
})
.merge(sshKeyCreate.pick({ privateKey: true }));

View File

@@ -34,8 +34,9 @@ export const findUserByAuthId = async (authId: string) => {
return user;
};
export const findUsers = async () => {
const users = await db.query.users.findMany({
export const findUsers = async (adminId: string) => {
const currentUsers = await db.query.users.findMany({
where: eq(users.adminId, adminId),
with: {
auth: {
columns: {
@@ -44,7 +45,7 @@ export const findUsers = async () => {
},
},
});
return users;
return currentUsers;
};
export const addNewProject = async (authId: string, projectId: string) => {