mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-30 19:45:23 +02:00
- Introduced new test files for permission checks, including `check-permission.test.ts`, `enterprise-only-resources.test.ts`, `resolve-permissions.test.ts`, and `service-access.test.ts`. - Implemented permission checks in various components to ensure actions are gated by user permissions, including `ShowTraefikConfig`, `UpdateTraefikConfig`, `ShowVolumes`, `ShowDomains`, and others. - Enhanced the logic for displaying UI elements based on user permissions, ensuring that only authorized users can access or modify resources.
206 lines
5.2 KiB
TypeScript
206 lines
5.2 KiB
TypeScript
import {
|
|
createRegistry,
|
|
execAsyncRemote,
|
|
execFileAsync,
|
|
findRegistryById,
|
|
IS_CLOUD,
|
|
removeRegistry,
|
|
updateRegistry,
|
|
} from "@dokploy/server";
|
|
import { db } from "@dokploy/server/db";
|
|
import { TRPCError } from "@trpc/server";
|
|
import { eq } from "drizzle-orm";
|
|
import {
|
|
apiCreateRegistry,
|
|
apiFindOneRegistry,
|
|
apiRemoveRegistry,
|
|
apiTestRegistry,
|
|
apiTestRegistryById,
|
|
apiUpdateRegistry,
|
|
registry,
|
|
} from "@/server/db/schema";
|
|
import { audit } from "@/server/api/utils/audit";
|
|
import { createTRPCRouter, withPermission } from "../trpc";
|
|
export const registryRouter = createTRPCRouter({
|
|
create: withPermission("registry", "create")
|
|
.input(apiCreateRegistry)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const reg = await createRegistry(input, ctx.session.activeOrganizationId);
|
|
await audit(ctx, {
|
|
action: "create",
|
|
resourceType: "registry",
|
|
resourceId: reg.registryId,
|
|
resourceName: reg.registryName,
|
|
});
|
|
return reg;
|
|
}),
|
|
remove: withPermission("registry", "delete")
|
|
.input(apiRemoveRegistry)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const registry = await findRegistryById(input.registryId);
|
|
if (registry.organizationId !== ctx.session.activeOrganizationId) {
|
|
throw new TRPCError({
|
|
code: "UNAUTHORIZED",
|
|
message: "You are not allowed to delete this registry",
|
|
});
|
|
}
|
|
await audit(ctx, {
|
|
action: "delete",
|
|
resourceType: "registry",
|
|
resourceId: registry.registryId,
|
|
resourceName: registry.registryName,
|
|
});
|
|
return await removeRegistry(input.registryId);
|
|
}),
|
|
update: withPermission("registry", "create")
|
|
.input(apiUpdateRegistry)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const { registryId, ...rest } = input;
|
|
const registry = await findRegistryById(registryId);
|
|
if (registry.organizationId !== ctx.session.activeOrganizationId) {
|
|
throw new TRPCError({
|
|
code: "UNAUTHORIZED",
|
|
message: "You are not allowed to update this registry",
|
|
});
|
|
}
|
|
const application = await updateRegistry(registryId, {
|
|
...rest,
|
|
});
|
|
|
|
if (!application) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: "Error updating registry",
|
|
});
|
|
}
|
|
|
|
await audit(ctx, {
|
|
action: "update",
|
|
resourceType: "registry",
|
|
resourceId: registryId,
|
|
resourceName: registry.registryName,
|
|
});
|
|
return true;
|
|
}),
|
|
all: withPermission("registry", "read").query(async ({ ctx }) => {
|
|
const registryResponse = await db.query.registry.findMany({
|
|
where: eq(registry.organizationId, ctx.session.activeOrganizationId),
|
|
});
|
|
return registryResponse;
|
|
}),
|
|
one: withPermission("registry", "read")
|
|
.input(apiFindOneRegistry)
|
|
.query(async ({ input, ctx }) => {
|
|
const registry = await findRegistryById(input.registryId);
|
|
if (registry.organizationId !== ctx.session.activeOrganizationId) {
|
|
throw new TRPCError({
|
|
code: "UNAUTHORIZED",
|
|
message: "You are not allowed to access this registry",
|
|
});
|
|
}
|
|
return registry;
|
|
}),
|
|
testRegistry: withPermission("registry", "read")
|
|
.input(apiTestRegistry)
|
|
.mutation(async ({ input }) => {
|
|
try {
|
|
const args = [
|
|
"login",
|
|
input.registryUrl,
|
|
"--username",
|
|
input.username,
|
|
"--password-stdin",
|
|
];
|
|
|
|
if (IS_CLOUD && !input.serverId) {
|
|
throw new TRPCError({
|
|
code: "NOT_FOUND",
|
|
message: "Select a server to test the registry",
|
|
});
|
|
}
|
|
|
|
if (input.serverId && input.serverId !== "none") {
|
|
await execAsyncRemote(
|
|
input.serverId,
|
|
`echo ${input.password} | docker ${args.join(" ")}`,
|
|
);
|
|
} else {
|
|
await execFileAsync("docker", args, {
|
|
input: Buffer.from(input.password).toString(),
|
|
});
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message:
|
|
error instanceof Error
|
|
? error.message
|
|
: "Error testing the registry",
|
|
cause: error,
|
|
});
|
|
}
|
|
}),
|
|
testRegistryById: withPermission("registry", "read")
|
|
.input(apiTestRegistryById)
|
|
.mutation(async ({ input, ctx }) => {
|
|
try {
|
|
const registryData = await db.query.registry.findFirst({
|
|
where: eq(registry.registryId, input.registryId ?? ""),
|
|
});
|
|
|
|
if (!registryData) {
|
|
throw new TRPCError({
|
|
code: "NOT_FOUND",
|
|
message: "Registry not found",
|
|
});
|
|
}
|
|
|
|
if (registryData.organizationId !== ctx.session.activeOrganizationId) {
|
|
throw new TRPCError({
|
|
code: "UNAUTHORIZED",
|
|
message: "You are not allowed to test this registry",
|
|
});
|
|
}
|
|
|
|
const args = [
|
|
"login",
|
|
registryData.registryUrl,
|
|
"--username",
|
|
registryData.username,
|
|
"--password-stdin",
|
|
];
|
|
|
|
if (IS_CLOUD && !input.serverId) {
|
|
throw new TRPCError({
|
|
code: "NOT_FOUND",
|
|
message: "Select a server to test the registry",
|
|
});
|
|
}
|
|
|
|
if (input.serverId && input.serverId !== "none") {
|
|
await execAsyncRemote(
|
|
input.serverId,
|
|
`echo ${registryData.password} | docker ${args.join(" ")}`,
|
|
);
|
|
} else {
|
|
await execFileAsync("docker", args, {
|
|
input: Buffer.from(registryData.password).toString(),
|
|
});
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message:
|
|
error instanceof Error
|
|
? error.message
|
|
: "Error testing the registry",
|
|
cause: error,
|
|
});
|
|
}
|
|
}),
|
|
});
|